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的纹理会先去动态合图中找已经存在的图块,如果存在则复用,不存在再创建。
|