1.需要修改引擎,参阅引擎定制工作流程
2.BITMAP缓存优化原理,参阅【乐府】突破Label的缓存模式之(1) BITMAP – Creator – Cocos中文社区
3.查看动态合图的api
运行时在console中输入
开启
cc.dynamicAtlasManager.showDebug(true);
关闭
cc.dynamicAtlasManager.showDebug(false);
4.修改记录
cocos2d/core/renderer/utils/label/ttf.js
_calDynamicAtlas (comp) {
if(comp.cacheMode !== Label.CacheMode.BITMAP) return;
let frame = comp._frame;
// Delete cache in atlas.
// mrlizs
// deleteFromDynamicAtlas(comp, frame);
if (!frame._original) {
frame.setRect(cc.rect(0, 0, _canvas.width, _canvas.height));
}
// mrlizs
// 给frame的texture计算一个新的_uuid值
frame._texture._uuid = comp.string + "_" + comp.node.color + "_" + comp.fontSize + comp.fontFamily;
this.packToDynamicAtlas(comp, frame);
}
cocos2d/core/renderer/utils/utils.js
deleteFromDynamicAtlas (comp, frame) {
if (frame && !CC_TEST) {
if (frame._original && dynamicAtlasManager) {
// mrlizs
// dynamicAtlasManager.deleteAtlasSpriteFrame(frame);
frame._resetDynamicAtlasFrame();
}
}
}
cocos2d/core/renderer/utils/dynamic-atlas/atlas.js
insertSpriteFrame (spriteFrame) {
let rect = spriteFrame._rect,
texture = spriteFrame._texture;
// mrlizs
// info = this._innerTextureInfos[texture._id];
// 在这里通过_uuid来判断重用性
// this._dynamicTextureRect 增加的一个字典用来记录uuid与texture的映射关系
let info = this._dynamicTextureRect[texture._uuid];
let sx = rect.x, sy = rect.y;
if (info) {
sx += info.x;
sy += info.y;
}
else {
let width = texture.width, height = texture.height;
if ((this._x + width + space) > this._width) {
this._x = space;
this._y = this._nexty;
}
if ((this._y + height + space) > this._nexty) {
this._nexty = this._y + height + space;
}
if (this._nexty > this._height) {
return null;
}
// texture bleeding
if (cc.dynamicAtlasManager.textureBleeding) {
// Smaller frame is more likely to be affected by linear filter
if (width <= 8 || height <= 8) {
this._texture.drawTextureAt(texture, this._x-1, this._y-1);
this._texture.drawTextureAt(texture, this._x-1, this._y+1);
this._texture.drawTextureAt(texture, this._x+1, this._y-1);
this._texture.drawTextureAt(texture, this._x+1, this._y+1);
}
this._texture.drawTextureAt(texture, this._x-1, this._y);
this._texture.drawTextureAt(texture, this._x+1, this._y);
this._texture.drawTextureAt(texture, this._x, this._y-1);
this._texture.drawTextureAt(texture, this._x, this._y+1);
}
this._texture.drawTextureAt(texture, this._x, this._y);
this._innerTextureInfos[texture._id] = {
x: this._x,
y: this._y,
texture: texture
};
// mrlizs
this._dynamicTextureRect[texture._uuid] = {
x: this._x,
y: this._y
};
this._count++;
sx += this._x;
sy += this._y;
this._x += width + space;
this._dirty = true;
}
let frame = {
x: sx,
y: sy,
texture: this._texture
}
this._innerSpriteFrames.push(spriteFrame);
return frame;
},
// mrlizs
fetchSpriteFrame(spriteFrame) {
let texture = spriteFrame._texture;
let info = this._dynamicTextureRect[texture._uuid];
if (!info) {
return null;
}
let rect = spriteFrame._rect;
let sx = rect.x + info.x, sy = rect.y + info.y;
let frame = {
x: sx,
y: sy,
texture: this._texture
}
if (!this._innerSpriteFrames.includes(spriteFrame)) {
this._innerSpriteFrames.push(spriteFrame);
}
return frame;
},
deleteInnerTexture (texture) {
if (texture && this._innerTextureInfos[texture._id]) {
delete this._innerTextureInfos[texture._id];
// mrlizs
delete this._dynamicTextureRect[texture._uuid];
for(let i = 0, n = this._innerSpriteFrames.length; i < n; i++){
if (this._innerSpriteFrames[i]._texture._uuid == texture._uuid){
this._innerSpriteFrames.splice(i,1);
break;
}
}
this._count--;
}
}
cocos2d/core/renderer/utils/dynamic-atlas/manager.js
insertSpriteFrame(spriteFrame) {
if (CC_EDITOR) return null;
if (!_enabled || _atlasIndex === _maxAtlasCount ||
!spriteFrame || spriteFrame._original) return null;
if (!spriteFrame._texture.packable) return null;
// mrlizs
for (let i = 0, n = _atlases.length; i < n; i++) {
let atlas = _atlases[i];
// 如果能从当前图集中找到相同_uuid的图集块,则重用
let frame = atlas.fetchSpriteFrame(spriteFrame);
if (frame != null) return frame;
}
let atlas = _atlases[_atlasIndex];
if (!atlas) {
atlas = newAtlas();
}
let frame = atlas.insertSpriteFrame(spriteFrame);
if (!frame && _atlasIndex !== _maxAtlasCount) {
atlas = newAtlas();
return atlas.insertSpriteFrame(spriteFrame);
}
return frame;
}
5.效果
修改前,原引擎对label的缓存是在onEnable时都会把上一次已缓存的纹理清掉然后重新创建,而实际上动态合图里有大量重复的label纹理,运行cc.dynamicAtlasManager.showDebug(true);
时可以看到合图内容。
修改后,首先不再清掉动态合图里的缓存纹理,然后label的纹理会先去动态合图中找已经存在的图块,如果存在则复用,不存在再创建。
本文为原创文章,转载请注明出处!