creator RenderComponent 和 Assembler

简介: creator RenderComponent 和 Assembler

CCSprite的类型触发切换Assem

  fillType : {
    get () {
        return this._fillType;
    },
    set (value) {
        if (value !== this._fillType) {
            this._fillType = value;
            this.setVertsDirty();
            this._resetAssembler();// 属性的更新触发了assembler重置
        }
    },
    type: FillType,
    tooltip: CC_DEV && 'i18n:COMPONENT.sprite.fill_type'
},
  • CCRenderComponent.js
    _resetAssembler () {
        Assembler.init(this);// 会触发红心绑定Assembler
        this._updateColor();
        this.setVertsDirty();
    },

Assembler基类的实现

  • cocos2d\core\renderer\assembler.js
export default class Assembler {
    constructor () {
        this._extendNative && this._extendNative();
    }
    init (renderComp) {
        this._renderComp = renderComp;
    }
    updateRenderData (comp) {
    }
    fillBuffers (comp, renderer) {
    }
    getVfmt () {
        return vfmtPosUvColor;
    }
}
Assembler.init = function (renderComp) {
    let renderCompCtor = renderComp.constructor;
    let assemblerCtor =  renderCompCtor.__assembler__;
    while (!assemblerCtor) {
        renderCompCtor = renderCompCtor.$super;
        if (!renderCompCtor) {
            cc.warn(`Can not find assembler for render component : [${cc.js.getClassName(renderComp)}]`);
            return;
        }
        assemblerCtor =  renderCompCtor.__assembler__;
    }
    if (assemblerCtor.getConstructor) {
        assemblerCtor = assemblerCtor.getConstructor(renderComp);
    }
    if (!renderComp._assembler || renderComp._assembler.constructor !== assemblerCtor) {
        let assembler = assemblerPool.get(assemblerCtor);
        assembler.init(renderComp);
        renderComp._assembler = assembler;
    }
};

注册spriteAssembler的地方

  • cocos2d\core\renderer\webgl\assemblers\sprite\index.js

js

复制代码

import Simple3D from "./3d/simple";
import Sliced3D from "./3d/sliced";
let ctor = {
    getConstructor(sprite) {
        let is3DNode = sprite.node.is3DNode;
        let ctor = is3DNode ? Simple3D : Simple;
        switch (sprite.type) { // 根据不同的类型进行不同的assembler的获取
            case Type.SLICED:
                ctor = is3DNode ? Sliced3D : Sliced;
                break;
        }
        return ctor;
    },
};
Assembler.register(cc.Sprite, ctor);

Sprite使用的Simple

  • cocos2d\core\renderer\webgl\assemblers\sprite\2d\simple.js
import Assembler2D from '../../../../assembler-2d';
export default class SimpleSpriteAssembler extends Assembler2D {
    updateRenderData (sprite) {
        this.packToDynamicAtlas(sprite, sprite._spriteFrame);
        if (sprite._vertsDirty) {
            this.updateUVs(sprite);
            this.updateVerts(sprite);
            sprite._vertsDirty = false;
        }
    }
    updateUVs (sprite) {
        let uv = sprite._spriteFrame.uv;
        let uvOffset = this.uvOffset;
        let floatsPerVert = this.floatsPerVert;
        let verts = this._renderData.vDatas[0];
        for (let i = 0; i < 4; i++) {
            let srcOffset = i * 2;
            let dstOffset = floatsPerVert * i + uvOffset;
            verts[dstOffset] = uv[srcOffset];
            verts[dstOffset + 1] = uv[srcOffset + 1];
        }
    }
    updateVerts (sprite) {
        let node = sprite.node,
            cw = node.width, ch = node.height,
            appx = node.anchorX * cw, appy = node.anchorY * ch,
            l, b, r, t;
        if (sprite.trim) {
            l = -appx;
            b = -appy;
            r = cw - appx;
            t = ch - appy;
        }
        else {
            let frame = sprite.spriteFrame,
                ow = frame._originalSize.width, oh = frame._originalSize.height,
                rw = frame._rect.width, rh = frame._rect.height,
                offset = frame._offset,
                scaleX = cw / ow, scaleY = ch / oh;
            let trimLeft = offset.x + (ow - rw) / 2;
            let trimRight = offset.x - (ow - rw) / 2;
            let trimBottom = offset.y + (oh - rh) / 2;
            let trimTop = offset.y - (oh - rh) / 2;
            l = trimLeft * scaleX - appx;
            b = trimBottom * scaleY - appy;
            r = cw + trimRight * scaleX - appx;
            t = ch + trimTop * scaleY - appy;
        }
        let local = this._local;
        local[0] = l;
        local[1] = b;
        local[2] = r;
        local[3] = t;
        this.updateWorldVerts(sprite);
    }
}

Assembler2D

  • cocos2d\core\renderer\assembler-2d.js
