CCSprite的类型触发切换Assem
fillType : {
get () {
return this._fillType;
},
set (value) {
if (value !== this._fillType) {
this._fillType = value;
this.setVertsDirty();
this._resetAssembler();
}
},
type: FillType,
tooltip: CC_DEV && 'i18n:COMPONENT.sprite.fill_type'
},
_resetAssembler () {
Assembler.init(this);
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
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) {
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) {
verts[vertexOffset] = vl + tx;
verts[vertexOffset + 1] = vb + ty;
vertexOffset += floatsPerVert;
verts[vertexOffset] = vr + tx;
verts[vertexOffset + 1] = vb + ty;
vertexOffset += floatsPerVert;
verts[vertexOffset] = vl + tx;
verts[vertexOffset + 1] = vt + ty;
vertexOffset += floatsPerVert;
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;
verts[vertexOffset] = al + cb + tx;
verts[vertexOffset + 1] = bl + db + ty;
vertexOffset += floatsPerVert;
verts[vertexOffset] = ar + cb + tx;
verts[vertexOffset + 1] = br + db + ty;
vertexOffset += floatsPerVert;
verts[vertexOffset] = al + ct + tx;
verts[vertexOffset + 1] = bl + dt + ty;
vertexOffset += floatsPerVert;
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);
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);
}
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) {
comp._vertsDirty = true;
comp._updateMaterial();
}
}
}
cc.js.addon(Assembler2D.prototype, {
floatsPerVert: 5,
verticesCount: 4,
indicesCount: 6,
uvOffset: 2,
colorOffset: 4,
});
cc.Assembler2D = Assembler2D;