From 311adb9248bd23ed8fe5d282b8c1aa02b5d0cfba Mon Sep 17 00:00:00 2001 From: SmallMain Date: Tue, 21 Jun 2022 12:01:39 +0800 Subject: [PATCH 10/15] =?UTF-8?q?Spine=20=E7=BB=84=E4=BB=B6=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E7=BA=B9=E7=90=86=E6=B8=B2=E6=9F=93=E3=80=81?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=9B=BE=E9=9B=86=E3=80=81=E4=B8=8E=E5=85=B6?= =?UTF-8?q?=E5=AE=83=E7=BB=84=E4=BB=B6=E5=90=88=E6=89=B9=E3=80=81region=20?= =?UTF-8?q?=E6=8D=A2=E8=A3=85=E5=B9=B6=E5=A2=9E=E5=8A=A0=E6=8D=A2=E8=A3=85?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E7=9A=84=20API=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- engine/cocos2d/core/assets/CCSpriteFrame.js | 1 + .../core/renderer/webgl/mesh-buffer.js | 46 +++ engine/extensions/spine/Skeleton.js | 68 ++++- engine/extensions/spine/lib/spine.js | 14 +- engine/extensions/spine/skeleton-data.js | 114 ++++++- engine/extensions/spine/spine-assembler.js | 278 ++++++++++++++---- 6 files changed, 455 insertions(+), 66 deletions(-) diff --git a/engine/cocos2d/core/assets/CCSpriteFrame.js b/engine/cocos2d/core/assets/CCSpriteFrame.js index 37837bd..7038378 100644 --- a/engine/cocos2d/core/assets/CCSpriteFrame.js +++ b/engine/cocos2d/core/assets/CCSpriteFrame.js @@ -651,6 +651,7 @@ let SpriteFrame = cc.Class(/** @lends cc.SpriteFrame# */{ this._texture = this._original._texture; this._original = null; this._calculateUV(); + this.emit("_resetDynamicAtlasFrame"); }, _calculateUV () { diff --git a/engine/cocos2d/core/renderer/webgl/mesh-buffer.js b/engine/cocos2d/core/renderer/webgl/mesh-buffer.js index f8d300f..d0a998f 100644 --- a/engine/cocos2d/core/renderer/webgl/mesh-buffer.js +++ b/engine/cocos2d/core/renderer/webgl/mesh-buffer.js @@ -187,6 +187,52 @@ let MeshBuffer = cc.Class({ this.requestStatic(vertexCount, indiceCount); return this._offsetInfo; }, + + requestForSpine(vertexCount, indiceCount) { + if (this._batcher._buffer !== this) { + this._batcher._flush(); + this._batcher._buffer = this; + } + + this.requestStaticForSpine(vertexCount, indiceCount); + return this._offsetInfo; + }, + + requestStaticForSpine(vertexCount, indiceCount) { + + this.checkAndSwitchBuffer(vertexCount); + + let byteOffset = this.byteOffset + vertexCount * this._vertexBytes; + let indiceOffset = this.indiceOffset + indiceCount; + + let byteLength = this._vData.byteLength; + let indiceLength = this._iData.length; + if (byteOffset > byteLength || indiceOffset > indiceLength) { + while (byteLength < byteOffset || indiceLength < indiceOffset) { + this._initVDataCount *= 2; + this._initIDataCount *= 2; + + byteLength = this._initVDataCount * 4; + indiceLength = this._initIDataCount; + } + + this._reallocBuffer(); + } + + let offsetInfo = this._offsetInfo; + offsetInfo.vertexOffset = this.vertexOffset; + offsetInfo.indiceOffset = this.indiceOffset; + offsetInfo.byteOffset = this.byteOffset; + }, + + adjustForSpine(vertexCount, indiceCount) { + this.vertexOffset += vertexCount; + this.indiceOffset += indiceCount; + + this.byteOffset = this.byteOffset + vertexCount * this._vertexBytes; + + this._dirty = true; + }, _reallocBuffer () { this._reallocVData(true); diff --git a/engine/extensions/spine/Skeleton.js b/engine/extensions/spine/Skeleton.js index da54c8c..42046fc 100644 --- a/engine/extensions/spine/Skeleton.js +++ b/engine/extensions/spine/Skeleton.js @@ -427,7 +427,16 @@ sp.Skeleton = cc.Class({ // Play times _playTimes : 0, // Is animation complete. - _isAniComplete : true, + _isAniComplete: true, + + autoSwitchMaterial: { + type: RenderComponent.EnableType, + default: RenderComponent.EnableType.GLOBAL, + }, + allowDynamicAtlas: { + type: RenderComponent.EnableType, + default: RenderComponent.EnableType.GLOBAL, + }, }, // CONSTRUCTOR @@ -443,6 +452,7 @@ sp.Skeleton = cc.Class({ this._startEntry = {animation : {name : ""}, trackIndex : 0}; this._endEntry = {animation : {name : ""}, trackIndex : 0}; this.attachUtil = new AttachUtil(); + this._dataDirty = true; }, // override base class _getDefaultMaterial to modify default material @@ -455,8 +465,11 @@ sp.Skeleton = cc.Class({ let useTint = this.useTint || (this.isAnimationCached() && !CC_NATIVERENDERER); let baseMaterial = this.getMaterial(0); if (baseMaterial) { - baseMaterial.define('USE_TINT', useTint); - baseMaterial.define('CC_USE_MODEL', !this.enableBatch); + const isMultiSupport = baseMaterial.material.isMultiSupport(); + if (!isMultiSupport) { + baseMaterial.define('USE_TINT', useTint); + baseMaterial.define('CC_USE_MODEL', !this.enableBatch); + } let srcBlendFactor = this.premultipliedAlpha ? cc.gfx.BLEND_ONE : cc.gfx.BLEND_SRC_ALPHA; let dstBlendFactor = cc.gfx.BLEND_ONE_MINUS_SRC_ALPHA; @@ -468,6 +481,11 @@ sp.Skeleton = cc.Class({ cc.gfx.BLEND_FUNC_ADD, dstBlendFactor, dstBlendFactor ); + + if (isMultiSupport) { + if (this.useTint) this.useTint = false; + if (!this.enableBatch) this.enableBatch = true; + } } this._materialCache = {}; }, @@ -493,7 +511,11 @@ sp.Skeleton = cc.Class({ let baseMaterial = this.getMaterial(0); if (baseMaterial) { let useTint = this.useTint || (this.isAnimationCached() && !CC_NATIVERENDERER); - baseMaterial.define('USE_TINT', useTint); + if (!baseMaterial.material.isMultiSupport()) { + baseMaterial.define('USE_TINT', useTint); + } else { + if (this.useTint) this.useTint = false; + } } this._materialCache = {}; }, @@ -502,7 +524,11 @@ sp.Skeleton = cc.Class({ _updateBatch () { let baseMaterial = this.getMaterial(0); if (baseMaterial) { - baseMaterial.define('CC_USE_MODEL', !this.enableBatch); + if (!baseMaterial.material.isMultiSupport()) { + baseMaterial.define('CC_USE_MODEL', !this.enableBatch); + } else { + if (!this.enableBatch) this.enableBatch = true; + } } this._materialCache = {}; }, @@ -955,6 +981,37 @@ sp.Skeleton = cc.Class({ this.invalidAnimationCache(); }, + /** + * 获取 attachment 的 region + */ + getRegion(slotName, attachmentName) { + const attachment = this.getAttachment(slotName, attachmentName); + if (attachment) { + return attachment.region; + } + return null; + }, + + /** + * 修改 attachment 的 region + */ + setRegion(slotName, attachmentName, region) { + const attachment = this.getAttachment(slotName, attachmentName); + if (attachment) { + attachment.region = region; + if (attachment instanceof sp.spine.MeshAttachment) { + attachment.updateUVs(); + } else if (attachment instanceof sp.spine.RegionAttachment) { + attachment.setRegion(region); + attachment.updateOffset(); + } + this._dataDirty = true; + this.invalidAnimationCache(); + return true; + } + return false; + }, + /** * Return the renderer of attachment. * @method getTextureAtlas @@ -1335,6 +1392,7 @@ sp.Skeleton = cc.Class({ this.attachUtil._associateAttachedNode(); this._preCacheMode = this._cacheMode; this.animation = this.defaultAnimation; + this._dataDirty = true; }, _refreshInspector () { diff --git a/engine/extensions/spine/lib/spine.js b/engine/extensions/spine/lib/spine.js index 857b433..fa12640 100644 --- a/engine/extensions/spine/lib/spine.js +++ b/engine/extensions/spine/lib/spine.js @@ -8004,7 +8004,7 @@ var spine; RegionAttachment.prototype.setRegion = function (region) { this.region = region; var uvs = this.uvs; - if (region.rotate) { + if (region.degrees === 90) { uvs[2] = region.u; uvs[3] = region.v2; uvs[4] = region.u; @@ -8013,8 +8013,16 @@ var spine; uvs[7] = region.v; uvs[0] = region.u2; uvs[1] = region.v2; - } - else { + } else if (region.degrees === 270) { + uvs[6] = region.u; + uvs[7] = region.v2; + uvs[0] = region.u; + uvs[1] = region.v; + uvs[2] = region.u2; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v2; + } else { uvs[0] = region.u; uvs[1] = region.v2; uvs[2] = region.u; diff --git a/engine/extensions/spine/skeleton-data.js b/engine/extensions/spine/skeleton-data.js index a7bdb10..9f233ed 100644 --- a/engine/extensions/spine/skeleton-data.js +++ b/engine/extensions/spine/skeleton-data.js @@ -139,6 +139,74 @@ let SkeletonData = cc.Class({ statics: { preventDeferredLoadDependents: true, + + createRegion(spriteFrame, original = undefined) { + const region = new sp.spine.TextureAtlasRegion(); + + const texture = spriteFrame.getTexture(); + const rect = spriteFrame.getRect(); + const origSize = spriteFrame.getOriginalSize(); + const _offset = spriteFrame.getOffset(); + const rotate = spriteFrame.isRotated(); + const offset = cc.v2( + (origSize.width - rect.width) * 0.5 + _offset.x, + (origSize.height - rect.height) * 0.5 + _offset.y, + ); + const degrees = rotate ? 270 : 0; + + if (original) { + region.name = original.name; + region.page = original.page; + } + + region.x = rect.x; + region.y = rect.y; + region.width = rect.width; + region.height = rect.height; + region.originalWidth = origSize.width; + region.originalHeight = origSize.height; + region.offsetX = offset.x; + region.offsetY = offset.y; + region.rotate = degrees != 0; + region.degrees = degrees; + + const skelTex = new sp.SkeletonTexture({ + width: texture.width, + height: texture.height, + }); + skelTex.setRealTexture(texture); + region.texture = skelTex; + + this.updateRegionUV(region); + + return region; + }, + + updateRegionUV(region) { + const texture = region.texture._texture; + if (region.rotate) { + region.u = region.x / texture.width; + region.v = region.y / texture.height; + region.u2 = (region.x + region.height) / texture.width; + region.v2 = (region.y + region.width) / texture.height; + } else { + region.u = region.x / texture.width; + region.v = region.y / texture.height; + region.u2 = (region.x + region.width) / texture.width; + region.v2 = (region.y + region.height) / texture.height; + } + }, + + createSpriteFrame(region) { + const frame = new cc.SpriteFrame( + region.texture._texture, + cc.rect(region.x, region.y, region.width, region.height), + region.rotate, // 如果 region 不是 0 或 270 则会出现问题 + cc.v2(region.offsetX - (region.originalWidth - region.width) * 0.5, region.offsetY - (region.originalHeight - region.height) * 0.5), + cc.size(region.originalWidth, region.originalHeight), + ); + return frame; + }, }, // PUBLIC @@ -166,6 +234,7 @@ let SkeletonData = cc.Class({ this._skinsEnum = null; this._animsEnum = null; } + this._cloneId = 0; }, ensureTexturesLoaded (loaded, caller) { @@ -322,7 +391,50 @@ let SkeletonData = cc.Class({ return this._atlasCache = new sp.spine.TextureAtlas(this.atlasText, this._getTexture.bind(this)); }, - destroy () { + /** + * 克隆 SkeletonData + */ + clone: function () { + const cloned = new SkeletonData(); + cloned._cloneId = this._cloneId + 1; + const suffix = '(clone ' + String(cloned._cloneId) + ')'; + cloned._uuid = this._uuid + suffix; + cloned.name = this.name + suffix; + cloned.scale = this.scale; + cloned.textureNames = this.textureNames; + cloned.textures = this.textures; + cloned._atlasText = this._atlasText; + cloned._skeletonJson = this._skeletonJson; + cloned._buffer = this._buffer; + + return cloned; + }, + + destroy() { + // 删除动态图集 + if (this._atlasCache) { + const regions = this._atlasCache.regions; + for (const region of regions) { + if (region._spriteFrame) { + region._spriteFrame.destroy(); + region._spriteFrame = null; + } + } + } + if (this._skeletonCache) { + const skins = this._skeletonCache.skins; + for (const skin of skins) { + for (const attachments of skin.attachments) { + for (const key in attachments) { + const region = attachments[key].region; + if (region && region._spriteFrame) { + region._spriteFrame.destroy(); + region._spriteFrame = null; + } + } + } + } + } SkeletonCache.removeSkeleton(this._uuid); this._super(); }, diff --git a/engine/extensions/spine/spine-assembler.js b/engine/extensions/spine/spine-assembler.js index 652af54..36c91f0 100644 --- a/engine/extensions/spine/spine-assembler.js +++ b/engine/extensions/spine/spine-assembler.js @@ -30,6 +30,7 @@ const spine = require('./lib/spine'); const RenderFlow = require('../../cocos2d/core/renderer/render-flow'); const VertexFormat = require('../../cocos2d/core/renderer/webgl/vertex-format') const VFOneColor = VertexFormat.vfmtPosUvColor; +const VFOneColorTexId = VertexFormat.vfmtPosUvColorTexId; const VFTwoColor = VertexFormat.vfmtPosUvTwoColor; const gfx = cc.gfx; @@ -58,6 +59,8 @@ let _multiplier; let _slotRangeStart; let _slotRangeEnd; let _useTint; +let _useMulti; +let _texId; let _debugSlots; let _debugBones; let _debugMesh; @@ -105,34 +108,67 @@ function _getSlotMaterial (tex, blendMode) { let baseMaterial = _comp._materials[0]; if (!baseMaterial) return null; - // The key use to find corresponding material - let key = tex.getId() + src + dst + _useTint + useModel; - let materialCache = _comp._materialCache; - let material = materialCache[key]; - if (!material) { - if (!materialCache.baseMaterial) { - material = baseMaterial; - materialCache.baseMaterial = baseMaterial; - } else { - material = cc.MaterialVariant.create(baseMaterial); + if (_useMulti) { + let key = tex.getId() + src + dst; + let materialCache = _comp._materialCache; + let materialInfo = materialCache[key]; + if (!materialInfo) { + let texId = baseMaterial.material.getMultiHandler().getIndex(tex.getImpl()); + if (!materialCache.baseMaterial) { + materialInfo = { material: baseMaterial, texId: texId }; + materialCache.baseMaterial = materialInfo; + } else { + materialInfo = { material: cc.MaterialVariant.create(baseMaterial), texId: texId }; + } + + if (texId === -1) { + materialInfo.material.setProperty('texture', tex); + materialInfo.texId = 0; + } + + // update blend function + materialInfo.material.setBlend( + true, + gfx.BLEND_FUNC_ADD, + src, dst, + gfx.BLEND_FUNC_ADD, + src, dst + ); + materialCache[key] = materialInfo; } - - material.define('CC_USE_MODEL', useModel); - material.define('USE_TINT', _useTint); - // update texture - material.setProperty('texture', tex); - - // update blend function - material.setBlend( - true, - gfx.BLEND_FUNC_ADD, - src, dst, - gfx.BLEND_FUNC_ADD, - src, dst - ); - materialCache[key] = material; + _texId = materialInfo.texId; + return materialInfo.material; + } else { + // The key use to find corresponding material + let key = tex.getId() + src + dst + _useTint + useModel; + let materialCache = _comp._materialCache; + let material = materialCache[key]; + if (!material) { + if (!materialCache.baseMaterial) { + material = baseMaterial; + materialCache.baseMaterial = baseMaterial; + } else { + material = cc.MaterialVariant.create(baseMaterial); + } + + material.define('CC_USE_MODEL', useModel); + material.define('USE_TINT', _useTint); + // update texture + material.setProperty('texture', tex); + + // update blend function + material.setBlend( + true, + gfx.BLEND_FUNC_ADD, + src, dst, + gfx.BLEND_FUNC_ADD, + src, dst + ); + materialCache[key] = material; + } + + return material; } - return material; } function _handleColor (color) { @@ -162,12 +198,112 @@ function _spineColorToInt32 (spineColor) { export default class SpineAssembler extends Assembler { updateRenderData (comp) { if (comp.isAnimationCached()) return; + + if (comp._dataDirty) { + // 自动合图 + this.packDynamicAtlasForSpine(comp); + + // 自动切换材质 + const autoSwitchMaterial = comp.autoSwitchMaterial; + if ((cc.sp.autoSwitchMaterial && autoSwitchMaterial === 0) || autoSwitchMaterial === 1) { + const material = comp._materials[0]; + if (!material) return false; + + const skins = comp.skeletonData._skeletonCache.skins; + for (const skin of skins) { + for (const attachment of skin.attachments) { + for (const key in attachment) { + const region = attachment[key].region; + if (region && region.texture) { + this.checkAndSwitchMaterial(comp, region.texture._texture, material); + break; + } + } + } + } + } + comp._dataDirty = false; + } + let skeleton = comp._skeleton; if (skeleton) { skeleton.updateWorldTransform(); } } + packDynamicAtlasForSpine(comp) { + if (CC_TEST) return false; + + const allowDynamicAtlas = comp.allowDynamicAtlas; + if ((cc.sp.allowDynamicAtlas && allowDynamicAtlas === 0) || allowDynamicAtlas === 1) { + if (cc.dynamicAtlasManager) { + const skins = comp.skeletonData._skeletonCache.skins; + for (const skin of skins) { + for (const attachments of skin.attachments) { + for (const key in attachments) { + const attachment = attachments[key]; + const region = attachment.region; + if (region && !region._original && region.texture && region.texture._texture.packable) { + if (region._spriteFrame) { + region._spriteFrame.destroy(); + region._spriteFrame = null; + } + const frame = sp.SkeletonData.createSpriteFrame(region); + const packedFrame = cc.dynamicAtlasManager.insertSpriteFrame(frame); + if (packedFrame) { + frame._setDynamicAtlasFrame(packedFrame); + + region._original = { + _texture: region.texture, + _x: region.x, + _y: region.y, + }; + + region.texture = new sp.SkeletonTexture({ + width: packedFrame.texture.width, + height: packedFrame.texture.height, + }); + region.texture.setRealTexture(packedFrame.texture); + + region.x = packedFrame.x; + region.y = packedFrame.y; + + // update uv + sp.SkeletonData.updateRegionUV(region); + if (attachment instanceof sp.spine.MeshAttachment) { + attachment.updateUVs(); + } else { + attachment.setRegion(region); + attachment.updateOffset(); + } + + frame.once("_resetDynamicAtlasFrame", () => { + region.x = region._original._x; + region.y = region._original._y; + region.texture = region._original._texture; + region._original = null; + + // update uv + sp.SkeletonData.updateRegionUV(region); + if (attachment instanceof sp.spine.MeshAttachment) { + attachment.updateUVs(); + } else { + attachment.setRegion(region); + attachment.updateOffset(); + } + }); + region._spriteFrame = frame; + } else { + frame.destroy(); + } + } + } + } + } + } + } + } + fillVertices (skeletonColor, attachmentColor, slotColor, clipper, slot) { let vbuf = _buffer._vData, @@ -207,16 +343,24 @@ export default class SpineAssembler extends Assembler { vbuf[v + 1] = _tempPos.y; // y vbuf[v + 2] = _tempUv.x; // u vbuf[v + 3] = _tempUv.y; // v - uintVData[v + 4] = _spineColorToInt32(_finalColor); // light color - _useTint && (uintVData[v + 5] = _spineColorToInt32(_darkColor)); // dark color + uintVData[v + 4] = _spineColorToInt32(_finalColor); // light color + if (_useMulti) { + vbuf[v + 5] = _texId; + } else { + _useTint && (uintVData[v + 5] = _spineColorToInt32(_darkColor)); // dark color + } } } else { _finalColor32 = _spineColorToInt32(_finalColor); _darkColor32 = _spineColorToInt32(_darkColor); for (let v = _vertexFloatOffset, n = _vertexFloatOffset + _vertexFloatCount; v < n; v += _perVertexSize) { - uintVData[v + 4] = _finalColor32; // light color - _useTint && (uintVData[v + 5] = _darkColor32); // dark color + uintVData[v + 4] = _finalColor32; // light color + if (_useMulti) { + vbuf[v + 5] = _texId; + } else { + _useTint && (uintVData[v + 5] = _darkColor32); // dark color + } } } } else { @@ -229,7 +373,7 @@ export default class SpineAssembler extends Assembler { _indexCount = clippedTriangles.length; _vertexFloatCount = clippedVertices.length / _perClipVertexSize * _perVertexSize; - offsetInfo = _buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + offsetInfo = _buffer.requestForSpine(_vertexFloatCount / _perVertexSize, _indexCount); _indexOffset = offsetInfo.indiceOffset, _vertexOffset = offsetInfo.vertexOffset, _vertexFloatOffset = offsetInfo.byteOffset >> 2; @@ -260,8 +404,12 @@ export default class SpineAssembler extends Assembler { vbuf[offset + 2] = _tempUv.x; // u vbuf[offset + 3] = _tempUv.y; // v uintVData[offset + 4] = _spineColorToInt32(_finalColor); - if (_useTint) { - uintVData[offset + 5] = _spineColorToInt32(_darkColor); + if (_useMulti) { + vbuf[offset + 5] = _texId; + } else { + if (_useTint) { + uintVData[offset + 5] = _spineColorToInt32(_darkColor); + } } } } else { @@ -273,10 +421,13 @@ export default class SpineAssembler extends Assembler { _finalColor32 = ((clippedVertices[v + 5]<<24) >>> 0) + (clippedVertices[v + 4]<<16) + (clippedVertices[v + 3]<<8) + clippedVertices[v + 2]; uintVData[offset + 4] = _finalColor32; - - if (_useTint) { - _darkColor32 = ((clippedVertices[v + 11]<<24) >>> 0) + (clippedVertices[v + 10]<<16) + (clippedVertices[v + 9]<<8) + clippedVertices[v + 8]; - uintVData[offset + 5] = _darkColor32; + if (_useMulti) { + vbuf[offset + 5] = _texId; + } else { + if (_useTint) { + _darkColor32 = ((clippedVertices[v + 11] << 24) >>> 0) + (clippedVertices[v + 10] << 16) + (clippedVertices[v + 9] << 8) + clippedVertices[v + 8]; + uintVData[offset + 5] = _darkColor32; + } } } } @@ -312,7 +463,7 @@ export default class SpineAssembler extends Assembler { } // x y u v r1 g1 b1 a1 r2 g2 b2 a2 or x y u v r g b a - _perClipVertexSize = _useTint ? 12 : 8; + _perClipVertexSize = _useMulti ? 12 : (_useTint ? 12 : 8); _vertexFloatCount = 0; _vertexFloatOffset = 0; @@ -384,7 +535,7 @@ export default class SpineAssembler extends Assembler { _vertexFloatCount = 4 * _perVertexSize; _indexCount = 6; - offsetInfo = _buffer.request(4, 6); + offsetInfo = _buffer.requestForSpine(4, 6); _indexOffset = offsetInfo.indiceOffset, _vertexOffset = offsetInfo.vertexOffset, _vertexFloatOffset = offsetInfo.byteOffset >> 2; @@ -413,7 +564,7 @@ export default class SpineAssembler extends Assembler { _vertexFloatCount = (attachment.worldVerticesLength >> 1) * _perVertexSize; _indexCount = triangles.length; - offsetInfo = _buffer.request(_vertexFloatCount / _perVertexSize, _indexCount); + offsetInfo = _buffer.requestForSpine(_vertexFloatCount / _perVertexSize, _indexCount); _indexOffset = offsetInfo.indiceOffset, _vertexOffset = offsetInfo.vertexOffset, _vertexFloatOffset = offsetInfo.byteOffset >> 2; @@ -485,7 +636,7 @@ export default class SpineAssembler extends Assembler { vbuf[ii + 1] = _x * _m01 + _y * _m05 + _m13; } } - _buffer.adjust(_vertexFloatCount / _perVertexSize, _indexCount); + _buffer.adjustForSpine(_vertexFloatCount / _perVertexSize, _indexCount); } clipper.clipEndWithSlot(slot); @@ -569,7 +720,7 @@ export default class SpineAssembler extends Assembler { _vertexCount = segInfo.vertexCount; _indexCount = segInfo.indexCount; - offsetInfo = _buffer.request(_vertexCount, _indexCount); + offsetInfo = _buffer.requestForSpine(_vertexCount, _indexCount); _indexOffset = offsetInfo.indiceOffset; _vertexOffset = offsetInfo.vertexOffset; _vfOffset = offsetInfo.byteOffset >> 2; @@ -599,19 +750,28 @@ export default class SpineAssembler extends Assembler { } } - _buffer.adjust(_vertexCount, _indexCount); - if ( !_needColor ) continue; + _buffer.adjustForSpine(_vertexCount, _indexCount); - // handle color - let frameColorOffset = frameVFOffset - segVFCount; - for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += 6, frameColorOffset += 6) { - if (frameColorOffset >= maxVFOffset) { - nowColor = colors[colorOffset++]; - _handleColor(nowColor); - maxVFOffset = nowColor.vfOffset; + if (_needColor) { + // handle color + let frameColorOffset = frameVFOffset - segVFCount; + for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += 6, frameColorOffset += 6) { + if (frameColorOffset >= maxVFOffset) { + nowColor = colors[colorOffset++]; + _handleColor(nowColor); + maxVFOffset = nowColor.vfOffset; + } + uintbuf[ii] = _finalColor32; + if (_useMulti) { + vbuf[ii + 1] = _texId; + } else { + uintbuf[ii + 1] = _darkColor32; + } + } + } else if (_useMulti) { + for (let ii = _vfOffset + 4, il = _vfOffset + 4 + segVFCount; ii < il; ii += 6) { + vbuf[ii + 1] = _texId; } - uintbuf[ii] = _finalColor32; - uintbuf[ii + 1] = _darkColor32; } } } @@ -628,13 +788,17 @@ export default class SpineAssembler extends Assembler { _nodeB = nodeColor.b / 255; _nodeA = nodeColor.a / 255; - _useTint = comp.useTint || comp.isAnimationCached(); - _vertexFormat = _useTint? VFTwoColor : VFOneColor; + let baseMaterial = comp._materials[0]; + if (!baseMaterial) return; + + _useMulti = baseMaterial.material.isMultiSupport(); + _useTint = !_useMulti && (comp.useTint || comp.isAnimationCached()); + _vertexFormat = _useMulti ? VFOneColorTexId : (_useTint ? VFTwoColor : VFOneColor); // x y u v color1 color2 or x y u v color - _perVertexSize = _useTint ? 6 : 5; + _perVertexSize = _useMulti ? 6 :(_useTint ? 6 : 5); _node = comp.node; - _buffer = renderer.getBuffer('spine', _vertexFormat); + _buffer = renderer.getBuffer('mesh', _vertexFormat); _renderer = renderer; _comp = comp; -- 2.32.0 (Apple Git-132)