import Assembler from './assembler';
import dynamicAtlasManager from './utils/dynamic-atlas/manager';
import RenderData from './webgl/render-data';
export default class Assembler2D extends Assembler {
    constructor () {
        super();
        this._renderData = new RenderData();
        this._renderData.init(this);
        this.initData();
        this.initLocal();
    }
    get verticesFloats () {
        return this.verticesCount * this.floatsPerVert;
    }
    initData () {
        let data = this._renderData;
        data.createQuadData(0, this.verticesFloats, this.indicesCount);
    }
    initLocal () {
        this._local = [];
        this._local.length = 4;
    }
    updateColor (comp, color) {
        let uintVerts = this._renderData.uintVDatas[0];
        if (!uintVerts) return;
        color = color != null ? color : comp.node.color._val;
        let floatsPerVert = this.floatsPerVert;
        let colorOffset = this.colorOffset;
        for (let i = colorOffset, l = uintVerts.length; i < l; i += floatsPerVert) {
            uintVerts[i] = color;
        }
    }
    getBuffer () {
        return cc.renderer._handle._meshBuffer;
    }
    updateWorldVerts (comp) {
        let local = this._local;
        let verts = this._renderData.vDatas[0];
        let matrix = comp.node._worldMatrix;
        let matrixm = matrix.m,
            a = matrixm[0], b = matrixm[1], c = matrixm[4], d = matrixm[5],
            tx = matrixm[12], ty = matrixm[13];
        let vl = local[0], vr = local[2],
            vb = local[1], vt = local[3];
        let floatsPerVert = this.floatsPerVert;
        let vertexOffset = 0;
        let justTranslate = a === 1 && b === 0 && c === 0 && d === 1;
        if (justTranslate) {
            // left bottom
            verts[vertexOffset] = vl + tx;
            verts[vertexOffset + 1] = vb + ty;
            vertexOffset += floatsPerVert;
            // right bottom
            verts[vertexOffset] = vr + tx;
            verts[vertexOffset + 1] = vb + ty;
            vertexOffset += floatsPerVert;
            // left top
            verts[vertexOffset] = vl + tx;
            verts[vertexOffset + 1] = vt + ty;
            vertexOffset += floatsPerVert;
            // right top
            verts[vertexOffset] = vr + tx;
            verts[vertexOffset + 1] = vt + ty;
        } else {
            let al = a * vl, ar = a * vr,
            bl = b * vl, br = b * vr,
            cb = c * vb, ct = c * vt,
            db = d * vb, dt = d * vt;
            // left bottom
            verts[vertexOffset] = al + cb + tx;
            verts[vertexOffset + 1] = bl + db + ty;
            vertexOffset += floatsPerVert;
            // right bottom
            verts[vertexOffset] = ar + cb + tx;
            verts[vertexOffset + 1] = br + db + ty;
            vertexOffset += floatsPerVert;
            // left top
            verts[vertexOffset] = al + ct + tx;
            verts[vertexOffset + 1] = bl + dt + ty;
            vertexOffset += floatsPerVert;
            // right top
            verts[vertexOffset] = ar + ct + tx;
            verts[vertexOffset + 1] = br + dt + ty;
        }
    }
    fillBuffers (comp, renderer) {
        if (renderer.worldMatDirty) {
            this.updateWorldVerts(comp);
        }
        let renderData = this._renderData;
        let vData = renderData.vDatas[0];
        let iData = renderData.iDatas[0];
        let buffer = this.getBuffer(renderer);
        let offsetInfo = buffer.request(this.verticesCount, this.indicesCount);
        // buffer data may be realloc, need get reference after request.
        // fill vertices
        let vertexOffset = offsetInfo.byteOffset >> 2,
            vbuf = buffer._vData;
        if (vData.length + vertexOffset > vbuf.length) {
            vbuf.set(vData.subarray(0, vbuf.length - vertexOffset), vertexOffset);
        } else {
            vbuf.set(vData, vertexOffset);
        }
        // fill indices
        let ibuf = buffer._iData,
            indiceOffset = offsetInfo.indiceOffset,
            vertexId = offsetInfo.vertexOffset;
        for (let i = 0, l = iData.length; i < l; i++) {
            ibuf[indiceOffset++] = vertexId + iData[i];
        }
    }
    packToDynamicAtlas (comp, frame) {
        if (CC_TEST) return;
        if (!frame._original && dynamicAtlasManager && frame._texture.packable && frame._texture.loaded) {
            let packedFrame = dynamicAtlasManager.insertSpriteFrame(frame);
            if (packedFrame) {
                frame._setDynamicAtlasFrame(packedFrame);
            }
        }
        let material = comp._materials[0];
        if (!material) return;
        if (material.getProperty('texture') !== frame._texture._texture) {
            // texture was packed to dynamic atlas, should update uvs
            comp._vertsDirty = true;
            comp._updateMaterial();
        }
    }
}
cc.js.addon(Assembler2D.prototype, {
    floatsPerVert: 5,
    verticesCount: 4,
    indicesCount: 6,
    uvOffset: 2,
    colorOffset: 4,
});
cc.Assembler2D = Assembler2D;
目录
相关文章
|
2月前
|
IDE 开发工具 C++
qt creator + vs2019编译记录
本文记录了作者在使用qt creator和vs2019编译项目时遇到的困难和解决方案,包括编译环境设置、qt creator编译脚本的成功案例、不带Ninja的编译脚本问题、错误示范以及相关参考链接。
qt creator + vs2019编译记录
|
5月前
Qt之HelloWord(Qt Creator 10)
Qt之HelloWord(Qt Creator 10)
|
5月前
|
C++
使用Qt Creator 出现的一些错误
使用Qt Creator 出现的一些错误
|
6月前
|
数据可视化 开发工具 C++
Qt Creator 界面
Qt Creator 界面
|
6月前
|
数据可视化 NoSQL 编译器
Qt Creator 新建项目
Qt Creator 新建项目
|
6月前
|
设计模式 索引
QT Creator概览
QT Creator概览
|
6月前
|
设计模式 数据可视化 编译器
【Qt】—— Qt Creator 创建项目
【Qt】—— Qt Creator 创建项目
119 0
|
设计模式 项目管理
Qt | 通过创建一个简单项目了解Qt Creator
手把手教你学会使用Qt Creator。
466 0
|
C++ 索引
1.2 Qt Creator简介
1.2 Qt Creator简介
1.2 Qt Creator简介