296 lines
9.8 KiB
JavaScript
296 lines
9.8 KiB
JavaScript
let gfx = cc.gfx;
|
|
// 颜色去除 + 物件图集合批
|
|
var vfmtPosUvIndex = new gfx.VertexFormat([
|
|
{ name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
|
|
{ name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
|
|
{ name: "a_texture_idx", type: gfx.ATTR_TYPE_FLOAT32, num: 1 },
|
|
]);
|
|
|
|
// 仅物件图集合批
|
|
var vfmtPosUvColorIndex = new gfx.VertexFormat([
|
|
{ name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
|
|
{ name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
|
|
{ name: "a_texture_idx", type: gfx.ATTR_TYPE_FLOAT32, num: 1 },
|
|
{ name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true },
|
|
]);
|
|
|
|
export class TmoAssembler extends cc.Assembler {
|
|
init(comp) {
|
|
super.init(comp);
|
|
|
|
this._noColor = comp.isNoColor();
|
|
this.updateColor = this._noColor ? undefined : this.updateColorFunc;
|
|
|
|
this.uvOffset = 2;
|
|
this.colorOffset = 5;
|
|
this.textureIndexOffset = 4;
|
|
this.floatsPerVert = this._noColor ? 5 : 6;
|
|
|
|
this.indicesCount = 6;
|
|
this.verticesCount = 4;
|
|
|
|
this._renderData = new cc.RenderData();
|
|
this._renderData.init(this);
|
|
|
|
this.initLocal();
|
|
this.initData();
|
|
}
|
|
|
|
initLocal() {
|
|
this._local = [];
|
|
this._local.length = 4;
|
|
}
|
|
|
|
initData() {
|
|
let data = this._renderData;
|
|
data.createFlexData(0, this.verticesCount, this.indicesCount, this.getVfmt());
|
|
|
|
// 填充顶点索引信息
|
|
let indices = data.iDatas[0];
|
|
let count = indices.length / 6;
|
|
for (let i = 0, idx = 0; i < count; i++) {
|
|
let vertextID = i * 4;
|
|
indices[idx++] = vertextID;
|
|
indices[idx++] = vertextID + 1;
|
|
indices[idx++] = vertextID + 2;
|
|
indices[idx++] = vertextID + 1;
|
|
indices[idx++] = vertextID + 3;
|
|
indices[idx++] = vertextID + 2;
|
|
}
|
|
}
|
|
|
|
getBuffer() {
|
|
return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
|
|
}
|
|
|
|
getVfmt() {
|
|
return this._noColor ? vfmtPosUvIndex : vfmtPosUvColorIndex;
|
|
}
|
|
|
|
updateRenderData(sprite) {
|
|
this.packToDynamicAtlas(sprite, sprite._spriteFrame);
|
|
|
|
if (sprite._vertsDirty) {
|
|
this.updateUVs(sprite);
|
|
this.updateVerts(sprite);
|
|
this.updateTextureIdx(sprite);
|
|
sprite._vertsDirty = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 填充textureIndex数据
|
|
* @param {cc.Sprite} sprite
|
|
*/
|
|
updateTextureIdx(sprite) {
|
|
let textureIdx = sprite._textureIdx;
|
|
let verts = this._renderData.vDatas[0];
|
|
|
|
let verticesCount = this.verticesCount;
|
|
let floatsPerVert = this.floatsPerVert;
|
|
let textureIndexOffset = this.textureIndexOffset;
|
|
|
|
for (let i = 0; i < verticesCount; i++) {
|
|
let index = i * floatsPerVert + textureIndexOffset;
|
|
verts[index] = textureIdx;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
get verticesFloats() {
|
|
return this.verticesCount * this.floatsPerVert;
|
|
}
|
|
|
|
updateColorFunc(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;
|
|
}
|
|
}
|
|
|
|
updateWorldVerts(comp) {
|
|
if (CC_NATIVERENDERER) {
|
|
// 原生平台兼容代码 复制于jsb-engine.js中的cc.Assembler2D.prototype.updateWorldVerts
|
|
var local = this._local;
|
|
var verts = this._renderData.vDatas[0];
|
|
var vl = local[0],
|
|
vr = local[2],
|
|
vb = local[1],
|
|
vt = local[3];
|
|
var floatsPerVert = this.floatsPerVert;
|
|
var vertexOffset = 0; // left bottom
|
|
|
|
verts[vertexOffset] = vl;
|
|
verts[vertexOffset + 1] = vb;
|
|
vertexOffset += floatsPerVert; // right bottom
|
|
|
|
verts[vertexOffset] = vr;
|
|
verts[vertexOffset + 1] = vb;
|
|
vertexOffset += floatsPerVert; // left top
|
|
|
|
verts[vertexOffset] = vl;
|
|
verts[vertexOffset + 1] = vt;
|
|
vertexOffset += floatsPerVert; // right top
|
|
|
|
verts[vertexOffset] = vr;
|
|
verts[vertexOffset + 1] = vt;
|
|
} else {
|
|
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 && cc.dynamicAtlasManager && frame._texture.packable) {
|
|
let packedFrame = cc.dynamicAtlasManager.insertSpriteFrame(frame);
|
|
if (packedFrame) {
|
|
frame._setDynamicAtlasFrame(packedFrame);
|
|
}
|
|
}
|
|
let material = comp._materials[0];
|
|
if (!material) return;
|
|
|
|
if (material.getProperty('texture') !== frame._texture) {
|
|
// texture was packed to dynamic atlas, should update uvs
|
|
comp._vertsDirty = true;
|
|
comp._updateMaterial();
|
|
}
|
|
}
|
|
} |