From 4ed7dc52a22edfd8305d5c1c110c0e26979dcc84 Mon Sep 17 00:00:00 2001 From: David DeSimone Date: Tue, 13 Dec 2016 14:30:06 -0800 Subject: [PATCH 01/65] Porting CCGLProgramState to cocos2d-html5. This will now give the user the ability to bind multiple texture uniforms to a single shader program. It will also allow users to have late-bound uniforms via a callback. --- cocos2d/core/CCDrawingPrimitivesWebGL.js | 18 +- .../base-nodes/CCAtlasNodeWebGLRenderCmd.js | 3 +- cocos2d/core/base-nodes/CCNode.js | 8 + .../core/base-nodes/CCNodeCanvasRenderCmd.js | 26 +- .../core/base-nodes/CCNodeWebGLRenderCmd.js | 22 +- cocos2d/core/layers/CCLayerWebGLRenderCmd.js | 6 +- cocos2d/core/platform/CCMacro.js | 2 +- cocos2d/core/renderer/RendererWebGL.js | 18 +- cocos2d/core/textures/TexturesWebGL.js | 6 +- cocos2d/effects/CCGrid.js | 8 +- .../CCMotionStreakWebGLRenderCmd.js | 3 +- .../CCParticleBatchNodeWebGLRenderCmd.js | 3 +- .../CCParticleSystemWebGLRenderCmd.js | 3 +- .../CCPhysicsDebugNodeWebGLRenderCmd.js | 3 +- .../CCProgressTimerWebGLRenderCmd.js | 2 +- cocos2d/shaders/CCGLProgram.js | 16 +- cocos2d/shaders/CCGLProgramState.js | 325 ++++++++++++++++++ .../shape-nodes/CCDrawNodeWebGLRenderCmd.js | 3 +- moduleConfig.json | 1 + 19 files changed, 417 insertions(+), 59 deletions(-) create mode 100644 cocos2d/shaders/CCGLProgramState.js diff --git a/cocos2d/core/CCDrawingPrimitivesWebGL.js b/cocos2d/core/CCDrawingPrimitivesWebGL.js index f8c9b46d0d..e6fc9b7262 100644 --- a/cocos2d/core/CCDrawingPrimitivesWebGL.js +++ b/cocos2d/core/CCDrawingPrimitivesWebGL.js @@ -81,7 +81,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# this.lazy_init(); var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); @@ -110,7 +110,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# this.lazy_init(); var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); @@ -145,7 +145,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# this.lazy_init(); var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); @@ -200,7 +200,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# this.lazy_init(); var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); @@ -231,7 +231,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# this.setDrawColor(color.r, color.g, color.b, color.a); var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); @@ -279,7 +279,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# vertices[(segments + 1) * 2 + 1] = center.y; var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); @@ -317,7 +317,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# vertices[segments * 2 + 1] = destination.y; var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); @@ -356,7 +356,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# vertices[segments * 2 + 1] = destination.y; var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); @@ -416,7 +416,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# } var glContext = this._renderContext; - this._shader.use(); + this._glProgramState.apply(); this._shader.setUniformForModelViewAndProjectionMatrixWithMat4(); glContext.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); this._shader.setUniformLocationWith4fv(this._colorLocation, this._colorArray); diff --git a/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js index 8fce00f8da..5810d00794 100644 --- a/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js +++ b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js @@ -68,8 +68,7 @@ this._matrix.mat[5] = wt.d; this._matrix.mat[13] = wt.ty; - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); + this._glProgramState.apply(this._matrix); cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst); if (this._uniformColor && this._colorF32Array) { diff --git a/cocos2d/core/base-nodes/CCNode.js b/cocos2d/core/base-nodes/CCNode.js index 4f05484c47..50068dbbef 100644 --- a/cocos2d/core/base-nodes/CCNode.js +++ b/cocos2d/core/base-nodes/CCNode.js @@ -2228,6 +2228,14 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ this._renderCmd.setShaderProgram(newShaderProgram); }, + setGLProgramState: function (glProgramState) { + this._renderCmd.setGLProgramState(glProgramState); + }, + + getGLProgramState: function () { + return this._renderCmd.getGLProgramState(); + }, + /** * Returns the state of OpenGL server side. * @function diff --git a/cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js b/cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js index 49308ef008..b7e53eaf39 100644 --- a/cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js +++ b/cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js @@ -513,7 +513,23 @@ cc.Node.RenderCmd.prototype = { if (locFlag & dirtyFlags.orderDirty) this._dirtyFlag &= ~dirtyFlags.orderDirty; - } + }, + + setShaderProgram: function (shaderProgram) { + //do nothing. + }, + + getShaderProgram: function () { + return null; + }, + + getGLProgramState: function () { + return null; + }, + + setGLProgramState: function (glProgramState) { + // do nothing + }, }; cc.Node.RenderCmd.prototype.originTransform = cc.Node.RenderCmd.prototype.transform; @@ -607,14 +623,6 @@ cc.Node.RenderCmd.prototype._originSyncStatus = cc.Node.RenderCmd.prototype._syn } }; - proto.setShaderProgram = function (shaderProgram) { - //do nothing. - }; - - proto.getShaderProgram = function () { - return null; - }; - //util functions cc.Node.CanvasRenderCmd._getCompositeOperationByBlendFunc = function (blendFunc) { if (!blendFunc) diff --git a/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js b/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js index 62e469800e..68a3968b90 100644 --- a/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js +++ b/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js @@ -27,7 +27,7 @@ this._node = renderable; this._anchorPointInPoints = {x: 0, y: 0}; this._displayedColor = cc.color(255, 255, 255, 255); - this._shaderProgram = null; + this._glProgramState = null; }; var proto = cc.Node.WebGLRenderCmd.prototype = Object.create(cc.Node.RenderCmd.prototype); @@ -38,10 +38,26 @@ }; proto.setShaderProgram = function (shaderProgram) { - this._shaderProgram = shaderProgram; + this._glProgramState = cc.GLProgramState.getOrCreateWithGLProgram(shaderProgram); }; proto.getShaderProgram = function () { - return this._shaderProgram; + return this._glProgramState ? this._glProgramState.getGLProgram() : null; }; + + proto.getGLProgramState = function () { + return this._glProgramState; + }; + + proto.setGLProgramState = function (glProgramState) { + this._glProgramState = glProgramState; + }; + + // Use a property getter/setter for backwards compatability, and + // to ease the transition from using glPrograms directly, to + // using glProgramStates. + Object.defineProperty(proto, '_shaderProgram', { + set: function () { this.setShaderProgram.apply(this, arguments); }, + get: function () { return this.getShaderProgram(); } + }); })(); diff --git a/cocos2d/core/layers/CCLayerWebGLRenderCmd.js b/cocos2d/core/layers/CCLayerWebGLRenderCmd.js index ea60a3c70f..a18dd6f9fc 100644 --- a/cocos2d/core/layers/CCLayerWebGLRenderCmd.js +++ b/cocos2d/core/layers/CCLayerWebGLRenderCmd.js @@ -97,8 +97,7 @@ this._matrix.mat[5] = wt.d; this._matrix.mat[13] = wt.ty; - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); + this._glProgramState.apply(this._matrix); context.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); context.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR); cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst); @@ -311,8 +310,7 @@ this._matrix.mat[13] = wt.ty; //draw gradient layer - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); + this._glProgramState.apply(this._matrix); context.enableVertexAttribArray(cc.VERTEX_ATTRIB_POSITION); context.enableVertexAttribArray(cc.VERTEX_ATTRIB_COLOR); cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst); diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js index e5e4e3c609..71a367618a 100644 --- a/cocos2d/core/platform/CCMacro.js +++ b/cocos2d/core/platform/CCMacro.js @@ -175,7 +175,7 @@ cc.nodeDrawSetup = function (node) { //cc.glEnable(node._glServerState); if (node._shaderProgram) { //cc._renderContext.useProgram(node._shaderProgram._programObj); - node._shaderProgram.use(); + node._glProgramState.apply(); node._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); } }; diff --git a/cocos2d/core/renderer/RendererWebGL.js b/cocos2d/core/renderer/RendererWebGL.js index 593a4434ef..38f6ce4f66 100644 --- a/cocos2d/core/renderer/RendererWebGL.js +++ b/cocos2d/core/renderer/RendererWebGL.js @@ -33,8 +33,8 @@ var _batchedInfo = { blendSrc: null, // The batched blend destination, all batching element should have the same blend destination blendDst: null, - // The batched shader, all batching element should have the same shader - shader: null + // The batched glProgramState, all batching element should have the same glProgramState + glProgramState: null }, _quadIndexBuffer = null, @@ -280,18 +280,18 @@ return { } var blendSrc = node._blendFunc.src; var blendDst = node._blendFunc.dst; - var shader = cmd._shaderProgram; + var glProgramState = cmd._glProgramState; if (_batchedInfo.texture !== texture || _batchedInfo.blendSrc !== blendSrc || _batchedInfo.blendDst !== blendDst || - _batchedInfo.shader !== shader) { + _batchedInfo.glProgramState !== glProgramState) { // Draw batched elements this._batchRendering(); // Update _batchedInfo _batchedInfo.texture = texture; _batchedInfo.blendSrc = blendSrc; _batchedInfo.blendDst = blendDst; - _batchedInfo.shader = shader; + _batchedInfo.glProgramState = glProgramState; } // Upload vertex data @@ -308,12 +308,12 @@ return { var gl = cc._renderContext; var texture = _batchedInfo.texture; - var shader = _batchedInfo.shader; + var glProgramState = _batchedInfo.glProgramState; var count = _batchingSize / 4; - if (shader) { - shader.use(); - shader._updateProjectionUniform(); + if (glProgramState) { + glProgramState.apply(); + glProgramState.getGLProgram()._updateProjectionUniform(); } cc.glBlendFunc(_batchedInfo.blendSrc, _batchedInfo.blendDst); diff --git a/cocos2d/core/textures/TexturesWebGL.js b/cocos2d/core/textures/TexturesWebGL.js index bcec5bfb53..49a33ae647 100644 --- a/cocos2d/core/textures/TexturesWebGL.js +++ b/cocos2d/core/textures/TexturesWebGL.js @@ -339,8 +339,7 @@ cc._tmp.WebGLTexture2D = function () { point.x, height + point.y, 0.0, width + point.x, height + point.y, 0.0]; - self._shaderProgram.use(); - self._shaderProgram.setUniformsForBuiltins(); + self._glProgramState.apply(); cc.glBindTexture2D(self); @@ -369,8 +368,7 @@ cc._tmp.WebGLTexture2D = function () { rect.x, rect.y + rect.height, /*0.0,*/ rect.x + rect.width, rect.y + rect.height /*0.0*/]; - self._shaderProgram.use(); - self._shaderProgram.setUniformsForBuiltins(); + self._glProgramState.apply(); cc.glBindTexture2D(self); diff --git a/cocos2d/effects/CCGrid.js b/cocos2d/effects/CCGrid.js index f6459a2269..84e08be6af 100644 --- a/cocos2d/effects/CCGrid.js +++ b/cocos2d/effects/CCGrid.js @@ -443,9 +443,7 @@ cc.Grid3D = cc.GridBase.extend(/** @lends cc.Grid3D# */{ this._matrix.mat[5] = wt.d; this._matrix.mat[13] = wt.ty; - this._shaderProgram.use(); - //this._shaderProgram.setUniformsForBuiltins(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); + this._glProgramState.apply(this._matrix); var gl = cc._renderContext, locDirty = this._dirty; @@ -714,9 +712,7 @@ cc.TiledGrid3D = cc.GridBase.extend(/** @lends cc.TiledGrid3D# */{ this._matrix.mat[5] = wt.d; this._matrix.mat[13] = wt.ty; - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); - //this._shaderProgram.setUniformsForBuiltins(); + this._glProgramState.apply(this._matrix); // // Attributes diff --git a/cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js b/cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js index e2d74f574a..a7d793a336 100644 --- a/cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js +++ b/cocos2d/motion-streak/CCMotionStreakWebGLRenderCmd.js @@ -49,8 +49,7 @@ cc.MotionStreak.WebGLRenderCmd.prototype.rendering = function (ctx) { this._matrix.mat[5] = wt.d; this._matrix.mat[13] = wt.ty; - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); + this._glProgramState.apply(this._matrix); cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst); cc.glBindTexture2D(node.texture); diff --git a/cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js b/cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js index 3dda639728..765e7553ad 100644 --- a/cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js +++ b/cocos2d/particle/CCParticleBatchNodeWebGLRenderCmd.js @@ -49,8 +49,7 @@ this._matrix.mat[5] = wt.d; this._matrix.mat[13] = wt.ty; - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); + this._glProgramState.apply(this._matrix); cc.glBlendFuncForParticle(_t._blendFunc.src, _t._blendFunc.dst); _t.textureAtlas.drawQuads(); }; diff --git a/cocos2d/particle/CCParticleSystemWebGLRenderCmd.js b/cocos2d/particle/CCParticleSystemWebGLRenderCmd.js index 892f8a2d21..54b1236119 100644 --- a/cocos2d/particle/CCParticleSystemWebGLRenderCmd.js +++ b/cocos2d/particle/CCParticleSystemWebGLRenderCmd.js @@ -204,8 +204,7 @@ this._matrix.mat[5] = wt.d; this._matrix.mat[13] = wt.ty; - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); //; + this._glProgramState.apply(this._matrix); cc.glBindTexture2D(node._texture); cc.glBlendFuncForParticle(node._blendFunc.src, node._blendFunc.dst); diff --git a/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js b/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js index 1c2a9fb69a..0b8a18504c 100644 --- a/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js +++ b/cocos2d/physics/CCPhysicsDebugNodeWebGLRenderCmd.js @@ -54,8 +54,7 @@ //cc.DrawNode.prototype.draw.call(node); cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst); - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); + this._glProgramState.apply(this._matrix); node._render(); node.clear(); diff --git a/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js b/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js index 8ee5a7da1a..c78b0d5f9d 100644 --- a/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js +++ b/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js @@ -64,7 +64,7 @@ if (this._vertexDataCount === 0 || !node._sprite) return; - this._shaderProgram.use(); + this._glProgramState.apply(); this._shaderProgram._updateProjectionUniform(); var blendFunc = node._sprite._blendFunc; diff --git a/cocos2d/shaders/CCGLProgram.js b/cocos2d/shaders/CCGLProgram.js index d9e59b109d..c7c191fa76 100644 --- a/cocos2d/shaders/CCGLProgram.js +++ b/cocos2d/shaders/CCGLProgram.js @@ -116,6 +116,7 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ ctor: function (vShaderFileName, fShaderFileName, glContext) { this._uniforms = {}; this._hashForUniforms = {}; + this._userUniforms = {}; this._glContext = glContext || cc._renderContext; vShaderFileName && fShaderFileName && this.init(vShaderFileName, fShaderFileName); @@ -231,7 +232,8 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ } this._glContext.linkProgram(this._programObj); - + this._parseUniforms(); + if (this._vertShader) this._glContext.deleteShader(this._vertShader); if (this._fragShader) @@ -253,6 +255,18 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ return true; }, + _parseUniforms: function _parseUniforms() { + var activeUniforms = this._glContext.getProgramParameter(this._programObj, this._glContext.ACTIVE_UNIFORMS); + for (var i = 0; i < activeUniforms; ++i) { + var uniform = this._glContext.getActiveUniform(this._programObj, i); + uniform.location = this._glContext.getUniformLocation(this._programObj, uniform.name); + if (uniform.name.indexOf("CC_") !== 0) { + uniform.location = this._glContext.getUniformLocation(this._programObj, uniform.name); + uniform.name = uniform.name.replace("[]", ""); + this._userUniforms[uniform.name] = uniform; + } + } + }, /** * it will call glUseProgram() */ diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js new file mode 100644 index 0000000000..6457d180fb --- /dev/null +++ b/cocos2d/shaders/CCGLProgramState.js @@ -0,0 +1,325 @@ +/**************************************************************************** + Copyright (c) 2008-2010 Ricardo Quesada + Copyright (c) 2011-2012 cocos2d-x.org + Copyright (c) 2013-2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +// @TODO add floatv and intv methods, that take arrays +// and float1..4 methods, which take arguments. + +var types = + { + GL_FLOAT: 0, + GL_INT: 1, + GL_FLOAT_VEC2: 2, + GL_FLOAT_VEC3: 3, + GL_FLOAT_VEC4: 4, + GL_FLOAT_MAT4: 5, + GL_CALLBACK: 6, + GL_TEXTURE: 7 + }; + +cc.UniformValue = cc.Class.extend({ + _uniform: null, + _glprogram: null, + _value: null, + _type: -1, + + ctor: function ctor(uniform, glprogram) { + this._uniform = uniform; + this._glprogram = glprogram; + }, + + setFloat: function setFloat(value) { + this._value = value; + this._type = types.GL_FLOAT; + }, + + setInt: function setInt(value) { + this._value = value; + this._type = types.GL_INT; + }, + + setVec2: function setVec2(v1, v2) { + this._value = [v1, v2]; + this._type = types.GL_FLOAT_VEC2; + }, + + setVec2v: function setVec2v(value) { + this._value = value; + this._type = types.GL_FLOAT_VEC2; + }, + + setVec3: function setVec3(v1, v2, v3) { + this._value = [v1, v2, v3]; + this._type = types.GL_FLOAT_VEC3; + }, + + setVec3v: function setVec3v(value) { + this._value = value; + this._type = types.GL_FLOAT_VEC3; + }, + + setVec4: function setVec4(v1, v2, v3, v4) { + this._value = [v1, v2, v3, v4]; + this._type = types.GL_FLOAT_VEC4; + }, + + setVec4v: function setVec4v(value) { + this._value = value; + this._type = types.GL_FLOAT_VEC4; + }, + + setMat4: function setMat4(value) { + this._value = value; + this._type = types.GL_FLOAT_MAT4; + }, + + setCallback: function setCallback(fn) { + this._value = fn; + this._type = types.GL_CALLBACK; + }, + + setTexture: function setTexture(textureId, textureUnit) { + this._value = textureUnit; + this._textureId = textureId; + this._type = types.GL_TEXTURE; + }, + + apply: function apply() { + switch (this._type) { + case types.GL_INT: + this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); + break; + case types.GL_FLOAT: + this._glprogram.setUniformLocationWith1f(this._uniform.location, this._value); + break; + case types.GL_FLOAT_VEC2: + this._glprogram.setUniformLocationWith2f(this._uniform.location, this._value[0], this._value[1]); + break; + case types.GL_FLOAT_VEC3: + this._glprogram.setUniformLocationWith3f(this._uniform.location, this._value[0], + this._value[1], this._value[2]); + break; + case types.GL_FLOAT_VEC4: + this._glprogram.setUniformLocationWith3f(this._uniform.location, this._value[0], + this._value[1], this._value[2]); + break; + case types.GL_FLOAT_MAT4: + this._glprogram.setUniformLocationWithMatrix4fv(this._uniform.location, this._value); + break; + case types.GL_CALLBACK: + this._value(this._glprogram, this._uniform); + break; + case types.GL_TEXTURE: + this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); + cc.glBindTexture2DN(this._value, this._textureId); + break; + default: + cc.Assert(false, "Unsupported type"); + } + }, +}); + +cc.GLProgramState = cc.Class.extend({ + _glprogram: null, + _uniformsByName: null, + _uniformsByLocation: null, + _boundTextureUnits: null, + _textureUnitIndex: 0, + + init: function init(glprogram) { + this._glprogram = glprogram; + this._uniformsByName = {}; + this._uniformsByLocation = {}; + this._boundTextureUnits = {}; + this._textureUnitIndex = 1; // Start at 1, as CC_Texture0 is bound to 0 + var userUniformKeys = Object.keys(glprogram._userUniforms); + for (var i = 0; i < userUniformKeys.length; ++i) { + var uniform = glprogram._userUniforms[userUniformKeys[i]]; + var uniformValue = new cc.UniformValue(uniform, glprogram); + this._uniformsByName[uniform.name] = uniformValue; + this._uniformsByLocation[uniform.location] = uniformValue; + } + }, + + apply: function apply(modelView) { + this.applyGLProgram(modelView); + this.applyUniforms(); + }, + + applyGLProgram: function applyGLProgram(modelView) { + this._glprogram.use(); + if (modelView) { + this._glprogram._setUniformForMVPMatrixWithMat4(modelView); + } + }, + + applyUniforms: function applyUniforms() { + var uniformKeys = Object.keys(this._uniformsByName); + for (var i = 0; i < uniformKeys.length; ++i) { + var uniform = this._uniformsByName[uniformKeys[i]]; + uniform.apply(); + } + }, + + setGLProgram: function setGLProgram(glprogram) { + this._glprogram = glprogram; + }, + + getGLProgram: function getGLProgram() { + return this._glprogram; + }, + + getUniformCount: function getUniformCount() { + return Object.keys(this._uniformsByName).length; + }, + + getUniformValue: function getUniformValue(uniform) + { + if (typeof uniform === 'string') { + return this._uniformsByName[uniform]; + } else { + return this._uniformsByLocation[uniform]; + } + }, + + // Accepts either string or uniform location + setUniformInt: function setUniformInt(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setInt(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformFloat: function setUniformFloat(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setFloat(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec2: function setUniformVec2(uniform, v1, v2) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec2(v1, v2); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec2v: function setUniformVec2v(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec2v(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec3: function setUniformVec3(uniform, v1, v2, v3) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec3(v1, v2, v3); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec3v: function setUniformVec3v(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec3v(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec4: function setUniformVec4(uniform, v1, v2, v3, v4) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec4(v1, v2, v3, v4); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec4v: function setUniformVec4v(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec4v(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + + setUniformMat4: function setUniformMat4(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setMat4(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + + }, + + setUniformCallback: function setUniformCallback(uniform, callback) { + var v = this.getUniformValue(uniform); + if (v) { + v.setCallback(callback); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + + }, + + setUniformTexture: function setUniformTexture(uniform, texture) { + var uniformValue = this.getUniformValue(uniform); + if (uniformValue) { + var textureUnit = this._boundTextureUnits[uniform]; + if (textureUnit) { + uniformValue.setTexture(texture, textureUnit); + } else { + uniformValue.setTexture(texture, this._textureUnitIndex); + this._boundTextureUnits[uniform] = this._textureUnitIndex++; + } + } + } +}); + +cc.GLProgramState._cache = {}; +cc.GLProgramState.getOrCreateWithGLProgram = function (glprogram) { + var programState = cc.GLProgramState._cache[glprogram.__instanceId]; + if (!programState) { + programState = new cc.GLProgramState(); + programState.init(glprogram); + cc.GLProgramState._cache[glprogram.__instanceId] = programState; + } + + return programState; +}; diff --git a/cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js b/cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js index ef9d443c98..cd7ea5125c 100644 --- a/cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js +++ b/cocos2d/shape-nodes/CCDrawNodeWebGLRenderCmd.js @@ -45,8 +45,7 @@ this._matrix.mat[13] = wt.ty; cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst); - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); + this._glProgramState.apply(this._matrix); node._render(); } }; diff --git a/moduleConfig.json b/moduleConfig.json index 99e383e35f..ee6224df60 100644 --- a/moduleConfig.json +++ b/moduleConfig.json @@ -229,6 +229,7 @@ "cocos2d/shaders/CCShaders.js", "cocos2d/shaders/CCShaderCache.js", "cocos2d/shaders/CCGLProgram.js", + "cocos2d/shaders/CCGLProgramState.js", "cocos2d/shaders/CCGLStateCache.js" ], "shape-nodes" : [ From beee1dc96f0ba8181cee778aaab90752f2514535 Mon Sep 17 00:00:00 2001 From: David DeSimone Date: Tue, 13 Dec 2016 15:36:49 -0800 Subject: [PATCH 02/65] Fixing rendering issues in CCAtlastNodeWebGLRenderCmd and CCGrid. --- cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js | 6 ++---- cocos2d/effects/CCGrid.js | 6 +++--- cocos2d/shaders/CCGLProgramState.js | 9 +++------ 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js index 5810d00794..085e3770bb 100644 --- a/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js +++ b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js @@ -32,14 +32,12 @@ this._textureAtlas = null; this._colorUnmodified = cc.color.WHITE; this._colorF32Array = null; - this._uniformColor = null; this._matrix = new cc.math.Matrix4(); this._matrix.identity(); //shader stuff this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR); - this._uniformColor = cc._renderContext.getUniformLocation(this._shaderProgram.getProgram(), "u_color"); }; var proto = cc.AtlasNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype); @@ -71,8 +69,8 @@ this._glProgramState.apply(this._matrix); cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst); - if (this._uniformColor && this._colorF32Array) { - context.uniform4fv(this._uniformColor, this._colorF32Array); + if (this._colorF32Array) { + this._glProgramState.setUniformVec4v("u_color", this._colorF32Array); this._textureAtlas.drawNumberOfQuads(node.quadsToDraw, 0); } }; diff --git a/cocos2d/effects/CCGrid.js b/cocos2d/effects/CCGrid.js index 84e08be6af..361cba84b3 100644 --- a/cocos2d/effects/CCGrid.js +++ b/cocos2d/effects/CCGrid.js @@ -39,7 +39,7 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{ _step: null, _grabber: null, _isTextureFlipped: false, - _shaderProgram: null, + _glProgramState: null, _directorProjection: 0, _dirty: false, @@ -62,7 +62,7 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{ this._step = cc.p(0, 0); this._grabber = null; this._isTextureFlipped = false; - this._shaderProgram = null; + this._glProgramState = null; this._directorProjection = 0; this._dirty = false; @@ -227,7 +227,7 @@ cc.GridBase = cc.Class.extend(/** @lends cc.GridBase# */{ if (!this._grabber) return false; this._grabber.grab(this._texture); - this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE); + this._glProgramState = cc.GLProgramState.getOrCreateWithGLProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE)); this.calculateVertexPoints(); return true; }, diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js index 6457d180fb..eb95a3be0c 100644 --- a/cocos2d/shaders/CCGLProgramState.js +++ b/cocos2d/shaders/CCGLProgramState.js @@ -24,9 +24,6 @@ THE SOFTWARE. ****************************************************************************/ -// @TODO add floatv and intv methods, that take arrays -// and float1..4 methods, which take arguments. - var types = { GL_FLOAT: 0, @@ -122,8 +119,8 @@ cc.UniformValue = cc.Class.extend({ this._value[1], this._value[2]); break; case types.GL_FLOAT_VEC4: - this._glprogram.setUniformLocationWith3f(this._uniform.location, this._value[0], - this._value[1], this._value[2]); + this._glprogram.setUniformLocationWith4f(this._uniform.location, this._value[0], + this._value[1], this._value[2], this._value[3]); break; case types.GL_FLOAT_MAT4: this._glprogram.setUniformLocationWithMatrix4fv(this._uniform.location, this._value); @@ -136,7 +133,7 @@ cc.UniformValue = cc.Class.extend({ cc.glBindTexture2DN(this._value, this._textureId); break; default: - cc.Assert(false, "Unsupported type"); + ; } }, }); From fdaa7e27f7c0ab13e5a3b08342e0b0742189ba94 Mon Sep 17 00:00:00 2001 From: David DeSimone Date: Mon, 19 Dec 2016 14:55:42 -0500 Subject: [PATCH 03/65] Updating CCGLProgramState based on code review feedback. Removing uneeded object creation and lookup. Removing uneeded repeated calls to bind uniform values. Changing GLProgramState to not use cc.Class but instead using classic prototypical inheritance. --- cocos2d/shaders/CCGLProgram.js | 14 - cocos2d/shaders/CCGLProgramState.js | 574 ++++++++++++++-------------- 2 files changed, 288 insertions(+), 300 deletions(-) diff --git a/cocos2d/shaders/CCGLProgram.js b/cocos2d/shaders/CCGLProgram.js index c7c191fa76..eda7e7fc46 100644 --- a/cocos2d/shaders/CCGLProgram.js +++ b/cocos2d/shaders/CCGLProgram.js @@ -116,7 +116,6 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ ctor: function (vShaderFileName, fShaderFileName, glContext) { this._uniforms = {}; this._hashForUniforms = {}; - this._userUniforms = {}; this._glContext = glContext || cc._renderContext; vShaderFileName && fShaderFileName && this.init(vShaderFileName, fShaderFileName); @@ -232,7 +231,6 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ } this._glContext.linkProgram(this._programObj); - this._parseUniforms(); if (this._vertShader) this._glContext.deleteShader(this._vertShader); @@ -255,18 +253,6 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ return true; }, - _parseUniforms: function _parseUniforms() { - var activeUniforms = this._glContext.getProgramParameter(this._programObj, this._glContext.ACTIVE_UNIFORMS); - for (var i = 0; i < activeUniforms; ++i) { - var uniform = this._glContext.getActiveUniform(this._programObj, i); - uniform.location = this._glContext.getUniformLocation(this._programObj, uniform.name); - if (uniform.name.indexOf("CC_") !== 0) { - uniform.location = this._glContext.getUniformLocation(this._programObj, uniform.name); - uniform.name = uniform.name.replace("[]", ""); - this._userUniforms[uniform.name] = uniform; - } - } - }, /** * it will call glUseProgram() */ diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js index eb95a3be0c..39aee7c290 100644 --- a/cocos2d/shaders/CCGLProgramState.js +++ b/cocos2d/shaders/CCGLProgramState.js @@ -25,298 +25,300 @@ ****************************************************************************/ var types = - { - GL_FLOAT: 0, - GL_INT: 1, - GL_FLOAT_VEC2: 2, - GL_FLOAT_VEC3: 3, - GL_FLOAT_VEC4: 4, - GL_FLOAT_MAT4: 5, - GL_CALLBACK: 6, - GL_TEXTURE: 7 - }; - -cc.UniformValue = cc.Class.extend({ - _uniform: null, - _glprogram: null, - _value: null, - _type: -1, - - ctor: function ctor(uniform, glprogram) { - this._uniform = uniform; - this._glprogram = glprogram; - }, - - setFloat: function setFloat(value) { - this._value = value; - this._type = types.GL_FLOAT; - }, - - setInt: function setInt(value) { - this._value = value; - this._type = types.GL_INT; - }, - - setVec2: function setVec2(v1, v2) { - this._value = [v1, v2]; - this._type = types.GL_FLOAT_VEC2; - }, - - setVec2v: function setVec2v(value) { - this._value = value; - this._type = types.GL_FLOAT_VEC2; - }, - - setVec3: function setVec3(v1, v2, v3) { - this._value = [v1, v2, v3]; - this._type = types.GL_FLOAT_VEC3; - }, - - setVec3v: function setVec3v(value) { - this._value = value; - this._type = types.GL_FLOAT_VEC3; - }, - - setVec4: function setVec4(v1, v2, v3, v4) { - this._value = [v1, v2, v3, v4]; - this._type = types.GL_FLOAT_VEC4; - }, - - setVec4v: function setVec4v(value) { - this._value = value; - this._type = types.GL_FLOAT_VEC4; - }, - - setMat4: function setMat4(value) { - this._value = value; - this._type = types.GL_FLOAT_MAT4; - }, - - setCallback: function setCallback(fn) { - this._value = fn; - this._type = types.GL_CALLBACK; - }, - - setTexture: function setTexture(textureId, textureUnit) { - this._value = textureUnit; - this._textureId = textureId; - this._type = types.GL_TEXTURE; - }, - - apply: function apply() { - switch (this._type) { - case types.GL_INT: - this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); - break; - case types.GL_FLOAT: - this._glprogram.setUniformLocationWith1f(this._uniform.location, this._value); - break; - case types.GL_FLOAT_VEC2: - this._glprogram.setUniformLocationWith2f(this._uniform.location, this._value[0], this._value[1]); - break; - case types.GL_FLOAT_VEC3: - this._glprogram.setUniformLocationWith3f(this._uniform.location, this._value[0], - this._value[1], this._value[2]); - break; - case types.GL_FLOAT_VEC4: - this._glprogram.setUniformLocationWith4f(this._uniform.location, this._value[0], - this._value[1], this._value[2], this._value[3]); - break; - case types.GL_FLOAT_MAT4: - this._glprogram.setUniformLocationWithMatrix4fv(this._uniform.location, this._value); - break; - case types.GL_CALLBACK: - this._value(this._glprogram, this._uniform); - break; - case types.GL_TEXTURE: - this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); - cc.glBindTexture2DN(this._value, this._textureId); - break; - default: - ; - } - }, -}); - -cc.GLProgramState = cc.Class.extend({ - _glprogram: null, - _uniformsByName: null, - _uniformsByLocation: null, - _boundTextureUnits: null, - _textureUnitIndex: 0, - - init: function init(glprogram) { - this._glprogram = glprogram; - this._uniformsByName = {}; - this._uniformsByLocation = {}; - this._boundTextureUnits = {}; - this._textureUnitIndex = 1; // Start at 1, as CC_Texture0 is bound to 0 - var userUniformKeys = Object.keys(glprogram._userUniforms); - for (var i = 0; i < userUniformKeys.length; ++i) { - var uniform = glprogram._userUniforms[userUniformKeys[i]]; - var uniformValue = new cc.UniformValue(uniform, glprogram); - this._uniformsByName[uniform.name] = uniformValue; - this._uniformsByLocation[uniform.location] = uniformValue; - } - }, - - apply: function apply(modelView) { - this.applyGLProgram(modelView); - this.applyUniforms(); - }, - - applyGLProgram: function applyGLProgram(modelView) { - this._glprogram.use(); - if (modelView) { - this._glprogram._setUniformForMVPMatrixWithMat4(modelView); - } - }, - - applyUniforms: function applyUniforms() { - var uniformKeys = Object.keys(this._uniformsByName); - for (var i = 0; i < uniformKeys.length; ++i) { - var uniform = this._uniformsByName[uniformKeys[i]]; - uniform.apply(); - } - }, - - setGLProgram: function setGLProgram(glprogram) { - this._glprogram = glprogram; - }, - - getGLProgram: function getGLProgram() { - return this._glprogram; - }, - - getUniformCount: function getUniformCount() { - return Object.keys(this._uniformsByName).length; - }, - - getUniformValue: function getUniformValue(uniform) - { - if (typeof uniform === 'string') { - return this._uniformsByName[uniform]; - } else { - return this._uniformsByLocation[uniform]; - } - }, - - // Accepts either string or uniform location - setUniformInt: function setUniformInt(uniform, value) { - var v = this.getUniformValue(uniform); - if (v) { - v.setInt(value); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - }, - - setUniformFloat: function setUniformFloat(uniform, value) { - var v = this.getUniformValue(uniform); - if (v) { - v.setFloat(value); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - }, - - setUniformVec2: function setUniformVec2(uniform, v1, v2) { - var v = this.getUniformValue(uniform); - if (v) { - v.setVec2(v1, v2); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - }, + { + GL_FLOAT: 0, + GL_INT: 1, + GL_FLOAT_VEC2: 2, + GL_FLOAT_VEC3: 3, + GL_FLOAT_VEC4: 4, + GL_FLOAT_MAT4: 5, + GL_CALLBACK: 6, + GL_TEXTURE: 7 + }; + + + +cc.UniformValue = function (uniform, glprogram) { + this._uniform = uniform; + this._glprogram = glprogram; + + this._value = null; + this._currentBoundValue = null; + this._type = -1; +}; + +cc.UniformValue.prototype = { + setFloat: function setFloat(value) { + this._value = value; + this._type = types.GL_FLOAT; + }, + + setInt: function setInt(value) { + this._value = value; + this._type = types.GL_INT; + }, + + setVec2: function setVec2(v1, v2) { + this._value = [v1, v2]; + this._type = types.GL_FLOAT_VEC2; + }, + + setVec2v: function setVec2v(value) { + this._value = value; + this._type = types.GL_FLOAT_VEC2; + }, + + setVec3: function setVec3(v1, v2, v3) { + this._value = [v1, v2, v3]; + this._type = types.GL_FLOAT_VEC3; + }, + + setVec3v: function setVec3v(value) { + this._value = value; + this._type = types.GL_FLOAT_VEC3; + }, + + setVec4: function setVec4(v1, v2, v3, v4) { + this._value = [v1, v2, v3, v4]; + this._type = types.GL_FLOAT_VEC4; + }, + + setVec4v: function setVec4v(value) { + this._value = value; + this._type = types.GL_FLOAT_VEC4; + }, + + setMat4: function setMat4(value) { + this._value = value; + this._type = types.GL_FLOAT_MAT4; + }, + + setCallback: function setCallback(fn) { + this._value = fn; + this._type = types.GL_CALLBACK; + }, + + setTexture: function setTexture(textureId, textureUnit) { + this._value = textureUnit; + this._textureId = textureId; + this._type = types.GL_TEXTURE; + }, + + apply: function apply() { + if (this._currentBoundValue === this._value + && this._type !== types.GL_CALLBACK) { + return; + } + + this._currentBoundValue = this._value; + switch (this._type) { + case types.GL_INT: + this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); + break; + case types.GL_FLOAT: + this._glprogram.setUniformLocationWith1f(this._uniform.location, this._value); + break; + case types.GL_FLOAT_VEC2: + this._glprogram.setUniformLocationWith2f(this._uniform.location, this._value[0], this._value[1]); + break; + case types.GL_FLOAT_VEC3: + this._glprogram.setUniformLocationWith3f(this._uniform.location, this._value[0], + this._value[1], this._value[2]); + break; + case types.GL_FLOAT_VEC4: + this._glprogram.setUniformLocationWith4f(this._uniform.location, this._value[0], + this._value[1], this._value[2], this._value[3]); + break; + case types.GL_FLOAT_MAT4: + this._glprogram.setUniformLocationWithMatrix4fv(this._uniform.location, this._value); + break; + case types.GL_CALLBACK: + this._value(this._glprogram, this._uniform); + break; + case types.GL_TEXTURE: + this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); + cc.glBindTexture2DN(this._value, this._textureId); + break; + default: + ; + } + }, +}; + +cc.GLProgramState = function (glprogram) { + this._glprogram = glprogram; + this._uniforms = []; + this._uniformsByName = {}; + this._uniformsByLocation = {}; + this._boundTextureUnits = {}; + this._textureUnitIndex = 1; // Start at 1, as CC_Texture0 is bound to 0 + + + var activeUniforms = glprogram._glContext.getProgramParameter(glprogram._programObj, + glprogram._glContext.ACTIVE_UNIFORMS); - setUniformVec2v: function setUniformVec2v(uniform, value) { - var v = this.getUniformValue(uniform); - if (v) { - v.setVec2v(value); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - }, + for (var i = 0; i < activeUniforms; ++i) { + var uniform = glprogram._glContext.getActiveUniform(glprogram._programObj, i); + if (uniform.name.indexOf("CC_") !== 0) { + uniform.location = glprogram._glContext.getUniformLocation(glprogram._programObj, + uniform.name); + uniform.name = uniform.name.replace("[]", ""); + var uniformValue = new cc.UniformValue(uniform, glprogram); + this._uniforms.push(uniformValue); + this._uniformsByName[uniform.name] = i; + this._uniformsByLocation[uniform.location] = i; + } + } +}; + +cc.GLProgramState.prototype = { + apply: function apply(modelView) { + this._glprogram.use(); + if (modelView) { + this._glprogram._setUniformForMVPMatrixWithMat4(modelView); + } + + for (var i = 0; i < this._uniforms.length; ++i) { + this._uniforms[i].apply(); + } + }, + + setGLProgram: function setGLProgram(glprogram) { + this._glprogram = glprogram; + }, + + getGLProgram: function getGLProgram() { + return this._glprogram; + }, + + getUniformCount: function getUniformCount() { + return this._uniforms.length; + }, + + getUniformValue: function getUniformValue(uniform) + { + if (typeof uniform === 'string') { + return this._uniforms[this._uniformsByName[uniform]]; + } else { + return this._uniforms[this._uniformsByLocation[uniform]]; + } + }, + + // Accepts either string or uniform location + setUniformInt: function setUniformInt(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setInt(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformFloat: function setUniformFloat(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setFloat(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec2: function setUniformVec2(uniform, v1, v2) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec2(v1, v2); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec2v: function setUniformVec2v(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec2v(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, - setUniformVec3: function setUniformVec3(uniform, v1, v2, v3) { - var v = this.getUniformValue(uniform); - if (v) { - v.setVec3(v1, v2, v3); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - }, - - setUniformVec3v: function setUniformVec3v(uniform, value) { - var v = this.getUniformValue(uniform); - if (v) { - v.setVec3v(value); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - }, + setUniformVec3: function setUniformVec3(uniform, v1, v2, v3) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec3(v1, v2, v3); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec3v: function setUniformVec3v(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec3v(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, - setUniformVec4: function setUniformVec4(uniform, v1, v2, v3, v4) { - var v = this.getUniformValue(uniform); - if (v) { - v.setVec4(v1, v2, v3, v4); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - }, - - setUniformVec4v: function setUniformVec4v(uniform, value) { - var v = this.getUniformValue(uniform); - if (v) { - v.setVec4v(value); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - }, + setUniformVec4: function setUniformVec4(uniform, v1, v2, v3, v4) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec4(v1, v2, v3, v4); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, + + setUniformVec4v: function setUniformVec4v(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setVec4v(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + }, - setUniformMat4: function setUniformMat4(uniform, value) { - var v = this.getUniformValue(uniform); - if (v) { - v.setMat4(value); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - - }, - - setUniformCallback: function setUniformCallback(uniform, callback) { - var v = this.getUniformValue(uniform); - if (v) { - v.setCallback(callback); - } else { - cc.log("cocos2d: warning: Uniform not found: " + uniform); - } - - }, - - setUniformTexture: function setUniformTexture(uniform, texture) { - var uniformValue = this.getUniformValue(uniform); - if (uniformValue) { - var textureUnit = this._boundTextureUnits[uniform]; - if (textureUnit) { - uniformValue.setTexture(texture, textureUnit); - } else { - uniformValue.setTexture(texture, this._textureUnitIndex); - this._boundTextureUnits[uniform] = this._textureUnitIndex++; - } - } - } -}); + setUniformMat4: function setUniformMat4(uniform, value) { + var v = this.getUniformValue(uniform); + if (v) { + v.setMat4(value); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + + }, + + setUniformCallback: function setUniformCallback(uniform, callback) { + var v = this.getUniformValue(uniform); + if (v) { + v.setCallback(callback); + } else { + cc.log("cocos2d: warning: Uniform not found: " + uniform); + } + + }, + + setUniformTexture: function setUniformTexture(uniform, texture) { + var uniformValue = this.getUniformValue(uniform); + if (uniformValue) { + var textureUnit = this._boundTextureUnits[uniform]; + if (textureUnit) { + uniformValue.setTexture(texture, textureUnit); + } else { + uniformValue.setTexture(texture, this._textureUnitIndex); + this._boundTextureUnits[uniform] = this._textureUnitIndex++; + } + } + } +}; cc.GLProgramState._cache = {}; cc.GLProgramState.getOrCreateWithGLProgram = function (glprogram) { - var programState = cc.GLProgramState._cache[glprogram.__instanceId]; - if (!programState) { - programState = new cc.GLProgramState(); - programState.init(glprogram); - cc.GLProgramState._cache[glprogram.__instanceId] = programState; - } - - return programState; + var programState = cc.GLProgramState._cache[glprogram.__instanceId]; + if (!programState) { + programState = new cc.GLProgramState(glprogram); + cc.GLProgramState._cache[glprogram.__instanceId] = programState; + } + + return programState; }; From 721abd1eab939a32a5f5d835fc0075ab40f2b2c2 Mon Sep 17 00:00:00 2001 From: David DeSimone Date: Mon, 19 Dec 2016 16:15:17 -0500 Subject: [PATCH 04/65] Preventing issue where mutating the value of an array after setting it may propigate to changing the GLProgramState --- cocos2d/shaders/CCGLProgramState.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js index 39aee7c290..1da5103db6 100644 --- a/cocos2d/shaders/CCGLProgramState.js +++ b/cocos2d/shaders/CCGLProgramState.js @@ -64,7 +64,7 @@ cc.UniformValue.prototype = { }, setVec2v: function setVec2v(value) { - this._value = value; + this._value = value.slice(0); this._type = types.GL_FLOAT_VEC2; }, @@ -74,7 +74,7 @@ cc.UniformValue.prototype = { }, setVec3v: function setVec3v(value) { - this._value = value; + this._value = value.slice(0); this._type = types.GL_FLOAT_VEC3; }, @@ -84,12 +84,12 @@ cc.UniformValue.prototype = { }, setVec4v: function setVec4v(value) { - this._value = value; + this._value = value.slice(0); this._type = types.GL_FLOAT_VEC4; }, setMat4: function setMat4(value) { - this._value = value; + this._value = value.slice(0); this._type = types.GL_FLOAT_MAT4; }, From 2c13088e5b77c5a76d4bc045f1dd07ff981b6443 Mon Sep 17 00:00:00 2001 From: David DeSimone Date: Mon, 19 Dec 2016 16:41:01 -0500 Subject: [PATCH 05/65] Fixing color/opacity rendering issue with CCAtlastNodeWebGLRendering. Fixing missing function call to setUniformsForBuiltins in TextureWebGL --- cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js | 6 ++++-- cocos2d/core/textures/TexturesWebGL.js | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js index 085e3770bb..5810d00794 100644 --- a/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js +++ b/cocos2d/core/base-nodes/CCAtlasNodeWebGLRenderCmd.js @@ -32,12 +32,14 @@ this._textureAtlas = null; this._colorUnmodified = cc.color.WHITE; this._colorF32Array = null; + this._uniformColor = null; this._matrix = new cc.math.Matrix4(); this._matrix.identity(); //shader stuff this._shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR); + this._uniformColor = cc._renderContext.getUniformLocation(this._shaderProgram.getProgram(), "u_color"); }; var proto = cc.AtlasNode.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype); @@ -69,8 +71,8 @@ this._glProgramState.apply(this._matrix); cc.glBlendFunc(node._blendFunc.src, node._blendFunc.dst); - if (this._colorF32Array) { - this._glProgramState.setUniformVec4v("u_color", this._colorF32Array); + if (this._uniformColor && this._colorF32Array) { + context.uniform4fv(this._uniformColor, this._colorF32Array); this._textureAtlas.drawNumberOfQuads(node.quadsToDraw, 0); } }; diff --git a/cocos2d/core/textures/TexturesWebGL.js b/cocos2d/core/textures/TexturesWebGL.js index 49a33ae647..42d0d3e7ec 100644 --- a/cocos2d/core/textures/TexturesWebGL.js +++ b/cocos2d/core/textures/TexturesWebGL.js @@ -340,6 +340,7 @@ cc._tmp.WebGLTexture2D = function () { width + point.x, height + point.y, 0.0]; self._glProgramState.apply(); + self._glProgramState._glprogram.setUniformsForBuiltins(); cc.glBindTexture2D(self); @@ -369,6 +370,7 @@ cc._tmp.WebGLTexture2D = function () { rect.x + rect.width, rect.y + rect.height /*0.0*/]; self._glProgramState.apply(); + self._glProgramState._glprogram.setUniformsForBuiltins(); cc.glBindTexture2D(self); From 781c3c8b01f304814b97911901fff0e78b4370fa Mon Sep 17 00:00:00 2001 From: David DeSimone Date: Mon, 19 Dec 2016 17:13:20 -0500 Subject: [PATCH 06/65] Fixing improper logical error in assigning values to uniformByName and uniformByLocation map --- cocos2d/shaders/CCGLProgramState.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js index 1da5103db6..edfa2ae175 100644 --- a/cocos2d/shaders/CCGLProgramState.js +++ b/cocos2d/shaders/CCGLProgramState.js @@ -156,7 +156,8 @@ cc.GLProgramState = function (glprogram) { var activeUniforms = glprogram._glContext.getProgramParameter(glprogram._programObj, glprogram._glContext.ACTIVE_UNIFORMS); - + + var count = 0; for (var i = 0; i < activeUniforms; ++i) { var uniform = glprogram._glContext.getActiveUniform(glprogram._programObj, i); if (uniform.name.indexOf("CC_") !== 0) { @@ -165,8 +166,9 @@ cc.GLProgramState = function (glprogram) { uniform.name = uniform.name.replace("[]", ""); var uniformValue = new cc.UniformValue(uniform, glprogram); this._uniforms.push(uniformValue); - this._uniformsByName[uniform.name] = i; - this._uniformsByLocation[uniform.location] = i; + this._uniformsByName[uniform.name] = count; + this._uniformsByLocation[uniform.location] = count; + count++; } } }; From 83540d8ec258bb75a86a64c51688b982640c54d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20Boya=20Garc=C3=ADa?= Date: Tue, 31 Jan 2017 15:59:52 +0100 Subject: [PATCH 07/65] Text wrapping support for more languages --- .../labelttf/CCLabelTTFCanvasRenderCmd.js | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js index 51fb3888b4..fe036fcf2a 100644 --- a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js +++ b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js @@ -24,13 +24,25 @@ cc.LabelTTF._textBaseline = ["top", "middle", "bottom"]; //check the first character cc.LabelTTF.wrapInspection = true; -//Support: English French German -//Other as Oriental Language -cc.LabelTTF._wordRex = /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+|\S)/; -cc.LabelTTF._symbolRex = /^[!,.:;}\]%\?>、‘“》?。,!]/; -cc.LabelTTF._lastWordRex = /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+|\S)$/; -cc.LabelTTF._lastEnglish = /[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+$/; -cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]/; +// These regular expressions consider a word any sequence of characters +// from these Unicode (sub)blocks: +// - Basic Latin (letters and numbers only, plus the hypen-minus '-') +// - Latin-1 Supplement (accentuated letters only) +// - Latin Extended-A (complete) +// - Latin Extended-B (complete) +// - IPA Extensions (complete) +// - Spacing Modifier Letters (complete) +// - Combining Diacritical Marks (Combining Grapheme Joiner excluded) +// - Greek and Coptic (complete, including reserved code points) +// - Cyrillic (complete) +// - Cyrillic Supplement (complete) +// - General Punctuation (Non-Breaking Hyphen [U+2011] only*) +// * Note that Hyphen [U+2010] is considered a word boundary. +cc.LabelTTF._wordRex = /([a-zA-Z0-9À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011]+|\S)/; +cc.LabelTTF._symbolRex = /^[!,.:;}\]%\?>、‘“》»?。,!\u2010]/; +cc.LabelTTF._lastWordRex = /([a-zA-Z0-9À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011]+|\S)$/; +cc.LabelTTF._lastEnglish = /[a-zA-Z0-9À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011]+$/; +cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011]/; (function () { cc.LabelTTF.RenderCmd = function () { From fa3d2faff9f11a346ceb0cd1a8278a05c6e03842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20Boya=20Garc=C3=ADa?= Date: Tue, 31 Jan 2017 18:57:03 +0100 Subject: [PATCH 08/65] =?UTF-8?q?Text=20wrap=20regexp:=20handle=20=C2=BF?= =?UTF-8?q?=C2=A1=20add=20the=20hyphen-minus=20and=20more=20quotation=20ma?= =?UTF-8?q?rks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/labelttf/CCLabelTTFCanvasRenderCmd.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js index fe036fcf2a..42d5ccf3d4 100644 --- a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js +++ b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js @@ -26,8 +26,8 @@ cc.LabelTTF.wrapInspection = true; // These regular expressions consider a word any sequence of characters // from these Unicode (sub)blocks: -// - Basic Latin (letters and numbers only, plus the hypen-minus '-') -// - Latin-1 Supplement (accentuated letters only) +// - Basic Latin (letters and numbers, plus the hypen-minus '-') +// - Latin-1 Supplement (accentuated letters and ¿¡ only) // - Latin Extended-A (complete) // - Latin Extended-B (complete) // - IPA Extensions (complete) @@ -36,13 +36,13 @@ cc.LabelTTF.wrapInspection = true; // - Greek and Coptic (complete, including reserved code points) // - Cyrillic (complete) // - Cyrillic Supplement (complete) -// - General Punctuation (Non-Breaking Hyphen [U+2011] only*) +// - General Punctuation (Non-Breaking Hyphen* [U+2011] and quotation marks) // * Note that Hyphen [U+2010] is considered a word boundary. -cc.LabelTTF._wordRex = /([a-zA-Z0-9À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011]+|\S)/; -cc.LabelTTF._symbolRex = /^[!,.:;}\]%\?>、‘“》»?。,!\u2010]/; -cc.LabelTTF._lastWordRex = /([a-zA-Z0-9À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011]+|\S)$/; -cc.LabelTTF._lastEnglish = /[a-zA-Z0-9À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011]+$/; -cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011]/; +cc.LabelTTF._wordRex = /([a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011‵-‷‹⁅]+|\S)/; +cc.LabelTTF._symbolRex = /^[!,.:;}\]%\?>、‘“》»?。,!\u2010′-‴›‼⁆⁇-⁉]/; +cc.LabelTTF._lastWordRex = /([a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011‵-‷‹⁅]+|\S)$/; +cc.LabelTTF._lastEnglish = /[a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011‵-‷‹⁅]+$/; +cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u0350-\u036FͰ-ԯ\u2011‵-‷‹⁅]/; (function () { cc.LabelTTF.RenderCmd = function () { From 245c22fdb497fd5c90eebde77b430eb3cbec61e2 Mon Sep 17 00:00:00 2001 From: jordanth Date: Thu, 20 Apr 2017 13:21:08 -0700 Subject: [PATCH 09/65] Wrap the created localCanvas element with the cc.$ class .addClass(...) is called on it a few lines later, which throws an error if localCanvas is a regular HTML element. --- CCBoot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CCBoot.js b/CCBoot.js index a366001d74..deeba9da56 100644 --- a/CCBoot.js +++ b/CCBoot.js @@ -2669,7 +2669,7 @@ cc.game = /** @lends cc.game# */{ } width = width || element.clientWidth; height = height || element.clientHeight; - this.canvas = cc._canvas = localCanvas = document.createElement("CANVAS"); + this.canvas = cc._canvas = localCanvas = cc.$(document.createElement("CANVAS")); this.container = cc.container = localContainer = document.createElement("DIV"); element.appendChild(localContainer); } From 811ca72104bbd5ef860924510c997249c18b3848 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 9 May 2017 11:32:50 +0800 Subject: [PATCH 10/65] Use imagePool to reduce image memory usage in WebGL mode --- CCBoot.js | 55 ++++++++++++++----- .../labelttf/CCLabelTTFCanvasRenderCmd.js | 10 +++- cocos2d/core/platform/CCLoaders.js | 10 +++- cocos2d/core/textures/CCTexture2D.js | 4 +- cocos2d/core/textures/CCTextureCache.js | 9 +-- cocos2d/core/textures/TexturesWebGL.js | 11 ++-- 6 files changed, 67 insertions(+), 32 deletions(-) diff --git a/CCBoot.js b/CCBoot.js index a366001d74..cbd4628a78 100644 --- a/CCBoot.js +++ b/CCBoot.js @@ -583,6 +583,33 @@ cc.path = /** @lends cc.path# */{ * @see cc.loader */ +var imagePool = { + _pool: new Array(10), + _MAX: 10, + _smallImg: "data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=", + + count: 0, + get: function () { + if (this.count > 0) { + this.count--; + var result = this._pool[this.count]; + this._pool[this.count] = null; + return result; + } + else { + return new Image(); + } + }, + put: function (img) { + var pool = this._pool; + if (img instanceof HTMLImageElement && this.count < this._MAX) { + img.src = this._smallImg; + pool[this.count] = img; + this.count++; + } + } +}; + /** * Singleton instance of cc.Loader. * @name cc.loader @@ -867,7 +894,7 @@ cc.loader = (function () { * @param {function} callback * @returns {Image} */ - loadImg: function (url, option, callback) { + loadImg: function (url, option, callback, img) { var opt = { isCrossOrigin: true }; @@ -876,30 +903,22 @@ cc.loader = (function () { else if (option !== undefined) callback = option; - var img = this.getRes(url); - if (img) { - callback && callback(null, img); - return img; - } - var queue = _queue[url]; if (queue) { queue.callbacks.push(callback); return queue.img; } - img = new Image(); + img = img || imagePool.get(); if (opt.isCrossOrigin && location.origin !== "file://") img.crossOrigin = "Anonymous"; + else + img.crossOrigin = null; var loadCallback = function () { this.removeEventListener('load', loadCallback, false); this.removeEventListener('error', errorCallback, false); - if (!_urlRegExp.test(url)) { - cc.loader.cache[url] = img; - } - var queue = _queue[url]; if (queue) { var callbacks = queue.callbacks; @@ -912,6 +931,10 @@ cc.loader = (function () { queue.img = null; delete _queue[url]; } + + if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) { + imagePool.put(img); + } }; var self = this; @@ -919,10 +942,10 @@ cc.loader = (function () { this.removeEventListener('load', loadCallback, false); this.removeEventListener('error', errorCallback, false); - if (img.crossOrigin && img.crossOrigin.toLowerCase() === "anonymous") { + if (window.location.protocol !== 'https:' && img.crossOrigin && img.crossOrigin.toLowerCase() === "anonymous") { opt.isCrossOrigin = false; self.release(url); - cc.loader.loadImg(url, opt, callback); + cc.loader.loadImg(url, opt, callback, img); } else { var queue = _queue[url]; if (queue) { @@ -936,6 +959,10 @@ cc.loader = (function () { queue.img = null; delete _queue[url]; } + + if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) { + imagePool.put(img); + } } }; diff --git a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js index 51fb3888b4..d6d691265d 100644 --- a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js +++ b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js @@ -418,7 +418,10 @@ cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]/; if (node._string.length === 0) { locLabelCanvas.width = 1; locLabelCanvas.height = locContentSize.height || 1; - node._texture && node._texture.handleLoadedTexture(); + if (node._texture) { + node._texture._htmlElementObj = this._labelCanvas; + node._texture.handleLoadedTexture(); + } node.setTextureRect(cc.rect(0, 0, 1, locContentSize.height)); return true; } @@ -432,7 +435,10 @@ cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]/; if (flag) locContext.clearRect(0, 0, width, height); this._saveStatus(); this._drawTTFInCanvas(locContext); - node._texture && node._texture.handleLoadedTexture(); + if (node._texture) { + node._texture._htmlElementObj = this._labelCanvas; + node._texture.handleLoadedTexture(); + } node.setTextureRect(cc.rect(0, 0, width, height)); return true; }; diff --git a/cocos2d/core/platform/CCLoaders.js b/cocos2d/core/platform/CCLoaders.js index 69c8e9430f..9d91344a23 100644 --- a/cocos2d/core/platform/CCLoaders.js +++ b/cocos2d/core/platform/CCLoaders.js @@ -54,9 +54,13 @@ cc._imgLoader = { callback = function (err, img) { if (err) return cb(err); - cc.loader.cache[url] = img; - cc.textureCache.handleLoadedTexture(url); - cb(null, img); + + var tex = cc.textureCache.getTextureForKey(url) || new cc.Texture2D(); + tex.url = url; + tex.initWithElement(img); + tex.handleLoadedTexture(); + cc.textureCache.cacheImage(url, tex); + cb(null, tex); }; } cc.loader.loadImg(realUrl, callback); diff --git a/cocos2d/core/textures/CCTexture2D.js b/cocos2d/core/textures/CCTexture2D.js index cd0a9ff153..687a5e3929 100644 --- a/cocos2d/core/textures/CCTexture2D.js +++ b/cocos2d/core/textures/CCTexture2D.js @@ -192,9 +192,7 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { var self = this; if (self._textureLoaded) return; if (!self._htmlElementObj) { - var img = cc.loader.getRes(self.url); - if (!img) return; - self.initWithElement(img); + return; } var locElement = self._htmlElementObj; diff --git a/cocos2d/core/textures/CCTextureCache.js b/cocos2d/core/textures/CCTextureCache.js index 2099565eb3..afd8af3e61 100644 --- a/cocos2d/core/textures/CCTextureCache.js +++ b/cocos2d/core/textures/CCTextureCache.js @@ -313,7 +313,7 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { var _p = cc.textureCache; - _p.handleLoadedTexture = function (url) { + _p.handleLoadedTexture = function (url, img) { var locTexs = this._textures; //remove judge var tex = locTexs[url]; @@ -321,6 +321,7 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { tex = locTexs[url] = new cc.Texture2D(); tex.url = url; } + tex.initWithElement(img); tex.handleLoadedTexture(); }; @@ -365,12 +366,12 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { if (err) return cb && cb.call(target, err); + cc.textureCache.handleLoadedTexture(url, img); + var texResult = locTexs[url]; if (!cc.loader.cache[url]) { - cc.loader.cache[url] = img; + cc.loader.cache[url] = texResult; } - cc.textureCache.handleLoadedTexture(url); - var texResult = locTexs[url]; cb && cb.call(target, texResult); }); diff --git a/cocos2d/core/textures/TexturesWebGL.js b/cocos2d/core/textures/TexturesWebGL.js index bcec5bfb53..5d704e25df 100644 --- a/cocos2d/core/textures/TexturesWebGL.js +++ b/cocos2d/core/textures/TexturesWebGL.js @@ -457,11 +457,8 @@ cc._tmp.WebGLTexture2D = function () { // Not sure about this ! Some texture need to be updated even after loaded if (!cc.game._rendererInitialized) return; - if (!self._htmlElementObj) { - var img = cc.loader.getRes(self.url); - if (!img) return; - self.initWithElement(img); - } + if (!self._htmlElementObj) + return; if (!self._htmlElementObj.width || !self._htmlElementObj.height) return; @@ -498,6 +495,7 @@ cc._tmp.WebGLTexture2D = function () { self._hasPremultipliedAlpha = premultiplied; self._hasMipmaps = false; + self._htmlElementObj = null; //dispatch load event to listener. self.dispatchEvent("load"); @@ -854,7 +852,7 @@ cc._tmp.WebGLTextureAtlas = function () { cc._tmp.WebGLTextureCache = function () { var _p = cc.textureCache; - _p.handleLoadedTexture = function (url) { + _p.handleLoadedTexture = function (url, img) { var locTexs = this._textures, tex, ext; //remove judge(webgl) if (!cc.game._rendererInitialized) { @@ -865,6 +863,7 @@ cc._tmp.WebGLTextureCache = function () { tex = locTexs[url] = new cc.Texture2D(); tex.url = url; } + tex.initWithElement(img); ext = cc.path.extname(url); if (ext === ".png") { tex.handleLoadedTexture(true); From d4d9cdfd19ee00eec57025c5becb96563ef86efc Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 9 May 2017 11:54:55 +0800 Subject: [PATCH 11/65] Fix eventManager memory leak --- cocos2d/core/event-manager/CCEventListener.js | 76 ++++++++++--------- cocos2d/core/event-manager/CCEventManager.js | 6 +- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/cocos2d/core/event-manager/CCEventListener.js b/cocos2d/core/event-manager/CCEventListener.js index 06e5bd4eee..c970c43fdf 100644 --- a/cocos2d/core/event-manager/CCEventListener.js +++ b/cocos2d/core/event-manager/CCEventListener.js @@ -277,15 +277,16 @@ cc.EventListener.CUSTOM = 8; cc._EventListenerCustom = cc.EventListener.extend({ _onCustomEvent: null, - ctor: function (listenerId, callback) { + ctor: function (listenerId, callback, target) { this._onCustomEvent = callback; - var selfPointer = this; - var listener = function (event) { - if (selfPointer._onCustomEvent !== null) - selfPointer._onCustomEvent(event); - }; + this._target = target; - cc.EventListener.prototype.ctor.call(this, cc.EventListener.CUSTOM, listenerId, listener); + cc.EventListener.prototype.ctor.call(this, cc.EventListener.CUSTOM, listenerId, this._callback); + }, + + _callback: function (event) { + if (this._onCustomEvent !== null) + this._onCustomEvent.call(this._target, event); }, checkAvailable: function () { @@ -308,31 +309,31 @@ cc._EventListenerMouse = cc.EventListener.extend({ onMouseScroll: null, ctor: function () { - var selfPointer = this; - var listener = function (event) { - var eventType = cc.EventMouse; - switch (event._eventType) { - case eventType.DOWN: - if (selfPointer.onMouseDown) - selfPointer.onMouseDown(event); - break; - case eventType.UP: - if (selfPointer.onMouseUp) - selfPointer.onMouseUp(event); - break; - case eventType.MOVE: - if (selfPointer.onMouseMove) - selfPointer.onMouseMove(event); - break; - case eventType.SCROLL: - if (selfPointer.onMouseScroll) - selfPointer.onMouseScroll(event); - break; - default: - break; - } - }; - cc.EventListener.prototype.ctor.call(this, cc.EventListener.MOUSE, cc._EventListenerMouse.LISTENER_ID, listener); + cc.EventListener.prototype.ctor.call(this, cc.EventListener.MOUSE, cc._EventListenerMouse.LISTENER_ID, this._callback); + }, + + _callback: function (event) { + var eventType = cc.EventMouse; + switch (event._eventType) { + case eventType.DOWN: + if (this.onMouseDown) + this.onMouseDown(event); + break; + case eventType.UP: + if (this.onMouseUp) + this.onMouseUp(event); + break; + case eventType.MOVE: + if (this.onMouseMove) + this.onMouseMove(event); + break; + case eventType.SCROLL: + if (this.onMouseScroll) + this.onMouseScroll(event); + break; + default: + break; + } }, clone: function () { @@ -501,11 +502,12 @@ cc._EventListenerFocus = cc.EventListener.extend({ }, onFocusChanged: null, ctor: function(){ - var listener = function(event){ - if(this.onFocusChanged) - this.onFocusChanged(event._widgetLoseFocus, event._widgetGetFocus); - }; - cc.EventListener.prototype.ctor.call(this, cc.EventListener.FOCUS, cc._EventListenerFocus.LISTENER_ID, listener); + cc.EventListener.prototype.ctor.call(this, cc.EventListener.FOCUS, cc._EventListenerFocus.LISTENER_ID, this._callback); + }, + _callback: function (event) { + if (this.onFocusChanged) { + this.onFocusChanged(event._widgetLoseFocus, event._widgetGetFocus); + } } }); diff --git a/cocos2d/core/event-manager/CCEventManager.js b/cocos2d/core/event-manager/CCEventManager.js index 890ba5bf7c..7f54f03939 100644 --- a/cocos2d/core/event-manager/CCEventManager.js +++ b/cocos2d/core/event-manager/CCEventManager.js @@ -258,8 +258,8 @@ cc.eventManager = /** @lends cc.eventManager# */{ if (!this._inDispatch) { listeners.clear(); - delete this._listenersMap[listenerID]; } + delete this._listenersMap[listenerID]; } var locToAddedListeners = this._toAddedListeners, listener; @@ -751,8 +751,8 @@ cc.eventManager = /** @lends cc.eventManager# */{ * @param {function} callback * @return {cc.EventListener} the generated event. Needed in order to remove the event from the dispatcher */ - addCustomListener: function (eventName, callback) { - var listener = new cc._EventListenerCustom(eventName, callback); + addCustomListener: function (eventName, callback, target) { + var listener = new cc._EventListenerCustom(eventName, callback, target); this.addListener(listener, 1); return listener; }, From f192b7d12737143dcef5edf8e73621435f78c289 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 9 May 2017 11:55:47 +0800 Subject: [PATCH 12/65] Listen to orientationChange event only on mobile --- cocos2d/core/platform/CCEGLView.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/platform/CCEGLView.js b/cocos2d/core/platform/CCEGLView.js index 6093dc0b04..448f1b2f1b 100755 --- a/cocos2d/core/platform/CCEGLView.js +++ b/cocos2d/core/platform/CCEGLView.js @@ -184,6 +184,10 @@ cc.EGLView = cc.Class.extend(/** @lends cc.view# */{ _t._rpFixedWidth = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_WIDTH); _t._targetDensityDPI = cc.DENSITYDPI_HIGH; + + if (sys.isMobile) { + window.addEventListener('orientationchange', this._orientationChange); + } }, // Resize helper functions @@ -276,14 +280,12 @@ cc.EGLView = cc.Class.extend(/** @lends cc.view# */{ if (!this.__resizeWithBrowserSize) { this.__resizeWithBrowserSize = true; window.addEventListener('resize', this._resizeEvent); - window.addEventListener('orientationchange', this._orientationChange); } } else { //disable if (this.__resizeWithBrowserSize) { this.__resizeWithBrowserSize = false; window.removeEventListener('resize', this._resizeEvent); - window.removeEventListener('orientationchange', this._orientationChange); } } }, From 0ff97d0972d2a24e6bb03b38f11627c89b28fcf1 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Tue, 9 May 2017 11:56:16 +0800 Subject: [PATCH 13/65] Fix texture cache.dumpCachedTextureInfo --- cocos2d/core/textures/CCTextureCache.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/textures/CCTextureCache.js b/cocos2d/core/textures/CCTextureCache.js index afd8af3e61..07442c8d3d 100644 --- a/cocos2d/core/textures/CCTextureCache.js +++ b/cocos2d/core/textures/CCTextureCache.js @@ -279,11 +279,11 @@ cc.textureCache = /** @lends cc.textureCache# */{ var selTexture = locTextures[key]; count++; if (selTexture.getHtmlElementObj() instanceof HTMLImageElement) - cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo, key, selTexture.getHtmlElementObj().src, selTexture.pixelsWidth, selTexture.pixelsHeight); + cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo, key, selTexture.getHtmlElementObj().src, selTexture.getPixelsWide(), selTexture.getPixelsHigh()); else { - cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_2, key, selTexture.pixelsWidth, selTexture.pixelsHeight); + cc.log(cc._LogInfos.textureCache_dumpCachedTextureInfo_2, key, selTexture.getPixelsWide(), selTexture.getPixelsHigh()); } - totalBytes += selTexture.pixelsWidth * selTexture.pixelsHeight * 4; + totalBytes += selTexture.getPixelsWide() * selTexture.getPixelsHigh() * 4; } var locTextureColorsCache = this._textureColorsCache; From 7c9a8b5bfaa78cd2ecf5a1651b04cf4f2572fa61 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 10 May 2017 10:59:52 +0800 Subject: [PATCH 14/65] Improve image loader and fix issues --- CCBoot.js | 6 ++++++ cocos2d/core/platform/CCLoaders.js | 8 ++------ cocos2d/core/textures/CCTexture2D.js | 1 + cocos2d/core/textures/CCTextureCache.js | 8 ++------ cocos2d/core/textures/TexturesWebGL.js | 9 +++------ 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/CCBoot.js b/CCBoot.js index cbd4628a78..8ac4065c37 100644 --- a/CCBoot.js +++ b/CCBoot.js @@ -903,6 +903,12 @@ cc.loader = (function () { else if (option !== undefined) callback = option; + var texture = this.getRes(url); + if (texture) { + callback && callback(null, texture); + return null; + } + var queue = _queue[url]; if (queue) { queue.callbacks.push(callback); diff --git a/cocos2d/core/platform/CCLoaders.js b/cocos2d/core/platform/CCLoaders.js index 9d91344a23..5826fd215d 100644 --- a/cocos2d/core/platform/CCLoaders.js +++ b/cocos2d/core/platform/CCLoaders.js @@ -54,12 +54,8 @@ cc._imgLoader = { callback = function (err, img) { if (err) return cb(err); - - var tex = cc.textureCache.getTextureForKey(url) || new cc.Texture2D(); - tex.url = url; - tex.initWithElement(img); - tex.handleLoadedTexture(); - cc.textureCache.cacheImage(url, tex); + + var tex = cc.textureCache.handleLoadedTexture(url, img); cb(null, tex); }; } diff --git a/cocos2d/core/textures/CCTexture2D.js b/cocos2d/core/textures/CCTexture2D.js index 687a5e3929..b80aec1274 100644 --- a/cocos2d/core/textures/CCTexture2D.js +++ b/cocos2d/core/textures/CCTexture2D.js @@ -227,6 +227,7 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { }, releaseTexture: function () { + this._htmlElementObj = null; cc.loader.release(this.url); }, diff --git a/cocos2d/core/textures/CCTextureCache.js b/cocos2d/core/textures/CCTextureCache.js index 07442c8d3d..5e59c2f83c 100644 --- a/cocos2d/core/textures/CCTextureCache.js +++ b/cocos2d/core/textures/CCTextureCache.js @@ -323,6 +323,7 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { } tex.initWithElement(img); tex.handleLoadedTexture(); + return tex; }; /** @@ -366,12 +367,7 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { if (err) return cb && cb.call(target, err); - cc.textureCache.handleLoadedTexture(url, img); - var texResult = locTexs[url]; - if (!cc.loader.cache[url]) { - cc.loader.cache[url] = texResult; - } - + var texResult = cc.textureCache.handleLoadedTexture(url, img); cb && cb.call(target, texResult); }); diff --git a/cocos2d/core/textures/TexturesWebGL.js b/cocos2d/core/textures/TexturesWebGL.js index 5d704e25df..58a2ced557 100644 --- a/cocos2d/core/textures/TexturesWebGL.js +++ b/cocos2d/core/textures/TexturesWebGL.js @@ -83,6 +83,7 @@ cc._tmp.WebGLTexture2D = function () { releaseTexture: function () { if (this._webTextureObj) cc._renderContext.deleteTexture(this._webTextureObj); + this._htmlElementObj = null; cc.loader.release(this.url); }, @@ -871,6 +872,7 @@ cc._tmp.WebGLTextureCache = function () { else { tex.handleLoadedTexture(); } + return tex; }; /** @@ -916,12 +918,7 @@ cc._tmp.WebGLTextureCache = function () { if (err) return cb && cb.call(target, err); - if (!cc.loader.cache[url]) { - cc.loader.cache[url] = img; - } - cc.textureCache.handleLoadedTexture(url); - - var texResult = locTexs[url]; + var texResult = cc.textureCache.handleLoadedTexture(url, img); cb && cb.call(target, texResult); }); From 7bf6632bca51c66443d97dbb40c99b4c7378ae53 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 10 May 2017 11:56:21 +0800 Subject: [PATCH 15/65] Fix duplicated loading will overwrite image into loader cache --- cocos2d/core/platform/CCLoaders.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/platform/CCLoaders.js b/cocos2d/core/platform/CCLoaders.js index 5826fd215d..16749a0949 100644 --- a/cocos2d/core/platform/CCLoaders.js +++ b/cocos2d/core/platform/CCLoaders.js @@ -48,13 +48,17 @@ cc._imgLoader = { load: function (realUrl, url, res, cb) { var callback; if (cc.loader.isLoading(realUrl)) { - callback = cb; + callback = function (err, img) { + if (err) + return cb(err); + var tex = cc.textureCache.getTextureForKey(url) || cc.textureCache.handleLoadedTexture(url, img); + cb(null, tex); + }; } else { callback = function (err, img) { if (err) return cb(err); - var tex = cc.textureCache.handleLoadedTexture(url, img); cb(null, tex); }; From 192a3052f6a5f430eb2f2a09554f44171b002ef5 Mon Sep 17 00:00:00 2001 From: giuseppelt Date: Fri, 19 May 2017 01:13:10 +0200 Subject: [PATCH 16/65] ParticleSystem: Mark as ChangeColor only if needed This avoid a waste of resources (particle image redraw), if the delta is only the alpha, which is handled by the context's globalAlpha --- cocos2d/particle/CCParticleSystemCanvasRenderCmd.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cocos2d/particle/CCParticleSystemCanvasRenderCmd.js b/cocos2d/particle/CCParticleSystemCanvasRenderCmd.js index 781baf7004..5f602e99f2 100644 --- a/cocos2d/particle/CCParticleSystemCanvasRenderCmd.js +++ b/cocos2d/particle/CCParticleSystemCanvasRenderCmd.js @@ -195,11 +195,12 @@ }; proto._updateDeltaColor = function (selParticle, dt) { if (!this._node._dontTint) { - selParticle.color.r += selParticle.deltaColor.r * dt; - selParticle.color.g += selParticle.deltaColor.g * dt; - selParticle.color.b += selParticle.deltaColor.b * dt; - selParticle.color.a += selParticle.deltaColor.a * dt; - selParticle.isChangeColor = true; + var deltaColor = selParticle.deltaColor; + selParticle.color.r += deltaColor.r * dt; + selParticle.color.g += deltaColor.g * dt; + selParticle.color.b += deltaColor.b * dt; + selParticle.color.a += deltaColor.a * dt; + selParticle.isChangeColor = deltaColor.r !== 0 || deltaColor.g !== 0 || deltaColor.b !== 0; } }; })(); From 5d989f0e95cb14d160bde830224e065e4f9d12d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Petr=C3=A9re?= Date: Tue, 13 Jun 2017 09:29:41 -0300 Subject: [PATCH 17/65] fix on moveTo() and MoveTo.create() JSDoc position can be passed as Number too (coordinate x) and both methods return cc.MoveTo --- cocos2d/actions/CCActionInterval.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index 74a855748e..4031671993 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -1311,7 +1311,7 @@ cc.RotateBy.create = cc.rotateBy; * @param {cc.Point|Number} deltaPos * @param {Number} [deltaY] * @example - * var actionTo = cc.moveBy(2, cc.p(windowSize.width - 40, windowSize.height - 40)); + * var actionBy = cc.moveBy(2, cc.p(windowSize.width - 40, windowSize.height - 40)); */ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ _positionDelta: null, @@ -1430,7 +1430,7 @@ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ * @return {cc.MoveBy} * @example * // example - * var actionTo = cc.moveBy(2, cc.p(windowSize.width - 40, windowSize.height - 40)); + * var actionBy = cc.moveBy(2, cc.p(windowSize.width - 40, windowSize.height - 40)); */ cc.moveBy = function (duration, deltaPos, deltaY) { return new cc.MoveBy(duration, deltaPos, deltaY); @@ -1458,7 +1458,7 @@ cc.MoveBy.create = cc.moveBy; * @param {cc.Point|Number} position * @param {Number} y * @example - * var actionBy = new cc.MoveTo(2, cc.p(80, 80)); + * var actionTo = new cc.MoveTo(2, cc.p(80, 80)); */ cc.MoveTo = cc.MoveBy.extend(/** @lends cc.MoveTo# */{ _endPosition: null, @@ -1524,12 +1524,12 @@ cc.MoveTo = cc.MoveBy.extend(/** @lends cc.MoveTo# */{ * Moving to the specified coordinates. * @function * @param {Number} duration duration in seconds - * @param {cc.Point} position + * @param {cc.Point|Number} position * @param {Number} y - * @return {cc.MoveBy} + * @return {cc.MoveTo} * @example * // example - * var actionBy = cc.moveTo(2, cc.p(80, 80)); + * var actionTo = cc.moveTo(2, cc.p(80, 80)); */ cc.moveTo = function (duration, position, y) { return new cc.MoveTo(duration, position, y); @@ -1540,9 +1540,9 @@ cc.moveTo = function (duration, position, y) { * @static * @deprecated since v3.0
Please use cc.moveTo instead. * @param {Number} duration duration in seconds - * @param {cc.Point} position + * @param {cc.Point|Number} position * @param {Number} y - * @return {cc.MoveBy} + * @return {cc.MoveTo} */ cc.MoveTo.create = cc.moveTo; From ea5cbd342fdd5b88ca1e85e5ede8322babd71f17 Mon Sep 17 00:00:00 2001 From: Nick Dong Date: Thu, 22 Jun 2017 10:44:09 +0700 Subject: [PATCH 18/65] Fix typo of error message --- cocos2d/core/CCActionManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCActionManager.js b/cocos2d/core/CCActionManager.js index f3c90b46ab..b677944086 100644 --- a/cocos2d/core/CCActionManager.js +++ b/cocos2d/core/CCActionManager.js @@ -116,7 +116,7 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ if(!action) throw new Error("cc.ActionManager.addAction(): action must be non-null"); if(!target) - throw new Error("cc.ActionManager.addAction(): action must be non-null"); + throw new Error("cc.ActionManager.addAction(): target must be non-null"); //check if the action target already exists var element = this._hashTargets[target.__instanceId]; From ad478831538f25b734fbc166ae27895bfc7754cd Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 28 Jun 2017 12:27:20 +0800 Subject: [PATCH 19/65] Add ENABLE_IMAEG_POOL setting --- CCBoot.js | 4 +++- cocos2d/core/textures/TexturesWebGL.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CCBoot.js b/CCBoot.js index 94006c0d1a..06ec6e67df 100644 --- a/CCBoot.js +++ b/CCBoot.js @@ -82,6 +82,8 @@ cc._canvas = null; cc.container = null; cc._gameDiv = null; +window.ENABLE_IMAEG_POOL = true; + /** * Iterate over an object or an array, executing a function for each matched element. * @param {object|array} obj @@ -938,7 +940,7 @@ cc.loader = (function () { delete _queue[url]; } - if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) { + if (ENABLE_IMAEG_POOL && cc._renderType === cc.game.RENDER_TYPE_WEBGL) { imagePool.put(img); } }; diff --git a/cocos2d/core/textures/TexturesWebGL.js b/cocos2d/core/textures/TexturesWebGL.js index 58a2ced557..6505accd52 100644 --- a/cocos2d/core/textures/TexturesWebGL.js +++ b/cocos2d/core/textures/TexturesWebGL.js @@ -496,7 +496,9 @@ cc._tmp.WebGLTexture2D = function () { self._hasPremultipliedAlpha = premultiplied; self._hasMipmaps = false; - self._htmlElementObj = null; + if (ENABLE_IMAEG_POOL) { + self._htmlElementObj = null; + } //dispatch load event to listener. self.dispatchEvent("load"); From d4751be3f300ca90dcfc58c70974c30dfc8db089 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 28 Jun 2017 12:53:14 +0800 Subject: [PATCH 20/65] Small improvements to GLProgramState implementation --- cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js | 2 +- cocos2d/shaders/CCGLProgramState.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js b/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js index 68a3968b90..0506dd522b 100644 --- a/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js +++ b/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js @@ -57,7 +57,7 @@ // to ease the transition from using glPrograms directly, to // using glProgramStates. Object.defineProperty(proto, '_shaderProgram', { - set: function () { this.setShaderProgram.apply(this, arguments); }, + set: function (value) { this.setShaderProgram(value); }, get: function () { return this.getShaderProgram(); } }); })(); diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js index edfa2ae175..0a9cef01cb 100644 --- a/cocos2d/shaders/CCGLProgramState.js +++ b/cocos2d/shaders/CCGLProgramState.js @@ -153,7 +153,6 @@ cc.GLProgramState = function (glprogram) { this._boundTextureUnits = {}; this._textureUnitIndex = 1; // Start at 1, as CC_Texture0 is bound to 0 - var activeUniforms = glprogram._glContext.getProgramParameter(glprogram._programObj, glprogram._glContext.ACTIVE_UNIFORMS); @@ -168,7 +167,7 @@ cc.GLProgramState = function (glprogram) { this._uniforms.push(uniformValue); this._uniformsByName[uniform.name] = count; this._uniformsByLocation[uniform.location] = count; - count++; + count++; } } }; @@ -181,7 +180,10 @@ cc.GLProgramState.prototype = { } for (var i = 0; i < this._uniforms.length; ++i) { - this._uniforms[i].apply(); + var uniform = this._uniforms[i]; + if (uniform._currentBoundValue !== uniform._value) { + uniform.apply(); + } } }, From 34b8218b919e74c9646c28690be2bcdd4aeb303e Mon Sep 17 00:00:00 2001 From: llq <664301573@qq.com> Date: Thu, 29 Jun 2017 09:59:18 +0800 Subject: [PATCH 21/65] web UIButton support BMFont --- extensions/ccui/uiwidgets/UIButton.js | 28 ++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/extensions/ccui/uiwidgets/UIButton.js b/extensions/ccui/uiwidgets/UIButton.js index 4feff73686..af3a868d86 100644 --- a/extensions/ccui/uiwidgets/UIButton.js +++ b/extensions/ccui/uiwidgets/UIButton.js @@ -100,12 +100,22 @@ ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{ } }, - _createTitleRendererIfNeeded: function ( ) { + _createTitleRendererIfNeeded: function (fntFile) { if(!this._titleRenderer) { - this._titleRenderer = new cc.LabelTTF(""); - this._titleRenderer.setAnchorPoint(0.5, 0.5); + if(fntFile != null) + { + this._titleRenderer = new cc.LabelBMFont("", fntFile); + this._titleRenderer.setAlignment(cc.TEXT_ALIGNMENT_CENTER); + } + else + { + this._titleRenderer = new cc.LabelTTF(""); + this._titleRenderer.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER); + } + + this._titleRenderer.setAnchorPoint(0.5, 0.4); this._titleColor = cc.color.WHITE; - this._titleRenderer.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER); + this.addProtectedChild(this._titleRenderer, ccui.Button.TITLE_RENDERER_ZORDER, -1); } }, @@ -657,7 +667,11 @@ ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{ setTitleFontSize: function (size) { this._createTitleRendererIfNeeded(); - this._titleRenderer.setFontSize(size); + if(this._titleRenderer.setFontSize) + this._titleRenderer.setFontSize(size); + else + this._titleRenderer.setBoundingWidth(size); + this._fontSize = size; }, @@ -705,9 +719,9 @@ ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{ * @param {String} fontName */ setTitleFontName: function (fontName) { - this._createTitleRendererIfNeeded(); + this._createTitleRendererIfNeeded(fontName); - this._titleRenderer.setFontName(fontName); + this._titleRenderer.setFontName && this._titleRenderer.setFontName(fontName); this._fontName = fontName; }, From a3f21e4ca534d636d5ebc8d8a9966fa45909435f Mon Sep 17 00:00:00 2001 From: zilongshanren Date: Wed, 5 Jul 2017 14:59:28 +0800 Subject: [PATCH 22/65] improve editbox touch handling --- extensions/editbox/CCEditBox.js | 74 ++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/extensions/editbox/CCEditBox.js b/extensions/editbox/CCEditBox.js index 758f04934f..25963fe24f 100644 --- a/extensions/editbox/CCEditBox.js +++ b/extensions/editbox/CCEditBox.js @@ -154,14 +154,14 @@ cc.EditBoxDelegate = cc.Class.extend({ * This method is called when an edit box gains focus after keyboard is shown. * @param {cc.EditBox} sender */ - editBoxEditingDidBegan: function (sender) { + editBoxEditingDidBegin: function (sender) { }, /** * This method is called when an edit box loses focus after keyboard is hidden. * @param {cc.EditBox} sender */ - editBoxEditingDidEnded: function (sender) { + editBoxEditingDidEnd: function (sender) { }, /** @@ -176,7 +176,7 @@ cc.EditBoxDelegate = cc.Class.extend({ * This method is called when the return button was pressed. * @param {cc.EditBox} sender */ - editBoxEditingReturn: function (sender) { + editBoxReturn: function (sender) { } }); @@ -219,6 +219,8 @@ cc.EditBox = cc.Node.extend({ _placeholderFontSize: 14, _placeholderColor: null, _className: 'EditBox', + _touchListener: null, + _touchEnabled: true, /** * constructor of cc.EditBox @@ -240,16 +242,29 @@ cc.EditBox = cc.Node.extend({ this.initWithSizeAndBackgroundSprite(size, normal9SpriteBg); - cc.eventManager.addListener({ + this._touchListener = cc.EventListener.create({ event: cc.EventListener.TOUCH_ONE_BY_ONE, swallowTouches: true, onTouchBegan: this._onTouchBegan.bind(this), onTouchEnded: this._onTouchEnded.bind(this) - }, this); + }); + cc.eventManager.addListener(this._touchListener, this); this.setInputFlag(this._editBoxInputFlag); }, + setTouchEnabled: function (enable) { + if (this._touchEnabled === enable) { + return; + } + this._touchEnabled = enable; + if (this._touchEnabled) { + cc.eventManager.addListener(this._touchListener, this); + } else { + cc.eventManager.removeListener(this._touchListener); + } + }, + _createRenderCmd: function () { if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) { return new cc.EditBox.CanvasRenderCmd(this); @@ -319,7 +334,21 @@ cc.EditBox = cc.Node.extend({ this._renderCmd._removeDomInputControl(); }, + _isAncestorsVisible: function (node) { + if (null == node) + return true; + + var parent = node.getParent(); + + if (parent && !parent.isVisible()) + return false; + return this._isAncestorsVisible(parent); + }, + _onTouchBegan: function (touch) { + if (!this.isVisible() || !this._isAncestorsVisible(this)) { + return; + } var touchPoint = touch.getLocation(); var bb = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); var hitted = cc.rectContainsPoint(bb, this.convertToNodeSpace(touchPoint)); @@ -333,6 +362,9 @@ cc.EditBox = cc.Node.extend({ }, _onTouchEnded: function () { + if (!this.isVisible() || !this._isAncestorsVisible(this)) { + return; + } this._renderCmd.show(); }, @@ -822,8 +854,8 @@ cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9Sp editBox._text = this.value; thisPointer._updateEditBoxContentStyle(); thisPointer.hidden(); - if (editBox._delegate && editBox._delegate.editBoxEditingReturn) { - editBox._delegate.editBoxEditingReturn(editBox); + if (editBox._delegate && editBox._delegate.editBoxReturn) { + editBox._delegate.editBoxReturn(editBox); } cc._canvas.focus(); } @@ -845,10 +877,12 @@ cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9Sp this.__autoResize = cc.view.__resizeWithBrowserSize; cc.view.resizeWithBrowserSize(false); - scrollWindowUp(editBox); + if (cc.sys.isMobile) { + scrollWindowUp(editBox); + } - if (editBox._delegate && editBox._delegate.editBoxEditingDidBegan) { - editBox._delegate.editBoxEditingDidBegan(editBox); + if (editBox._delegate && editBox._delegate.editBoxEditingDidBegin) { + editBox._delegate.editBoxEditingDidBegin(editBox); } }); tmpEdTxt.addEventListener('blur', function () { @@ -862,8 +896,8 @@ cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9Sp cc.view.resizeWithBrowserSize(true); } window.scrollY = 0; - if (editBox._delegate && editBox._delegate.editBoxEditingDidEnded) { - editBox._delegate.editBoxEditingDidEnded(editBox); + if (editBox._delegate && editBox._delegate.editBoxEditingDidEnd) { + editBox._delegate.editBoxEditingDidEnd(editBox); } if (this.value === '') { @@ -930,10 +964,12 @@ cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9Sp this.__autoResize = cc.view.__resizeWithBrowserSize; cc.view.resizeWithBrowserSize(false); - scrollWindowUp(editBox); + if (cc.sys.isMobile) { + scrollWindowUp(editBox); + } - if (editBox._delegate && editBox._delegate.editBoxEditingDidBegan) { - editBox._delegate.editBoxEditingDidBegan(editBox); + if (editBox._delegate && editBox._delegate.editBoxEditingDidBegin) { + editBox._delegate.editBoxEditingDidBegin(editBox); } }); @@ -943,8 +979,8 @@ cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9Sp if (e.keyCode === cc.KEY.enter) { e.stopPropagation(); - if (editBox._delegate && editBox._delegate.editBoxEditingReturn) { - editBox._delegate.editBoxEditingReturn(editBox); + if (editBox._delegate && editBox._delegate.editBoxReturn) { + editBox._delegate.editBoxReturn(editBox); } } }); @@ -960,8 +996,8 @@ cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9Sp cc.view.resizeWithBrowserSize(true); } - if (editBox._delegate && editBox._delegate.editBoxEditingDidEnded) { - editBox._delegate.editBoxEditingDidEnded(editBox); + if (editBox._delegate && editBox._delegate.editBoxEditingDidEnd) { + editBox._delegate.editBoxEditingDidEnd(editBox); } if (this.value === '') { From 1fa0ac444d3f29019da5df2779ebd362dbec5f4d Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 13 Jul 2017 18:20:49 +0800 Subject: [PATCH 23/65] Improve renderer webgl to support mesh rendering --- cocos2d/core/platform/CCMacro.js | 7 +++ cocos2d/core/renderer/RendererWebGL.js | 62 ++++++++------------------ 2 files changed, 25 insertions(+), 44 deletions(-) diff --git a/cocos2d/core/platform/CCMacro.js b/cocos2d/core/platform/CCMacro.js index 5bb6eb7ab7..a52958c3dc 100644 --- a/cocos2d/core/platform/CCMacro.js +++ b/cocos2d/core/platform/CCMacro.js @@ -499,6 +499,13 @@ cc.ORIENTATION_AUTO = 3; */ cc.CONCURRENCY_HTTP_REQUEST_COUNT = cc.sys.isMobile ? 20 : 0; +/** + * The maximum vertex count for a single batched draw call. + * @constant + * @type Number + */ +cc.BATCH_VERTEX_COUNT = 2000; + // ------------------- vertex attrib flags ----------------------------- /** diff --git a/cocos2d/core/renderer/RendererWebGL.js b/cocos2d/core/renderer/RendererWebGL.js index 7df0452993..d0655f6f28 100644 --- a/cocos2d/core/renderer/RendererWebGL.js +++ b/cocos2d/core/renderer/RendererWebGL.js @@ -33,7 +33,7 @@ var _batchedInfo = { blendSrc: null, // The batched blend destination, all batching element should have the same blend destination blendDst: null, - // The batched glProgramState, all batching element should have the same glProgramState + // The batched gl program state, all batching element should have the same state glProgramState: null }, @@ -129,7 +129,7 @@ return { _cacheToBufferCmds: {}, // an array saves the renderer commands need for cache to other canvas _cacheInstanceIds: [], _currentID: 0, - _clearColor: cc.color(), //background color,default BLACK + _clearColor: cc.color(0, 0, 0, 255), //background color,default BLACK init: function () { var gl = cc._renderContext; @@ -138,7 +138,7 @@ return { this.mat4Identity = new cc.math.Matrix4(); this.mat4Identity.identity(); - initQuadBuffer(2000); + initQuadBuffer(cc.BATCH_VERTEX_COUNT); if (cc.sys.os === cc.sys.OS_IOS) { _IS_IOS = true; } @@ -313,18 +313,23 @@ return { _batchingSize += increment; }, - _updateBatchedInfo: function (texture, blendFunc, shaderProgram) { - if (texture) { + _updateBatchedInfo: function (texture, blendFunc, glProgramState) { + if (texture !== _batchedInfo.texture || + blendFunc.src !== _batchedInfo.blendSrc || + blendFunc.dst !== _batchedInfo.blendDst || + glProgramState !== _batchedInfo.glProgramState) { + // Draw batched elements + this._batchRendering(); + // Update _batchedInfo _batchedInfo.texture = texture; - } - - if (blendFunc) { _batchedInfo.blendSrc = blendFunc.src; _batchedInfo.blendDst = blendFunc.dst; - } + _batchedInfo.glProgramState = glProgramState; - if (shaderProgram) { - _batchedInfo.shader = shaderProgram; + return true; + } + else { + return false; } }, @@ -339,7 +344,7 @@ return { // Check batching var node = cmd._node; - var texture = node._texture || (node._spriteFrame ? node._spriteFrame._texture : null); + var texture = node._texture || (node._spriteFrame && node._spriteFrame._texture); var blendSrc = node._blendFunc.src; var blendDst = node._blendFunc.dst; var glProgramState = cmd._glProgramState; @@ -361,38 +366,7 @@ return { // Upload vertex data var len = cmd.uploadData(_vertexDataF32, _vertexDataUI32, _batchingSize * _sizePerVertex); if (len > 0) { - var i, curr, type = cmd.vertexType || VertexType.QUAD; - switch (type) { - case VertexType.QUAD: - for (i = 0; i < len; i += 4) { - curr = _batchingSize + i; - _indexData[_indexSize++] = curr + 0; - _indexData[_indexSize++] = curr + 1; - _indexData[_indexSize++] = curr + 2; - _indexData[_indexSize++] = curr + 1; - _indexData[_indexSize++] = curr + 2; - _indexData[_indexSize++] = curr + 3; - } - break; - case VertexType.TRIANGLE: - _pureQuad = false; - for (i = 0; i < len; i += 3) { - curr = _batchingSize + i; - _indexData[_indexSize++] = curr + 0; - _indexData[_indexSize++] = curr + 1; - _indexData[_indexSize++] = curr + 2; - } - break; - case VertexType.CUSTOM: - _pureQuad = false; - if (cmd.uploadIndexData) { - _indexSize += cmd.uploadIndexData(_indexData, _indexSize, _batchingSize); - } - break; - default: - return; - } - _batchingSize += len; + this._increaseBatchingSize(len, cmd.vertexType); } }, From aa69d8c336b5fba6048539cc84b5615116e32245 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 13 Jul 2017 18:21:16 +0800 Subject: [PATCH 24/65] Improve ActionManager performance and fix memory leak caused by element pool --- cocos2d/core/CCActionManager.js | 80 +++++++++------------------------ 1 file changed, 20 insertions(+), 60 deletions(-) diff --git a/cocos2d/core/CCActionManager.js b/cocos2d/core/CCActionManager.js index f3c90b46ab..9ecc3c4886 100644 --- a/cocos2d/core/CCActionManager.js +++ b/cocos2d/core/CCActionManager.js @@ -30,25 +30,13 @@ * @example * var element = new cc.HashElement(); */ -cc.HashElement = cc.Class.extend(/** @lends cc.HashElement# */{ - actions:null, - target:null, //ccobject - actionIndex:0, - currentAction:null, //CCAction - currentActionSalvaged:false, - paused:false, - /** - * Constructor - */ - ctor:function () { - this.actions = []; - this.target = null; - this.actionIndex = 0; - this.currentAction = null; //CCAction - this.currentActionSalvaged = false; - this.paused = false; - } -}); +cc.HashElement = function () { + this.actions = []; + this.target = null; + this.actionIndex = 0; + this.currentAction = null; //CCAction + this.paused = false; +}; /** * cc.ActionManager is a class that can manage actions.
@@ -64,10 +52,6 @@ cc.HashElement = cc.Class.extend(/** @lends cc.HashElement# */{ * var mng = new cc.ActionManager(); */ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ - _hashTargets:null, - _arrayTargets:null, - _currentTarget:null, - _currentTargetSalvaged:false, _elementPool: [], _searchElementByTarget:function (arr, target) { @@ -82,7 +66,6 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ this._hashTargets = {}; this._arrayTargets = []; this._currentTarget = null; - this._currentTargetSalvaged = false; }, _getElement: function (target, paused) { @@ -99,8 +82,8 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ element.actions.length = 0; element.actionIndex = 0; element.currentAction = null; - element.currentActionSalvaged = false; element.paused = false; + element.target = null; this._elementPool.push(element); }, @@ -156,15 +139,8 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ return; var element = this._hashTargets[target.__instanceId]; if (element) { - if (element.actions.indexOf(element.currentAction) !== -1 && !(element.currentActionSalvaged)) - element.currentActionSalvaged = true; - element.actions.length = 0; - if (this._currentTarget === element && !forceDelete) { - this._currentTargetSalvaged = true; - } else { - this._deleteHashElement(element); - } + this._deleteHashElement(element); } }, /** Removes an action given an action reference. @@ -181,6 +157,9 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ for (var i = 0; i < element.actions.length; i++) { if (element.actions[i] === action) { element.actions.splice(i, 1); + // update actionIndex in case we are in tick. looping over the actions + if (element.actionIndex >= i) + element.actionIndex--; break; } } @@ -291,10 +270,10 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ * @param {Array} targetsToResume */ resumeTargets:function(targetsToResume){ - if(!targetsToResume) + if (!targetsToResume) return; - for(var i = 0 ; i< targetsToResume.length; i++){ + for (var i = 0; i< targetsToResume.length; i++) { if(targetsToResume[i]) this.resumeTarget(targetsToResume[i]); } @@ -311,9 +290,6 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ _removeActionAtIndex:function (index, element) { var action = element.actions[index]; - if ((action === element.currentAction) && (!element.currentActionSalvaged)) - element.currentActionSalvaged = true; - element.actions.splice(index, 1); // update actionIndex in case we are in tick. looping over the actions @@ -321,11 +297,7 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ element.actionIndex--; if (element.actions.length === 0) { - if (this._currentTarget === element) { - this._currentTargetSalvaged = true; - } else { - this._deleteHashElement(element); - } + this._deleteHashElement(element); } }, @@ -356,25 +328,17 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ for (var elt = 0; elt < locTargets.length; elt++) { this._currentTarget = locTargets[elt]; locCurrTarget = this._currentTarget; - //this._currentTargetSalvaged = false; - if (!locCurrTarget.paused) { + if (!locCurrTarget.paused && locCurrTarget.actions) { // The 'actions' CCMutableArray may change while inside this loop. - for (locCurrTarget.actionIndex = 0; - locCurrTarget.actionIndex < (locCurrTarget.actions ? locCurrTarget.actions.length : 0); - locCurrTarget.actionIndex++) { + for (locCurrTarget.actionIndex = 0; locCurrTarget.actionIndex < locCurrTarget.actions.length; locCurrTarget.actionIndex++) { locCurrTarget.currentAction = locCurrTarget.actions[locCurrTarget.actionIndex]; if (!locCurrTarget.currentAction) continue; - locCurrTarget.currentActionSalvaged = false; //use for speed locCurrTarget.currentAction.step(dt * ( locCurrTarget.currentAction._speedMethod ? locCurrTarget.currentAction._speed : 1 ) ); - if (locCurrTarget.currentActionSalvaged) { - // The currentAction told the node to remove it. To prevent the action from - // accidentally deallocating itself before finishing its step, we retained - // it. Now that step is done, it's safe to release it. - locCurrTarget.currentAction = null;//release - } else if (locCurrTarget.currentAction.isDone()) { + + if (locCurrTarget.currentAction.isDone()) { locCurrTarget.currentAction.stop(); var action = locCurrTarget.currentAction; // Make currentAction nil to prevent removeAction from salvaging it. @@ -385,12 +349,8 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ locCurrTarget.currentAction = null; } } - - // elt, at this moment, is still valid - // so it is safe to ask this here (issue #490) - // only delete currentTarget if no actions were scheduled during the cycle (issue #481) - if (this._currentTargetSalvaged && locCurrTarget.actions.length === 0) { + if (locCurrTarget.actions.length === 0) { this._deleteHashElement(locCurrTarget) && elt--; } } From c44b97cb3ca37fcf44ea3a9b6bd1120e442968ce Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 13 Jul 2017 18:21:49 +0800 Subject: [PATCH 25/65] Improve spine rendering --- cocos2d/core/textures/CCTexture2D.js | 1 - extensions/spine/CCSkeleton.js | 54 +- extensions/spine/CCSkeletonAnimation.js | 25 +- extensions/spine/CCSkeletonCanvasRenderCmd.js | 400 +++++++------- extensions/spine/CCSkeletonTexture.js | 13 +- extensions/spine/CCSkeletonWebGLRenderCmd.js | 522 +++++++++--------- extensions/spine/LICENSE | 27 + extensions/spine/Spine.js | 13 +- 8 files changed, 558 insertions(+), 497 deletions(-) create mode 100644 extensions/spine/LICENSE diff --git a/cocos2d/core/textures/CCTexture2D.js b/cocos2d/core/textures/CCTexture2D.js index b80aec1274..b69d83cfd9 100644 --- a/cocos2d/core/textures/CCTexture2D.js +++ b/cocos2d/core/textures/CCTexture2D.js @@ -190,7 +190,6 @@ cc.game.addEventListener(cc.game.EVENT_RENDERER_INITED, function () { */ handleLoadedTexture: function () { var self = this; - if (self._textureLoaded) return; if (!self._htmlElementObj) { return; } diff --git a/extensions/spine/CCSkeleton.js b/extensions/spine/CCSkeleton.js index d7f35ebf71..eec8aa2fbb 100644 --- a/extensions/spine/CCSkeleton.js +++ b/extensions/spine/CCSkeleton.js @@ -59,6 +59,8 @@ sp.ATTACHMENT_TYPE = { SKINNED_MESH:3 }; +var spine = sp.spine; + /** *

* The skeleton of Spine.
@@ -78,7 +80,6 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ _premultipliedAlpha: false, _ownsSkeletonData: null, _atlas: null, - _blendFunc: null, /** * The constructor of sp.Skeleton. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function. @@ -105,7 +106,6 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ init: function () { cc.Node.prototype.init.call(this); this._premultipliedAlpha = (cc._renderType === cc.game.RENDER_TYPE_WEBGL && cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA); - this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST}; this.scheduleUpdate(); }, @@ -171,7 +171,7 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ /** * Initializes sp.Skeleton with Data. - * @param {spine.SkeletonData|String} skeletonDataFile + * @param {sp.spine.SkeletonData|String} skeletonDataFile * @param {String|spine.Atlas|spine.SkeletonData} atlasFile atlas filename or atlas data or owns SkeletonData * @param {Number} [scale] scale can be specified on the JSON or binary loader which will scale the bone positions, image sizes, and animation translations. */ @@ -211,13 +211,13 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ */ getBoundingBox: function () { var minX = cc.FLT_MAX, minY = cc.FLT_MAX, maxX = cc.FLT_MIN, maxY = cc.FLT_MIN; - var scaleX = this.getScaleX(), scaleY = this.getScaleY(), vertices = [], + var scaleX = this.getScaleX(), scaleY = this.getScaleY(), vertices, slots = this._skeleton.slots, VERTEX = spine.RegionAttachment; for (var i = 0, slotCount = slots.length; i < slotCount; ++i) { var slot = slots[i]; var attachment = slot.attachment; - if (!attachment || ! (attachment instanceof spine.RegionAttachment)) + if (!attachment || !(attachment instanceof spine.RegionAttachment)) continue; vertices = attachment.updateWorldVertices(slot, false); minX = Math.min(minX, vertices[VERTEX.X1] * scaleX, vertices[VERTEX.X4] * scaleX, vertices[VERTEX.X2] * scaleX, vertices[VERTEX.X3] * scaleX); @@ -260,7 +260,7 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ /** * Finds a bone by name. This does a string comparison for every bone. * @param {String} boneName - * @returns {spine.Bone} + * @returns {sp.spine.Bone} */ findBone: function (boneName) { return this._skeleton.findBone(boneName); @@ -269,7 +269,7 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ /** * Finds a slot by name. This does a string comparison for every slot. * @param {String} slotName - * @returns {spine.Slot} + * @returns {sp.spine.Slot} */ findSlot: function (slotName) { return this._skeleton.findSlot(slotName); @@ -278,7 +278,7 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ /** * Finds a skin by name and makes it the active skin. This does a string comparison for every skin. Note that setting the skin does not change which attachments are visible. * @param {string} skinName - * @returns {spine.Skin} + * @returns {sp.spine.Skin} */ setSkin: function (skinName) { return this._skeleton.setSkinByName(skinName); @@ -288,7 +288,7 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ * Returns the attachment for the slot and attachment name. The skeleton looks first in its skin, then in the skeleton data’s default skin. * @param {String} slotName * @param {String} attachmentName - * @returns {spine.RegionAttachment|spine.BoundingBoxAttachment} + * @returns {sp.spine.Attachment} */ getAttachment: function (slotName, attachmentName) { return this._skeleton.getAttachmentByName(slotName, attachmentName); @@ -321,8 +321,8 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ /** * Sets skeleton data to sp.Skeleton. - * @param {spine.SkeletonData} skeletonData - * @param {spine.SkeletonData} ownsSkeletonData + * @param {sp.spine.SkeletonData} skeletonData + * @param {sp.spine.SkeletonData} ownsSkeletonData */ setSkeletonData: function (skeletonData, ownsSkeletonData) { if(skeletonData.width != null && skeletonData.height != null) @@ -338,8 +338,8 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ /** * Return the renderer of attachment. - * @param {spine.RegionAttachment|spine.BoundingBoxAttachment} regionAttachment - * @returns {cc.Node} + * @param {sp.spine.RegionAttachment|sp.spine.BoundingBoxAttachment} regionAttachment + * @returns {sp.spine.TextureAtlasRegion} */ getTextureAtlas: function (regionAttachment) { return regionAttachment.region; @@ -350,23 +350,23 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ * @returns {cc.BlendFunc} */ getBlendFunc: function () { - return this._blendFunc; + var slot = this._skeleton.drawOrder[0]; + if (slot) { + var blend = this._renderCmd._getBlendFunc(slot.data.blendMode, this._premultipliedAlpha); + return blend; + } + else { + return {}; + } }, /** - * Sets the blendFunc of sp.Skeleton. + * Sets the blendFunc of sp.Skeleton, it won't have any effect for skeleton, skeleton is using slot's data to determine the blend function. * @param {cc.BlendFunc|Number} src * @param {Number} [dst] */ setBlendFunc: function (src, dst) { - var locBlendFunc = this._blendFunc; - if (dst === undefined) { - locBlendFunc.src = src.src; - locBlendFunc.dst = src.dst; - } else { - locBlendFunc.src = src; - locBlendFunc.dst = dst; - } + return; }, /** @@ -378,6 +378,14 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ } }); +cc.defineGetterSetter(sp.Skeleton.prototype, "opacityModifyRGB", sp.Skeleton.prototype.isOpacityModifyRGB); + +// For renderer webgl to identify skeleton's default texture and blend function +cc.defineGetterSetter(sp.Skeleton.prototype, "_blendFunc", sp.Skeleton.prototype.getBlendFunc); +cc.defineGetterSetter(sp.Skeleton.prototype, '_texture', function () { + return this._renderCmd._currTexture; +}); + /** * Creates a skeleton object. * @deprecated since v3.0, please use new sp.Skeleton(skeletonDataFile, atlasFile, scale) instead. diff --git a/extensions/spine/CCSkeletonAnimation.js b/extensions/spine/CCSkeletonAnimation.js index 339bd08f15..17f0f25675 100644 --- a/extensions/spine/CCSkeletonAnimation.js +++ b/extensions/spine/CCSkeletonAnimation.js @@ -32,8 +32,7 @@ sp._atlasLoader = { load:function(line){ var texturePath = cc.path.join(cc.path.dirname(this.spAtlasFile), line); var texture = cc.textureCache.addImage(texturePath); - var tex = new sp.SkeletonTexture(); - tex._image = { width: texture.getPixelsWide(), height: texture.getPixelsHigh() }; + var tex = new sp.SkeletonTexture({ width: texture.getPixelsWide(), height: texture.getPixelsHigh() }); tex.setRealTexture(texture); return tex; }, @@ -55,7 +54,7 @@ sp.ANIMATION_EVENT_TYPE = { EVENT: 5 }; -sp.TrackEntryListeners = function(startListener, endListener, completeListener, eventListener, interruptListener, disposeListener){ +sp.TrackEntryListeners = function (startListener, endListener, completeListener, eventListener, interruptListener, disposeListener) { this.startListener = startListener || null; this.endListener = endListener || null; this.completeListener = completeListener || null; @@ -156,7 +155,7 @@ sp.SkeletonAnimation = sp.Skeleton.extend(/** @lends sp.SkeletonAnimation# */{ /** * Sets animation state data to sp.SkeletonAnimation. - * @param {spine.AnimationStateData} stateData + * @param {sp.spine.AnimationStateData} stateData */ setAnimationStateData: function (stateData) { var state = new spine.AnimationState(stateData); @@ -192,7 +191,7 @@ sp.SkeletonAnimation = sp.Skeleton.extend(/** @lends sp.SkeletonAnimation# */{ * @param {Number} trackIndex * @param {String} name * @param {Boolean} loop - * @returns {spine.TrackEntry|null} + * @returns {sp.spine.TrackEntry|null} */ setAnimation: function (trackIndex, name, loop) { var animation = this._skeleton.data.findAnimation(name); @@ -209,7 +208,7 @@ sp.SkeletonAnimation = sp.Skeleton.extend(/** @lends sp.SkeletonAnimation# */{ * @param {String} name * @param {Boolean} loop * @param {Number} [delay=0] - * @returns {spine.TrackEntry|null} + * @returns {sp.spine.TrackEntry|null} */ addAnimation: function (trackIndex, name, loop, delay) { delay = delay == null ? 0 : delay; @@ -221,10 +220,19 @@ sp.SkeletonAnimation = sp.Skeleton.extend(/** @lends sp.SkeletonAnimation# */{ return this._state.addAnimationWith(trackIndex, animation, loop, delay); }, + /** + * Find animation with specified name + * @param {String} name + * @returns {sp.spine.Animation|null} + */ + findAnimation: function (name) { + return this._skeleton.data.findAnimation(name); + }, + /** * Returns track entry by trackIndex. * @param trackIndex - * @returns {spine.TrackEntry|null} + * @returns {sp.spine.TrackEntry|null} */ getCurrent: function (trackIndex) { return this._state.getCurrent(trackIndex); @@ -254,6 +262,7 @@ sp.SkeletonAnimation = sp.Skeleton.extend(/** @lends sp.SkeletonAnimation# */{ update: function (dt) { this._super(dt); dt *= this._timeScale; + this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.contentDirty); this._state.update(dt); this._state.apply(this._skeleton); this._skeleton.updateWorldTransform(); @@ -339,4 +348,4 @@ sp.SkeletonAnimation = sp.Skeleton.extend(/** @lends sp.SkeletonAnimation# */{ */ sp.SkeletonAnimation.createWithJsonFile = sp.SkeletonAnimation.create = function (skeletonDataFile, atlasFile/* or atlas*/, scale) { return new sp.SkeletonAnimation(skeletonDataFile, atlasFile, scale); -}; \ No newline at end of file +}; diff --git a/extensions/spine/CCSkeletonCanvasRenderCmd.js b/extensions/spine/CCSkeletonCanvasRenderCmd.js index 2b20f3f97c..0c37adb83d 100644 --- a/extensions/spine/CCSkeletonCanvasRenderCmd.js +++ b/extensions/spine/CCSkeletonCanvasRenderCmd.js @@ -23,208 +23,224 @@ ****************************************************************************/ (function () { - sp.Skeleton.CanvasRenderCmd = function (renderableObject) { - this._rootCtor(renderableObject); - this._needDraw = true; - }; - - var proto = sp.Skeleton.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype); - proto.constructor = sp.Skeleton.CanvasRenderCmd; - - proto.rendering = function (wrapper, scaleX, scaleY) { - var node = this._node, i, n, slot, slotNode; - wrapper = wrapper || cc._renderContext; - - var locSkeleton = node._skeleton, drawOrder = locSkeleton.drawOrder; - for (i = 0, n = drawOrder.length; i < n; i++) { - slot = drawOrder[i]; - slotNode = slot._slotNode; - if (slotNode._visible && slotNode._renderCmd && slot.currentSprite) { - slotNode._renderCmd.transform(this, true); - slot.currentSprite._renderCmd.rendering(wrapper, scaleX, scaleY); - slotNode._renderCmd._dirtyFlag = slot.currentSprite._renderCmd._dirtyFlag = 0; - } - } - if (!node._debugSlots && !node._debugBones) - return; - - wrapper.setTransform(this._worldTransform, scaleX, scaleY); - wrapper.setGlobalAlpha(1); - var attachment, drawingUtil = cc._drawingUtil; - if (node._debugSlots) { - // Slots. - drawingUtil.setDrawColor(0, 0, 255, 255); - drawingUtil.setLineWidth(1); - - var points = []; - for (i = 0, n = locSkeleton.slots.length; i < n; i++) { - slot = locSkeleton.drawOrder[i]; - if (!slot.attachment || !(slot.attachment instanceof spine.RegionAttachment)) - continue; - attachment = slot.attachment; - this._updateRegionAttachmentSlot(attachment, slot, points); - drawingUtil.drawPoly(points, 4, true); - } - } +var spine = sp.spine; - if (node._debugBones) { - // Bone lengths. - var bone; - drawingUtil.setLineWidth(2); - drawingUtil.setDrawColor(255, 0, 0, 255); - - for (i = 0, n = locSkeleton.bones.length; i < n; i++) { - bone = locSkeleton.bones[i]; - var x = bone.data.length * bone.a + bone.worldX; - var y = bone.data.length * bone.c + bone.worldY; - drawingUtil.drawLine( - {x: bone.worldX, y: bone.worldY}, - {x: x, y: y}); - } +sp.Skeleton.CanvasRenderCmd = function (renderableObject) { + this._rootCtor(renderableObject); + this._needDraw = true; +}; - // Bone origins. - drawingUtil.setPointSize(4); - drawingUtil.setDrawColor(0, 0, 255, 255); // Root bone is blue. +var proto = sp.Skeleton.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype); +proto.constructor = sp.Skeleton.CanvasRenderCmd; - for (i = 0, n = locSkeleton.bones.length; i < n; i++) { - bone = locSkeleton.bones[i]; - drawingUtil.drawPoint({x: bone.worldX, y: bone.worldY}); - if (i === 0) - drawingUtil.setDrawColor(0, 255, 0, 255); - } +proto.rendering = function (wrapper, scaleX, scaleY) { + var node = this._node, i, n, slot, slotNode; + wrapper = wrapper || cc._renderContext; + + var locSkeleton = node._skeleton, drawOrder = locSkeleton.drawOrder; + for (i = 0, n = drawOrder.length; i < n; i++) { + slot = drawOrder[i]; + slotNode = slot._slotNode; + if (slotNode._visible && slotNode._renderCmd && slot.currentSprite) { + slotNode._renderCmd.transform(this, true); + slot.currentSprite._renderCmd.rendering(wrapper, scaleX, scaleY); + slotNode._renderCmd._dirtyFlag = slot.currentSprite._renderCmd._dirtyFlag = 0; } - }; - - proto._updateRegionAttachmentSlot = function (attachment, slot, points) { - if (!points) - return; - - var vertices = attachment.updateWorldVertices(slot, false); - var VERTEX = spine.RegionAttachment; - points.length = 0; - points.push(cc.p(vertices[VERTEX.X1], vertices[VERTEX.Y1])); - points.push(cc.p(vertices[VERTEX.X4], vertices[VERTEX.Y4])); - points.push(cc.p(vertices[VERTEX.X3], vertices[VERTEX.Y3])); - points.push(cc.p(vertices[VERTEX.X2], vertices[VERTEX.Y2])); - }; - - proto._createChildFormSkeletonData = function () { - var node = this._node; - var locSkeleton = node._skeleton, spriteName, sprite; - for (var i = 0, n = locSkeleton.slots.length; i < n; i++) { - var slot = locSkeleton.slots[i], attachment = slot.attachment; - var slotNode = new cc.Node(); - slot._slotNode = slotNode; - - if (attachment instanceof spine.RegionAttachment) { - spriteName = attachment.region.name; - sprite = this._createSprite(slot, attachment); - slot.currentSprite = sprite; - slot.currentSpriteName = spriteName; - slotNode.addChild(sprite); - } else if (attachment instanceof spine.MeshAttachment) { - //todo for mesh - } + } + + if (!node._debugSlots && !node._debugBones) + return; + + wrapper.setTransform(this._worldTransform, scaleX, scaleY); + wrapper.setGlobalAlpha(1); + var attachment, drawingUtil = cc._drawingUtil; + if (node._debugSlots) { + // Slots. + drawingUtil.setDrawColor(0, 0, 255, 255); + drawingUtil.setLineWidth(1); + + var points = []; + for (i = 0, n = locSkeleton.slots.length; i < n; i++) { + slot = locSkeleton.drawOrder[i]; + if (!slot.attachment || !(slot.attachment instanceof spine.RegionAttachment)) + continue; + attachment = slot.attachment; + this._updateRegionAttachmentSlot(attachment, slot, points); + drawingUtil.drawPoly(points, 4, true); } - }; - - var loaded = function (sprite, texture, rendererObject, attachment) { - var rect = new cc.Rect(rendererObject.x, rendererObject.y, rendererObject.width, rendererObject.height); - sprite.initWithTexture(texture, rect, rendererObject.rotate, false); - sprite._rect.width = attachment.width; - sprite._rect.height = attachment.height; - sprite.setContentSize(attachment.width, attachment.height); - sprite.setRotation(-attachment.rotation); - sprite.setScale(rendererObject.width / rendererObject.originalWidth * attachment.scaleX, - rendererObject.height / rendererObject.originalHeight * attachment.scaleY); - }; - - proto._createSprite = function (slot, attachment) { - var rendererObject = attachment.region; - var texture = rendererObject.texture.getRealTexture(); - var sprite = new cc.Sprite(); - if (texture.isLoaded()) { - loaded(sprite, texture, rendererObject, attachment); - } else { - texture.addEventListener('load', function () { - loaded(sprite, texture, rendererObject, attachment); - }, this); + } + + if (node._debugBones) { + // Bone lengths. + var bone; + drawingUtil.setLineWidth(2); + drawingUtil.setDrawColor(255, 0, 0, 255); + + for (i = 0, n = locSkeleton.bones.length; i < n; i++) { + bone = locSkeleton.bones[i]; + var x = bone.data.length * bone.a + bone.worldX; + var y = bone.data.length * bone.c + bone.worldY; + drawingUtil.drawLine( + {x: bone.worldX, y: bone.worldY}, + {x: x, y: y}); } - slot.sprites = slot.sprites || {}; - slot.sprites[rendererObject.name] = sprite; - return sprite; - }; - - proto._updateChild = function () { - var locSkeleton = this._node._skeleton, slots = locSkeleton.slots; - var color = this._displayedColor, opacity = this._displayedOpacity; - var i, n, selSprite, ax, ay; - - var slot, attachment, slotNode; - for (i = 0, n = slots.length; i < n; i++) { - slot = slots[i]; - attachment = slot.attachment; - slotNode = slot._slotNode; - if (!attachment) { - slotNode.setVisible(false); - continue; - } - if (attachment instanceof spine.RegionAttachment){ - if (attachment.region) { - if (!slot.currentSpriteName || slot.currentSpriteName !== attachment.name) { - var spriteName = attachment.region.name; - if (slot.currentSprite !== undefined) - slot.currentSprite.setVisible(false); - slot.sprites = slot.sprites || {}; - if (slot.sprites[spriteName] !== undefined) - slot.sprites[spriteName].setVisible(true); - else { - var sprite = this._createSprite(slot, attachment); - slotNode.addChild(sprite); - } - slot.currentSprite = slot.sprites[spriteName]; - slot.currentSpriteName = spriteName; + + // Bone origins. + drawingUtil.setPointSize(4); + drawingUtil.setDrawColor(0, 0, 255, 255); // Root bone is blue. + + for (i = 0, n = locSkeleton.bones.length; i < n; i++) { + bone = locSkeleton.bones[i]; + drawingUtil.drawPoint({x: bone.worldX, y: bone.worldY}); + if (i === 0) + drawingUtil.setDrawColor(0, 255, 0, 255); + } + } +}; + +proto.updateStatus = function() { + this.originUpdateStatus(); + this._updateCurrentRegions(); + this._regionFlag = _ccsg.Node.CanvasRenderCmd.RegionStatus.DirtyDouble; + this._dirtyFlag &= ~_ccsg.Node._dirtyFlags.contentDirty; +}; + +proto.getLocalBB = function() { + return this._node.getBoundingBox(); +}; + +proto._updateRegionAttachmentSlot = function (attachment, slot, points) { + if (!points) + return; + + var vertices = attachment.updateWorldVertices(slot, false); + var VERTEX = spine.RegionAttachment; + points.length = 0; + points.push(cc.p(vertices[VERTEX.X1], vertices[VERTEX.Y1])); + points.push(cc.p(vertices[VERTEX.X4], vertices[VERTEX.Y4])); + points.push(cc.p(vertices[VERTEX.X3], vertices[VERTEX.Y3])); + points.push(cc.p(vertices[VERTEX.X2], vertices[VERTEX.Y2])); +}; + +proto._createChildFormSkeletonData = function () { + var node = this._node; + var locSkeleton = node._skeleton, spriteName, sprite; + for (var i = 0, n = locSkeleton.slots.length; i < n; i++) { + var slot = locSkeleton.slots[i], attachment = slot.attachment; + var slotNode = new cc.Node(); + slot._slotNode = slotNode; + + if (attachment instanceof spine.RegionAttachment) { + spriteName = attachment.region.name; + sprite = this._createSprite(slot, attachment); + slot.currentSprite = sprite; + slot.currentSpriteName = spriteName; + slotNode.addChild(sprite); + } else if (attachment instanceof spine.MeshAttachment) { + //todo for mesh + } + } +}; + +var loaded = function (sprite, texture, attachment) { + var rendererObject = attachment.region; + var rect = new cc.Rect(rendererObject.x, rendererObject.y, rendererObject.width, rendererObject.height); + sprite.initWithTexture(texture, rect, rendererObject.rotate, false); + sprite._rect.width = attachment.width; + sprite._rect.height = attachment.height; + sprite.setContentSize(attachment.width, attachment.height); + sprite.setRotation(-attachment.rotation); + sprite.setScale(rendererObject.width / rendererObject.originalWidth * attachment.scaleX, + rendererObject.height / rendererObject.originalHeight * attachment.scaleY); +}; + +proto._createSprite = function (slot, attachment) { + var rendererObject = attachment.region; + var texture = rendererObject.texture.getRealTexture(); + var sprite = new cc.Sprite(); + if (texture.isLoaded()) { + loaded(sprite, texture, attachment); + } else { + texture.addEventListener('load', function () { + loaded(sprite, texture, attachment); + }, this); + } + slot.sprites = slot.sprites || {}; + slot.sprites[rendererObject.name] = sprite; + return sprite; +}; + +proto._updateChild = function () { + var locSkeleton = this._node._skeleton, slots = locSkeleton.slots; + var color = this._displayedColor, opacity = this._displayedOpacity; + var i, n, selSprite, ax, ay; + + var slot, attachment, slotNode; + for (i = 0, n = slots.length; i < n; i++) { + slot = slots[i]; + attachment = slot.attachment; + slotNode = slot._slotNode; + if (!attachment) { + slotNode.setVisible(false); + continue; + } + if (attachment instanceof spine.RegionAttachment) { + if (attachment.region) { + if (!slot.currentSpriteName || slot.currentSpriteName !== attachment.name) { + var spriteName = attachment.region.name; + if (slot.currentSprite !== undefined) + slot.currentSprite.setVisible(false); + slot.sprites = slot.sprites || {}; + if (slot.sprites[spriteName] !== undefined) + slot.sprites[spriteName].setVisible(true); + else { + var sprite = this._createSprite(slot, attachment); + slotNode.addChild(sprite); } + slot.currentSprite = slot.sprites[spriteName]; + slot.currentSpriteName = spriteName; } - var bone = slot.bone; - if (attachment.region.offsetX === 0 && attachment.region.offsetY === 0) { - ax = attachment.x; - ay = attachment.y; - } - else { - //var regionScaleX = attachment.width / attachment.regionOriginalWidth * attachment.scaleX; - //ax = attachment.x + attachment.regionOffsetX * regionScaleX - (attachment.width * attachment.scaleX - attachment.regionWidth * regionScaleX) / 2; - ax = (attachment.offset[0] + attachment.offset[4]) * 0.5; - ay = (attachment.offset[1] + attachment.offset[5]) * 0.5; - } - slotNode.setPosition(bone.worldX + ax * bone.a + ay * bone.b, bone.worldY + ax * bone.c + ay * bone.d); - slotNode.setScale(bone.getWorldScaleX(), bone.getWorldScaleY()); - - //set the color and opacity - selSprite = slot.currentSprite; - selSprite._flippedX = bone.skeleton.flipX; - selSprite._flippedY = bone.skeleton.flipY; - if (selSprite._flippedY || selSprite._flippedX) { - slotNode.setRotation(bone.getWorldRotationX()); - selSprite.setRotation(attachment.rotation); - } else { - slotNode.setRotation(-bone.getWorldRotationX()); - selSprite.setRotation(-attachment.rotation); - } - - //hack for sprite - selSprite._renderCmd._displayedOpacity = 0 | (opacity * slot.color.a); - var r = 0 | (color.r * slot.color.r), g = 0 | (color.g * slot.color.g), b = 0 | (color.b * slot.color.b); - selSprite.setColor(cc.color(r, g, b)); - selSprite._renderCmd._updateColor(); - } else if (attachment instanceof spine.MeshAttachment) { - //todo for mesh + } + var bone = slot.bone; + if (attachment.region.offsetX === 0 && attachment.region.offsetY === 0) { + ax = attachment.x; + ay = attachment.y; + } + else { + //var regionScaleX = attachment.width / attachment.regionOriginalWidth * attachment.scaleX; + //ax = attachment.x + attachment.regionOffsetX * regionScaleX - (attachment.width * attachment.scaleX - attachment.regionWidth * regionScaleX) / 2; + ax = (attachment.offset[0] + attachment.offset[4]) * 0.5; + ay = (attachment.offset[1] + attachment.offset[5]) * 0.5; + } + slotNode.setPosition(bone.worldX + ax * bone.a + ay * bone.b, bone.worldY + ax * bone.c + ay * bone.d); + slotNode.setScale(bone.getWorldScaleX(), bone.getWorldScaleY()); + + //set the color and opacity + selSprite = slot.currentSprite; + selSprite._flippedX = bone.skeleton.flipX; + selSprite._flippedY = bone.skeleton.flipY; + if (selSprite._flippedY || selSprite._flippedX) { + slotNode.setRotation(bone.getWorldRotationX()); + selSprite.setRotation(attachment.rotation); } else { - slotNode.setVisible(false); - continue; + slotNode.setRotation(-bone.getWorldRotationX()); + selSprite.setRotation(-attachment.rotation); } - slotNode.setVisible(true); + + //hack for sprite + selSprite._renderCmd._displayedOpacity = 0 | (opacity * slot.color.a); + var r = 0 | (color.r * slot.color.r), g = 0 | (color.g * slot.color.g), b = 0 | (color.b * slot.color.b); + selSprite.setColor(cc.color(r, g, b)); + selSprite._renderCmd._updateColor(); + } else if (attachment instanceof spine.MeshAttachment) { + // Can not render mesh + } else { + slotNode.setVisible(false); + continue; } - }; + slotNode.setVisible(true); + } +}; + })(); diff --git a/extensions/spine/CCSkeletonTexture.js b/extensions/spine/CCSkeletonTexture.js index 997065b339..9250369c30 100644 --- a/extensions/spine/CCSkeletonTexture.js +++ b/extensions/spine/CCSkeletonTexture.js @@ -22,7 +22,11 @@ THE SOFTWARE. ****************************************************************************/ -sp.SkeletonTexture = cc.Class.extend({ +sp.SkeletonTexture = function (image) { + sp.spine.Texture.call(this, image); +}; +cc.inherits(sp.SkeletonTexture, sp.spine.Texture); +cc.extend(sp.SkeletonTexture.prototype, { name: 'sp.SkeletonTexture', _texture: null, @@ -60,9 +64,4 @@ sp.SkeletonTexture = cc.Class.extend({ cc.glBindTexture2D(this._texture); } } -}); - -var proto = sp.SkeletonTexture.prototype; -cc.extend(proto, spine.Texture.prototype); -// proto.constructor = spine.Texture; - +}); \ No newline at end of file diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js index e9fc27601a..221546ed75 100644 --- a/extensions/spine/CCSkeletonWebGLRenderCmd.js +++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js @@ -23,289 +23,289 @@ ****************************************************************************/ (function () { - sp.Skeleton.WebGLRenderCmd = function (renderableObject) { - this._rootCtor(renderableObject); - this._needDraw = true; - this._matrix = new cc.math.Matrix4(); - this._matrix.identity(); - this.vertexType = cc.renderer.VertexType.CUSTOM; - this.setShaderProgram(cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); - }; - var proto = sp.Skeleton.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype); - proto.constructor = sp.Skeleton.WebGLRenderCmd; - - proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset){ +var spine = sp.spine; + +sp.Skeleton.WebGLRenderCmd = function (renderableObject) { + this._rootCtor(renderableObject); + this._needDraw = true; + this._matrix = new cc.math.Matrix4(); + this._matrix.identity(); + this._currTexture = null; + this._currBlendFunc = {}; + this.vertexType = cc.renderer.VertexType.CUSTOM; + this.setShaderProgram(cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLOR)); +}; + +var proto = sp.Skeleton.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype); +proto.constructor = sp.Skeleton.WebGLRenderCmd; + +proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset){ + var node = this._node; + var color = this._displayedColor, locSkeleton = node._skeleton; + + var attachment, slot, i, n; + var premultiAlpha = node._premultipliedAlpha; + + locSkeleton.r = color.r / 255; + locSkeleton.g = color.g / 255; + locSkeleton.b = color.b / 255; + locSkeleton.a = this._displayedOpacity / 255; + if (premultiAlpha) { + locSkeleton.r *= locSkeleton.a; + locSkeleton.g *= locSkeleton.a; + locSkeleton.b *= locSkeleton.a; + } + + var debugSlotsInfo = null; + if (this._node._debugSlots) { + debugSlotsInfo = []; + } + + for (i = 0, n = locSkeleton.drawOrder.length; i < n; i++) { + slot = locSkeleton.drawOrder[i]; + if (!slot.attachment) + continue; + attachment = slot.attachment; + + // get the vertices length + var vertCount = 0; + if (attachment instanceof spine.RegionAttachment) { + vertCount = 6; // a quad = two triangles = six vertices + } + else if (attachment instanceof spine.MeshAttachment) { + vertCount = attachment.regionUVs.length / 2; + } + else { + continue; + } - // rendering the cached data first - cc.renderer._batchRendering(); - vertexDataOffset = 0; + // no vertices to render + if (vertCount === 0) { + continue; + } - var node = this._node; - var color = node.getColor(), locSkeleton = node._skeleton; + var regionTextureAtlas = node.getTextureAtlas(attachment); - var textureAtlas, attachment, slot, i, n; - var premultiAlpha = node._premultipliedAlpha; - var blendMode = -1; - var dataInited = false; - var cachedVertices = 0; + // Broken for changing batch info + this._currTexture = regionTextureAtlas.texture.getRealTexture(); + var batchBroken = cc.renderer._updateBatchedInfo(this._currTexture, this._getBlendFunc(slot.data.blendMode, premultiAlpha), this._glProgramState); - var wt = this._worldTransform, mat = this._matrix.mat; - mat[0] = wt.a; - mat[4] = wt.c; - mat[12] = wt.tx; - mat[1] = wt.b; - mat[5] = wt.d; - mat[13] = wt.ty; + // Broken for vertex data overflow + if (!batchBroken && vertexDataOffset + vertCount * 6 > f32buffer.length) { + // render the cached data + cc.renderer._batchRendering(); + batchBroken = true; + } + if (batchBroken) { + vertexDataOffset = 0; + } - this._shaderProgram.use(); - this._shaderProgram._setUniformForMVPMatrixWithMat4(this._matrix); - locSkeleton.r = color.r / 255; - locSkeleton.g = color.g / 255; - locSkeleton.b = color.b / 255; - locSkeleton.a = node.getOpacity() / 255; - if (premultiAlpha) { - locSkeleton.r *= locSkeleton.a; - locSkeleton.g *= locSkeleton.a; - locSkeleton.b *= locSkeleton.a; + // update the vertex buffer + var slotDebugPoints = null; + if (attachment instanceof spine.RegionAttachment) { + slotDebugPoints = this._uploadRegionAttachmentData(attachment, slot, premultiAlpha, f32buffer, ui32buffer, vertexDataOffset); + } + else if (attachment instanceof spine.MeshAttachment) { + this._uploadMeshAttachmentData(attachment, slot, premultiAlpha, f32buffer, ui32buffer, vertexDataOffset); + } + else { + continue; } - var debugSlotsInfo = null; if (this._node._debugSlots) { - debugSlotsInfo = []; + debugSlotsInfo[i] = slotDebugPoints; } - for (i = 0, n = locSkeleton.drawOrder.length; i < n; i++) { - slot = locSkeleton.drawOrder[i]; - if (!slot.attachment) - continue; - attachment = slot.attachment; - - // get the vertices length - var vertCount = 0; - if (attachment instanceof spine.RegionAttachment) { - vertCount = 6; // a quad = two triangles = six vertices - } - else if (attachment instanceof spine.MeshAttachment) { - vertCount = attachment.regionUVs.length / 2; - } - else { - continue; - } - - // no vertices to render - if (vertCount === 0) { - continue; - } - var regionTextureAtlas = node.getTextureAtlas(attachment); - // init data at the first time - if (!dataInited) { - textureAtlas = regionTextureAtlas; - blendMode = slot.data.blendMode; - cc.renderer._updateBatchedInfo(textureAtlas.texture.getRealTexture(), this._getBlendFunc(blendMode, premultiAlpha), this.getShaderProgram()); - dataInited = true; - } + // update the index buffer + if (attachment instanceof spine.RegionAttachment) { + cc.renderer._increaseBatchingSize(vertCount, cc.renderer.VertexType.TRIANGLE); + } else { + cc.renderer._increaseBatchingSize(vertCount, cc.renderer.VertexType.CUSTOM, attachment.triangles); + } - // if data changed or the vertices will be overflow - if ((cachedVertices + vertCount) * 6 > f32buffer.length || - textureAtlas !== regionTextureAtlas || - blendMode !== slot.data.blendMode) { - // render the cached data - cc.renderer._batchRendering(); - vertexDataOffset = 0; - cachedVertices = 0; - - // update the batched info - textureAtlas = regionTextureAtlas; - blendMode = slot.data.blendMode; - cc.renderer._updateBatchedInfo(textureAtlas.texture.getRealTexture(), this._getBlendFunc(blendMode, premultiAlpha), this.getShaderProgram()); - } + // update the index data + vertexDataOffset += vertCount * 6; + } - // update the vertex buffer - var slotDebugPoints = null; - if (attachment instanceof spine.RegionAttachment) { - slotDebugPoints = this._uploadRegionAttachmentData(attachment, slot, premultiAlpha, f32buffer, ui32buffer, vertexDataOffset); - } - else if (attachment instanceof spine.MeshAttachment) { - this._uploadMeshAttachmentData(attachment, slot, premultiAlpha, f32buffer, ui32buffer, vertexDataOffset); - } - else { - continue; - } - - if (this._node._debugSlots) { - debugSlotsInfo[i] = slotDebugPoints; - } + if (node._debugBones || node._debugSlots) { + // flush previous vertices + cc.renderer._batchRendering(); - // update the index buffer - if (attachment instanceof spine.RegionAttachment) { - cc.renderer._increaseBatchingSize(vertCount, cc.renderer.VertexType.TRIANGLE); - } else { - cc.renderer._increaseBatchingSize(vertCount, cc.renderer.VertexType.CUSTOM, attachment.triangles); + var wt = this._worldTransform, mat = this._matrix.mat; + mat[0] = wt.a; + mat[4] = wt.c; + mat[12] = wt.tx; + mat[1] = wt.b; + mat[5] = wt.d; + mat[13] = wt.ty; + cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW); + cc.current_stack.stack.push(cc.current_stack.top); + cc.current_stack.top = this._matrix; + var drawingUtil = cc._drawingUtil; + + if (node._debugSlots && debugSlotsInfo && debugSlotsInfo.length > 0) { + // Slots. + drawingUtil.setDrawColor(0, 0, 255, 255); + drawingUtil.setLineWidth(1); + + for (i = 0, n = locSkeleton.slots.length; i < n; i++) { + var points = debugSlotsInfo[i]; + if (points) { + drawingUtil.drawPoly(points, 4, true); + } } - - // update the index data - cachedVertices += vertCount; - vertexDataOffset += vertCount * 6; } - // render the left vertices - if (cachedVertices > 0) { - cc.renderer._batchRendering(); - } - - if (node._debugBones || node._debugSlots) { - cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW); - cc.current_stack.stack.push(cc.current_stack.top); - cc.current_stack.top = this._matrix; - var drawingUtil = cc._drawingUtil; - - if (node._debugSlots && debugSlotsInfo && debugSlotsInfo.length > 0) { - // Slots. - drawingUtil.setDrawColor(0, 0, 255, 255); - drawingUtil.setLineWidth(1); - - for (i = 0, n = locSkeleton.slots.length; i < n; i++) { - var points = debugSlotsInfo[i]; - if (points) { - drawingUtil.drawPoly(points, 4, true); - } - } + if (node._debugBones) { + // Bone lengths. + var bone; + drawingUtil.setLineWidth(2); + drawingUtil.setDrawColor(255, 0, 0, 255); + + for (i = 0, n = locSkeleton.bones.length; i < n; i++) { + bone = locSkeleton.bones[i]; + var x = bone.data.length * bone.a + bone.worldX; + var y = bone.data.length * bone.c + bone.worldY; + drawingUtil.drawLine(cc.p(bone.worldX, bone.worldY), cc.p(x, y)); } - if (node._debugBones) { - // Bone lengths. - var bone; - drawingUtil.setLineWidth(2); - drawingUtil.setDrawColor(255, 0, 0, 255); - - for (i = 0, n = locSkeleton.bones.length; i < n; i++) { - bone = locSkeleton.bones[i]; - var x = bone.data.length * bone.a + bone.worldX; - var y = bone.data.length * bone.c + bone.worldY; - drawingUtil.drawLine(cc.p(bone.worldX, bone.worldY), cc.p(x, y)); - } - - // Bone origins. - drawingUtil.setPointSize(4); - drawingUtil.setDrawColor(0, 0, 255, 255); // Root bone is blue. + // Bone origins. + drawingUtil.setPointSize(4); + drawingUtil.setDrawColor(0, 0, 255, 255); // Root bone is blue. - for (i = 0, n = locSkeleton.bones.length; i < n; i++) { - bone = locSkeleton.bones[i]; - drawingUtil.drawPoint(cc.p(bone.worldX, bone.worldY)); - if (i == 0) { - drawingUtil.setDrawColor(0, 255, 0, 255); - } + for (i = 0, n = locSkeleton.bones.length; i < n; i++) { + bone = locSkeleton.bones[i]; + drawingUtil.drawPoint(cc.p(bone.worldX, bone.worldY)); + if (i == 0) { + drawingUtil.setDrawColor(0, 255, 0, 255); } } - cc.kmGLPopMatrix(); } + cc.kmGLPopMatrix(); + } + + return 0; +}; + +proto._getBlendFunc = function (blendMode, premultiAlpha) { + var ret = this._currBlendFunc; + switch (blendMode) { + case spine.BlendMode.Normal: + ret.src = premultiAlpha ? cc.ONE : cc.SRC_ALPHA; + ret.dst = cc.ONE_MINUS_SRC_ALPHA; + break; + case spine.BlendMode.Additive: + ret.src = premultiAlpha ? cc.ONE : cc.SRC_ALPHA; + ret.dst = cc.ONE; + break; + case spine.BlendMode.Multiply: + ret.src = cc.DST_COLOR; + ret.dst = cc.ONE_MINUS_SRC_ALPHA; + break; + case spine.BlendMode.Screen: + ret.src = cc.ONE; + ret.dst = cc.ONE_MINUS_SRC_COLOR; + break; + default: + ret = this._node._blendFunc; + break; + } + + return ret; +}; + +proto._createChildFormSkeletonData = function(){}; + +proto._updateChild = function(){}; + +proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlpha, f32buffer, ui32buffer, vertexDataOffset) { + // the vertices in format: + // [ + // X1, Y1, C1R, C1G, C1B, C1A, U1, V1, // bottom left + // X2, Y2, C2R, C2G, C2B, C2A, U2, V2, // top left + // X3, Y3, C3R, C3G, C3B, C3A, U3, V3, // top right + // X4, Y4, C4R, C4G, C4B, C4A, U4, V4 // bottom right + // ] + // + var nodeColor = this._displayedColor; + var nodeR = nodeColor.r, + nodeG = nodeColor.g, + nodeB = nodeColor.b, + nodeA = this._displayedOpacity; + var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); + var wt = this._worldTransform, + wa = wt.a, wb = wt.b, wc = wt.c, wd = wt.d, + wx = wt.tx, wy = wt.ty, + z = this._node.vertexZ; + + var offset = vertexDataOffset; + // generate 6 vertices data (two triangles) from the quad vertices + // using two angles : (0, 1, 2) & (0, 2, 3) + for (var i = 0; i < 6; i++) { + var srcIdx = i < 4 ? i % 3 : i - 2; + var vx = vertices[srcIdx * 8], + vy = vertices[srcIdx * 8 + 1]; + var x = vx * wa + vy * wb + wx, + y = vx * wc + vy * wd + wy; + var r = vertices[srcIdx * 8 + 2] * nodeR, + g = vertices[srcIdx * 8 + 3] * nodeG, + b = vertices[srcIdx * 8 + 4] * nodeB, + a = vertices[srcIdx * 8 + 5] * nodeA; + var color = ((a<<24) | (b<<16) | (g<<8) | r); + f32buffer[offset] = x; + f32buffer[offset + 1] = y; + f32buffer[offset + 2] = z; + ui32buffer[offset + 3] = color; + f32buffer[offset + 4] = vertices[srcIdx * 8 + 6]; + f32buffer[offset + 5] = vertices[srcIdx * 8 + 7]; + offset += 6; + } + + if (this._node._debugSlots) { + // return the quad points info if debug slot enabled + var VERTEX = spine.RegionAttachment; + return [ + cc.p(vertices[VERTEX.X1], vertices[VERTEX.Y1]), + cc.p(vertices[VERTEX.X2], vertices[VERTEX.Y2]), + cc.p(vertices[VERTEX.X3], vertices[VERTEX.Y3]), + cc.p(vertices[VERTEX.X4], vertices[VERTEX.Y4]) + ]; + } +}; + +proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, f32buffer, ui32buffer, vertexDataOffset) { + var wt = this._worldTransform, + wa = wt.a, wb = wt.b, wc = wt.c, wd = wt.d, + wx = wt.tx, wy = wt.ty, + z = this._node.vertexZ; + // get the vertex data + var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); + var offset = vertexDataOffset; + var nodeColor = this._displayedColor; + var nodeR = nodeColor.r, + nodeG = nodeColor.g, + nodeB = nodeColor.b, + nodeA = this._displayedOpacity; + for (var i = 0, n = vertices.length; i < n; i += 8) { + var vx = vertices[i], + vy = vertices[i + 1]; + var x = vx * wa + vy * wb + wx, + y = vx * wc + vy * wd + wy; + var r = vertices[i + 2] * nodeR, + g = vertices[i + 3] * nodeG, + b = vertices[i + 4] * nodeB, + a = vertices[i + 5] * nodeA; + var color = ((a<<24) | (b<<16) | (g<<8) | r); + + f32buffer[offset] = x; + f32buffer[offset + 1] = y; + f32buffer[offset + 2] = z; + ui32buffer[offset + 3] = color; + f32buffer[offset + 4] = vertices[i + 6]; + f32buffer[offset + 5] = vertices[i + 7]; + offset += 6; + } +}; - return 0; - }; - - proto._getBlendFunc = function (blendMode, premultiAlpha) { - var ret = {}; - switch (blendMode) { - case spine.BlendMode.Normal: - ret.src = premultiAlpha ? cc.ONE : cc.SRC_ALPHA; - ret.dst = cc.ONE_MINUS_SRC_ALPHA; - break; - case spine.BlendMode.Additive: - ret.src = premultiAlpha ? cc.ONE : cc.SRC_ALPHA; - ret.dst = cc.ONE; - break; - case spine.BlendMode.Multiply: - ret.src = cc.DST_COLOR; - ret.dst = cc.ONE_MINUS_SRC_ALPHA; - break; - case spine.BlendMode.Screen: - ret.src = cc.ONE; - ret.dst = cc.ONE_MINUS_SRC_COLOR; - break; - default: - ret = this._node._blendFunc; - break; - } - - return ret; - }; - - proto._createChildFormSkeletonData = function () { - }; - - proto._updateChild = function () { - }; - - proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlpha, f32buffer, ui32buffer, vertexDataOffset) { - // the vertices in format: - // [ - // X1, Y1, C1R, C1G, C1B, C1A, U1, V1, // bottom left - // X2, Y2, C2R, C2G, C2B, C2A, U2, V2, // top left - // X3, Y3, C3R, C3G, C3B, C3A, U3, V3, // top right - // X4, Y4, C4R, C4G, C4B, C4A, U4, V4 // bottom right - // ] - // - var nodeColor = this._displayedColor; - var nodeR = nodeColor.r, - nodeG = nodeColor.g, - nodeB = nodeColor.b, - nodeA = nodeColor.a; - var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); - var offset = vertexDataOffset; - // generate 6 vertices data (two triangles) from the quad vertices - // using two angles : (0, 1, 2) & (0, 2, 3) - for (var i = 0; i < 6; i++) { - var srcIdx = i < 4 ? i % 3 : i - 2; - var r = vertices[srcIdx * 8 + 2] * nodeR, - g = vertices[srcIdx * 8 + 3] * nodeG, - b = vertices[srcIdx * 8 + 4] * nodeB, - a = vertices[srcIdx * 8 + 5] * nodeA; - var color = ((a<<24) | (b<<16) | (g<<8) | r); - f32buffer[offset] = vertices[srcIdx * 8]; - f32buffer[offset + 1] = vertices[srcIdx * 8 + 1]; - f32buffer[offset + 2] = this._node.vertexZ; - ui32buffer[offset + 3] = color; - f32buffer[offset + 4] = vertices[srcIdx * 8 + 6]; - f32buffer[offset + 5] = vertices[srcIdx * 8 + 7]; - offset += 6; - } - - if (this._node._debugSlots) { - // return the quad points info if debug slot enabled - var VERTEX = spine.RegionAttachment; - return [ - cc.p(vertices[VERTEX.X1], vertices[VERTEX.Y1]), - cc.p(vertices[VERTEX.X2], vertices[VERTEX.Y2]), - cc.p(vertices[VERTEX.X3], vertices[VERTEX.Y3]), - cc.p(vertices[VERTEX.X4], vertices[VERTEX.Y4]) - ]; - } - }; - - proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, f32buffer, ui32buffer, vertexDataOffset) { - // get the vertex data - var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); - var offset = vertexDataOffset; - var nodeColor = this._displayedColor; - var nodeR = nodeColor.r, - nodeG = nodeColor.g, - nodeB = nodeColor.b, - nodeA = nodeColor.a; - for (var i = 0, n = vertices.length; i < n; i += 8) { - var r = vertices[i + 2] * nodeR, - g = vertices[i + 3] * nodeG, - b = vertices[i + 4] * nodeB, - a = vertices[i + 5] * nodeA; - var color = ((a<<24) | (b<<16) | (g<<8) | r); - - f32buffer[offset] = vertices[i]; - f32buffer[offset + 1] = vertices[i + 1]; - f32buffer[offset + 2] = this._node.vertexZ; - ui32buffer[offset + 3] = color; - f32buffer[offset + 4] = vertices[i + 6]; - f32buffer[offset + 5] = vertices[i + 7]; - offset += 6; - } - }; })(); diff --git a/extensions/spine/LICENSE b/extensions/spine/LICENSE new file mode 100644 index 0000000000..daceab94a4 --- /dev/null +++ b/extensions/spine/LICENSE @@ -0,0 +1,27 @@ +Spine Runtimes Software License v2.5 + +Copyright (c) 2013-2016, Esoteric Software +All rights reserved. + +You are granted a perpetual, non-exclusive, non-sublicensable, and +non-transferable license to use, install, execute, and perform the Spine +Runtimes software and derivative works solely for personal or internal +use. Without the written permission of Esoteric Software (see Section 2 of +the Spine Software License Agreement), you may not (a) modify, translate, +adapt, or develop new applications using the Spine Runtimes or otherwise +create derivative works or improvements of the Spine Runtimes or (b) remove, +delete, alter, or obscure any trademarks or any copyright, trademark, patent, +or other intellectual property or proprietary rights notices on or in the +Software, including any copy thereof. Redistributions in binary or source +form must include this license and terms. + +THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF +USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/extensions/spine/Spine.js b/extensions/spine/Spine.js index 401e6b84c3..c845c19f41 100644 --- a/extensions/spine/Spine.js +++ b/extensions/spine/Spine.js @@ -1,3 +1,5 @@ +// Spine runtime version 3.5.35 + var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } @@ -1096,7 +1098,7 @@ var spine; } } if (entry.mixDuration > 0) - this.queueEvents(from, animationTime); + this.queueEvents(from, animationTime); this.events.length = 0; from.nextAnimationLast = animationTime; from.nextTrackLast = from.trackTime; @@ -4239,13 +4241,12 @@ var spine; var scale = this.scale; attachment.worldVerticesLength = verticesLength; var vertices = map.vertices; - var scaledVertices = spine.Utils.toFloatArray(vertices); if (verticesLength == vertices.length) { if (scale != 1) { for (var i = 0, n = vertices.length; i < n; i++) - scaledVertices[i] *= scale; + vertices[i] *= scale; } - attachment.vertices = scaledVertices; + attachment.vertices = spine.Utils.toFloatArray(vertices); return; } var weights = new Array(); @@ -5352,4 +5353,6 @@ var spine; }()); spine.TimeKeeper = TimeKeeper; })(spine || (spine = {})); -//# sourceMappingURL=spine-core.js.map \ No newline at end of file + +var sp = sp || {}; +sp.spine = spine; From f65a2303c15dd8eba797c447980772ec7c88c36e Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 14 Jul 2017 12:07:00 +0800 Subject: [PATCH 26/65] Fix action recycling issue with lock --- cocos2d/actions/CCActionInterval.js | 2 +- cocos2d/core/CCActionManager.js | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index 74a855748e..b7149df915 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -1083,7 +1083,7 @@ cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{ initWithDuration: function (duration, deltaAngleX, deltaAngleY) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { this._dstAngleX = deltaAngleX || 0; - this._dstAngleY = deltaAngleY || this._dstAngleX; + this._dstAngleY = deltaAngleY !== undefined ? deltaAngleY : this._dstAngleX; return true; } return false; diff --git a/cocos2d/core/CCActionManager.js b/cocos2d/core/CCActionManager.js index 9ecc3c4886..c0777396a6 100644 --- a/cocos2d/core/CCActionManager.js +++ b/cocos2d/core/CCActionManager.js @@ -36,6 +36,7 @@ cc.HashElement = function () { this.actionIndex = 0; this.currentAction = null; //CCAction this.paused = false; + this.lock = false; }; /** @@ -84,6 +85,7 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ element.currentAction = null; element.paused = false; element.target = null; + element.lock = false; this._elementPool.push(element); }, @@ -303,7 +305,7 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ _deleteHashElement:function (element) { var ret = false; - if (element) { + if (element && !element.lock) { if (this._hashTargets[element.target.__instanceId]) { delete this._hashTargets[element.target.__instanceId]; var targets = this._arrayTargets; @@ -329,6 +331,7 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ this._currentTarget = locTargets[elt]; locCurrTarget = this._currentTarget; if (!locCurrTarget.paused && locCurrTarget.actions) { + locCurrTarget.lock = true; // The 'actions' CCMutableArray may change while inside this loop. for (locCurrTarget.actionIndex = 0; locCurrTarget.actionIndex < locCurrTarget.actions.length; locCurrTarget.actionIndex++) { locCurrTarget.currentAction = locCurrTarget.actions[locCurrTarget.actionIndex]; @@ -338,16 +341,16 @@ cc.ActionManager = cc.Class.extend(/** @lends cc.ActionManager# */{ //use for speed locCurrTarget.currentAction.step(dt * ( locCurrTarget.currentAction._speedMethod ? locCurrTarget.currentAction._speed : 1 ) ); - if (locCurrTarget.currentAction.isDone()) { + if (locCurrTarget.currentAction && locCurrTarget.currentAction.isDone()) { locCurrTarget.currentAction.stop(); var action = locCurrTarget.currentAction; - // Make currentAction nil to prevent removeAction from salvaging it. locCurrTarget.currentAction = null; this.removeAction(action); } locCurrTarget.currentAction = null; } + locCurrTarget.lock = false; } // only delete currentTarget if no actions were scheduled during the cycle (issue #481) if (locCurrTarget.actions.length === 0) { From 1d1c5e2d8ee219f378b9b69a72a9d6336b254b88 Mon Sep 17 00:00:00 2001 From: Nick Dong Date: Wed, 26 Jul 2017 11:39:28 +0700 Subject: [PATCH 27/65] Fix 'titleColor' attribute name for UIButton https://github.com/cocos2d/cocos2d-html5/blob/develop/extensions/ccui/uiwidgets/UIButton.js#L803 --- extensions/ccui/uiwidgets/UIButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/ccui/uiwidgets/UIButton.js b/extensions/ccui/uiwidgets/UIButton.js index 4feff73686..4741e2e767 100644 --- a/extensions/ccui/uiwidgets/UIButton.js +++ b/extensions/ccui/uiwidgets/UIButton.js @@ -33,7 +33,7 @@ * @property {String} titleFont - The content string font of the button title * @property {Number} titleFontSize - The content string font size of the button title * @property {String} titleFontName - The content string font name of the button title - * @property {cc.Color} titleFontColor - The content string font color of the button title + * @property {cc.Color} titleColor - The content string font color of the button title * @property {Boolean} pressedActionEnabled - Indicate whether button has zoom effect when clicked */ ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{ From 6efd2a21c4ae49e670927534700ac5332f027a78 Mon Sep 17 00:00:00 2001 From: Administrator <363012115@qq.com> Date: Tue, 8 Aug 2017 15:55:36 +0800 Subject: [PATCH 28/65] fix the problem of loading local resources failed when the protocol is 'file://' --- CCBoot.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CCBoot.js b/CCBoot.js index 06ec6e67df..8f4bafd3cd 100644 --- a/CCBoot.js +++ b/CCBoot.js @@ -797,7 +797,7 @@ cc.loader = (function () { xhr.setRequestHeader("Accept-Charset", "utf-8"); xhr.onreadystatechange = function () { if (xhr.readyState === 4) - xhr.status === 200 ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null); + (xhr.status === 200||xhr.status === 0) ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null); }; } else { if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8"); @@ -806,7 +806,7 @@ cc.loader = (function () { clearTimeout(xhr._timeoutId); } if (xhr.readyState === 4) { - xhr.status === 200 ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null); + (xhr.status === 200||xhr.status === 0) ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null); } }; xhr.onerror = function () { @@ -845,7 +845,7 @@ cc.loader = (function () { window.msg = arrayBuffer; } if (xhr.readyState === 4) { - xhr.status === 200 ? cb(null, xhr.response) : cb({status:xhr.status, errorMessage:errInfo}, null); + (xhr.status === 200||xhr.status === 0) ? cb(null, xhr.response) : cb({status:xhr.status, errorMessage:errInfo}, null); } }; xhr.onerror = function(){ From 87c456cd78cba6ffc7cdbaa5de0e90d7a05f98dd Mon Sep 17 00:00:00 2001 From: Danilo Neves Cruz Date: Sat, 2 Sep 2017 03:59:59 -0300 Subject: [PATCH 29/65] fix cc.GLProgramState.apply --- cocos2d/shaders/CCGLProgramState.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js index 0a9cef01cb..80e25b3ade 100644 --- a/cocos2d/shaders/CCGLProgramState.js +++ b/cocos2d/shaders/CCGLProgramState.js @@ -43,7 +43,6 @@ cc.UniformValue = function (uniform, glprogram) { this._glprogram = glprogram; this._value = null; - this._currentBoundValue = null; this._type = -1; }; @@ -105,12 +104,6 @@ cc.UniformValue.prototype = { }, apply: function apply() { - if (this._currentBoundValue === this._value - && this._type !== types.GL_CALLBACK) { - return; - } - - this._currentBoundValue = this._value; switch (this._type) { case types.GL_INT: this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); @@ -180,10 +173,7 @@ cc.GLProgramState.prototype = { } for (var i = 0; i < this._uniforms.length; ++i) { - var uniform = this._uniforms[i]; - if (uniform._currentBoundValue !== uniform._value) { - uniform.apply(); - } + this._uniforms[i].apply(); } }, From 444c237e145fba57785f9128bce53afb3fa9cb29 Mon Sep 17 00:00:00 2001 From: Danilo Neves Cruz Date: Sat, 2 Sep 2017 21:35:32 -0300 Subject: [PATCH 30/65] fix cc.GLProgram uniform cache --- cocos2d/shaders/CCGLProgram.js | 327 +++++++++++++++++----------- cocos2d/shaders/CCGLProgramState.js | 69 +++--- 2 files changed, 222 insertions(+), 174 deletions(-) diff --git a/cocos2d/shaders/CCGLProgram.js b/cocos2d/shaders/CCGLProgram.js index 8708db54f5..67e23db2d7 100644 --- a/cocos2d/shaders/CCGLProgram.js +++ b/cocos2d/shaders/CCGLProgram.js @@ -42,28 +42,22 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ _projectionUpdated: -1, // Uniform cache - _updateUniformLocation: function (location) { - if (!location) + _updateUniform: function (name) { + if (!name) return false; - var updated; - var element = this._hashForUniforms[location]; - - if (!element) { - element = [ - arguments[1], - arguments[2], - arguments[3], - arguments[4] - ]; - this._hashForUniforms[location] = element; + var updated = false; + var element = this._hashForUniforms[name]; + var args = Array.isArray(arguments[1]) ? arguments[1] : + Array.prototype.slice.call(arguments, 1); + + if (!element || element.length !== args.length) { + this._hashForUniforms[name] = args.slice(); updated = true; } else { - updated = false; - var count = arguments.length - 1; - for (var i = 0; i < count; ++i) { - if (arguments[i + 1] !== element[i]) { - element[i] = arguments[i + 1]; + for (var i = 0; i < args.length; i += 1) { + if (args[i] !== element[i]) { + element[i] = args[i]; updated = true; } } @@ -169,9 +163,7 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ if (this._fragShader) locGL.attachShader(this._programObj, this._fragShader); - for (var key in this._hashForUniforms) { - delete this._hashForUniforms[key]; - } + if (Object.keys(this._hashForUniforms).length > 0) this._hashForUniforms = {}; cc.checkGLErrorDebug(); return true; @@ -231,7 +223,7 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ } this._glContext.linkProgram(this._programObj); - + if (this._vertShader) this._glContext.deleteShader(this._vertShader); if (this._fragShader) @@ -268,18 +260,13 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * cc.UNIFORM_SAMPLER */ updateUniforms: function () { - this._uniforms[cc.UNIFORM_PMATRIX_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_PMATRIX_S); - this._uniforms[cc.UNIFORM_MVMATRIX_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVMATRIX_S); - this._uniforms[cc.UNIFORM_MVPMATRIX_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVPMATRIX_S); - this._uniforms[cc.UNIFORM_TIME_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_TIME_S); - this._uniforms[cc.UNIFORM_SINTIME_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SINTIME_S); - this._uniforms[cc.UNIFORM_COSTIME_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_COSTIME_S); - + [cc.UNIFORM_PMATRIX_S, cc.UNIFORM_MVMATRIX_S, cc.UNIFORM_MVPMATRIX_S, + cc.UNIFORM_TIME_S, cc.UNIFORM_SINTIME_S, cc.UNIFORM_COSTIME_S, + cc.UNIFORM_RANDOM01_S, cc.UNIFORM_SAMPLER_S].forEach(function(name) { + this._addUniformLocation(name); + }.bind(this)); this._usesTime = (this._uniforms[cc.UNIFORM_TIME_S] != null || this._uniforms[cc.UNIFORM_SINTIME_S] != null || this._uniforms[cc.UNIFORM_COSTIME_S] != null); - this._uniforms[cc.UNIFORM_RANDOM01_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_RANDOM01_S); - this._uniforms[cc.UNIFORM_SAMPLER_S] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SAMPLER_S); - this.use(); // Since sample most probably won't change, set it to 0 now. this.setUniformLocationWith1i(this._uniforms[cc.UNIFORM_SAMPLER_S], 0); @@ -287,7 +274,9 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ _addUniformLocation: function (name) { var location = this._glContext.getUniformLocation(this._programObj, name); + if (location) location._name = name; this._uniforms[name] = location; + return location; }, /** @@ -301,7 +290,7 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ if (!this._programObj) throw new Error("cc.GLProgram.getUniformLocationForName(): Invalid operation. Cannot get uniform location when program is not initialized"); - var location = this._uniforms[name] || this._glContext.getUniformLocation(this._programObj, name); + var location = this._uniforms[name] || this._addUniformLocation(name); return location; }, @@ -327,16 +316,15 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} i1 */ setUniformLocationWith1i: function (location, i1) { - var gl = this._glContext; - if (typeof location === 'string') { - var updated = this._updateUniformLocation(location, i1); - if (updated) { - var locObj = this.getUniformLocationForName(location); - gl.uniform1i(locObj, i1); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, i1)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform1i(location, i1); } - } - else { - gl.uniform1i(location, i1); + } else { + this._glContext.uniform1i(location, i1); } }, @@ -347,16 +335,15 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} i2 */ setUniformLocationWith2i: function (location, i1, i2) { - var gl = this._glContext; - if (typeof location === 'string') { - var updated = this._updateUniformLocation(location, i1, i2); - if (updated) { - var locObj = this.getUniformLocationForName(location); - gl.uniform2i(locObj, i1, i2); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, i1, i2)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform2i(location, i1, i2); } - } - else { - gl.uniform2i(location, i1, i2); + } else { + this._glContext.uniform2i(location, i1, i2); } }, @@ -368,16 +355,15 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} i3 */ setUniformLocationWith3i: function (location, i1, i2, i3) { - var gl = this._glContext; - if (typeof location === 'string') { - var updated = this._updateUniformLocation(location, i1, i2, i3); - if (updated) { - var locObj = this.getUniformLocationForName(location); - gl.uniform3i(locObj, i1, i2, i3); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, i1, i2, i3)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform3i(location, i1, i2, i3); } - } - else { - gl.uniform3i(location, i1, i2, i3); + } else { + this._glContext.uniform3i(location, i1, i2, i3); } }, @@ -390,16 +376,15 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} i4 */ setUniformLocationWith4i: function (location, i1, i2, i3, i4) { - var gl = this._glContext; - if (typeof location === 'string') { - var updated = this._updateUniformLocation(location, i1, i2, i3, i4); - if (updated) { - var locObj = this.getUniformLocationForName(location); - gl.uniform4i(locObj, i1, i2, i3, i4); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, i1, i2, i3, i4)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform4i(location, i1, i2, i3, i4); } - } - else { - gl.uniform4i(location, i1, i2, i3, i4); + } else { + this._glContext.uniform4i(location, i1, i2, i3, i4); } }, @@ -410,8 +395,16 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} numberOfArrays */ setUniformLocationWith2iv: function (location, intArray) { - var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location; - this._glContext.uniform2iv(locObj, intArray); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, intArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform2iv(location, intArray); + } + } else { + this._glContext.uniform2iv(location, intArray); + } }, /** @@ -420,8 +413,16 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Int32Array} intArray */ setUniformLocationWith3iv: function (location, intArray) { - var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location; - this._glContext.uniform3iv(locObj, intArray); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, intArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform3iv(location, intArray); + } + } else { + this._glContext.uniform3iv(location, intArray); + } }, /** @@ -430,8 +431,16 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Int32Array} intArray */ setUniformLocationWith4iv: function (location, intArray) { - var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location; - this._glContext.uniform4iv(locObj, intArray); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, intArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform4iv(location, intArray); + } + } else { + this._glContext.uniform4iv(location, intArray); + } }, /** @@ -449,16 +458,15 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} f1 */ setUniformLocationWith1f: function (location, f1) { - var gl = this._glContext; - if (typeof location === 'string') { - var updated = this._updateUniformLocation(location, f1); - if (updated) { - var locObj = this.getUniformLocationForName(location); - gl.uniform1f(locObj, f1); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, f1)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform1f(location, f1); } - } - else { - gl.uniform1f(location, f1); + } else { + this._glContext.uniform1f(location, f1); } }, @@ -469,16 +477,15 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} f2 */ setUniformLocationWith2f: function (location, f1, f2) { - var gl = this._glContext; - if (typeof location === 'string') { - var updated = this._updateUniformLocation(location, f1, f2); - if (updated) { - var locObj = this.getUniformLocationForName(location); - gl.uniform2f(locObj, f1, f2); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, f1, f2)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform2f(location, f1, f2); } - } - else { - gl.uniform2f(location, f1, f2); + } else { + this._glContext.uniform2f(location, f1, f2); } }, @@ -490,16 +497,15 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} f3 */ setUniformLocationWith3f: function (location, f1, f2, f3) { - var gl = this._glContext; - if (typeof location === 'string') { - var updated = this._updateUniformLocation(location, f1, f2, f3); - if (updated) { - var locObj = this.getUniformLocationForName(location); - gl.uniform3f(locObj, f1, f2, f3); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, f1, f2, f3)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform3f(location, f1, f2, f3); } - } - else { - gl.uniform3f(location, f1, f2, f3); + } else { + this._glContext.uniform3f(location, f1, f2, f3); } }, @@ -512,16 +518,16 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Number} f4 */ setUniformLocationWith4f: function (location, f1, f2, f3, f4) { - var gl = this._glContext; - if (typeof location === 'string') { - var updated = this._updateUniformLocation(location, f1, f2, f3, f4); - if (updated) { - var locObj = this.getUniformLocationForName(location); - gl.uniform4f(locObj, f1, f2, f3, f4); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, f1, f2, f3, f4)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform4f(location, f1, f2, f3, f4); } - } - else { - gl.uniform4f(location, f1, f2, f3, f4); + } else { + this._glContext.uniform4f(location, f1, f2, f3, f4); + cc.log('uniform4f', f1, f2, f3, f4); } }, @@ -531,8 +537,16 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Float32Array} floatArray */ setUniformLocationWith2fv: function (location, floatArray) { - var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location; - this._glContext.uniform2fv(locObj, floatArray); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, floatArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform2fv(location, floatArray); + } + } else { + this._glContext.uniform2fv(location, floatArray); + } }, /** @@ -541,8 +555,16 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Float32Array} floatArray */ setUniformLocationWith3fv: function (location, floatArray) { - var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location; - this._glContext.uniform3fv(locObj, floatArray); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, floatArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform3fv(location, floatArray); + } + } else { + this._glContext.uniform3fv(location, floatArray); + } }, /** @@ -551,17 +573,53 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Float32Array} floatArray */ setUniformLocationWith4fv: function (location, floatArray) { - var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location; - this._glContext.uniform4fv(locObj, floatArray); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, floatArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniform4fv(location, floatArray); + } + } else { + this._glContext.uniform4fv(location, floatArray); + cc.log('uniform4fv', floatArray); + } }, + + /** + * calls glUniformMatrix2fv + * @param {WebGLUniformLocation|String} location + * @param {Float32Array} matrixArray + */ + setUniformLocationWithMatrix2fv: function (location, matrixArray) { + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, matrixArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniformMatrix2fv(location, false, matrixArray); + } + } else { + this._glContext.uniformMatrix2fv(location, false, matrixArray); + } + }, + /** * calls glUniformMatrix3fv * @param {WebGLUniformLocation|String} location * @param {Float32Array} matrixArray */ setUniformLocationWithMatrix3fv: function (location, matrixArray) { - var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location; - this._glContext.uniformMatrix3fv(locObj, false, matrixArray); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, matrixArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniformMatrix3fv(location, false, matrixArray); + } + } else { + this._glContext.uniformMatrix3fv(location, false, matrixArray); + } }, /** @@ -570,8 +628,16 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * @param {Float32Array} matrixArray */ setUniformLocationWithMatrix4fv: function (location, matrixArray) { - var locObj = typeof location === 'string' ? this.getUniformLocationForName(location) : location; - this._glContext.uniformMatrix4fv(locObj, false, matrixArray); + var isString = typeof location === 'string'; + var name = isString ? location : location && location._name; + if (name) { + if (this._updateUniform(name, matrixArray)) { + if (isString) location = this.getUniformLocationForName(name); + this._glContext.uniformMatrix4fv(location, false, matrixArray); + } + } else { + this._glContext.uniformMatrix4fv(location, false, matrixArray); + } }, setUniformLocationF32: function () { @@ -664,25 +730,25 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * will update the MVP matrix on the MVP uniform if it is different than the previous call for this same shader program. */ setUniformForModelViewProjectionMatrix: function () { - this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], false, + this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], cc.getMat4MultiplyValue(cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top)); }, setUniformForModelViewProjectionMatrixWithMat4: function (swapMat4) { cc.kmMat4Multiply(swapMat4, cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top); - this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], false, swapMat4.mat); + this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX_S], swapMat4.mat); }, setUniformForModelViewAndProjectionMatrixWithMat4: function () { - this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], false, cc.modelview_matrix_stack.top.mat); - this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], false, cc.projection_matrix_stack.top.mat); + this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], cc.modelview_matrix_stack.top.mat); + this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], cc.projection_matrix_stack.top.mat); }, _setUniformForMVPMatrixWithMat4: function (modelViewMatrix) { if (!modelViewMatrix) throw new Error("modelView matrix is undefined."); - this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], false, modelViewMatrix.mat); - this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], false, cc.projection_matrix_stack.top.mat); + this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX_S], modelViewMatrix.mat); + this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX_S], cc.projection_matrix_stack.top.mat); }, _updateProjectionUniform: function () { @@ -748,7 +814,7 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ reset: function () { this._vertShader = null; this._fragShader = null; - this._uniforms.length = 0; + if (Object.keys(this._uniforms).length > 0) this._uniforms = {}; // it is already deallocated by android //ccGLDeleteProgram(m_uProgram); @@ -756,10 +822,7 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ this._programObj = null; // Purge uniform hash - for (var key in this._hashForUniforms) { - this._hashForUniforms[key].length = 0; - delete this._hashForUniforms[key]; - } + if (Object.keys(this._hashForUniforms).length > 0) this._hashForUniforms = {}; }, /** diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js index 80e25b3ade..2e9ec348ee 100644 --- a/cocos2d/shaders/CCGLProgramState.js +++ b/cocos2d/shaders/CCGLProgramState.js @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -var types = +var types = { GL_FLOAT: 0, GL_INT: 1, @@ -50,7 +50,7 @@ cc.UniformValue.prototype = { setFloat: function setFloat(value) { this._value = value; this._type = types.GL_FLOAT; - }, + }, setInt: function setInt(value) { this._value = value; @@ -106,30 +106,28 @@ cc.UniformValue.prototype = { apply: function apply() { switch (this._type) { case types.GL_INT: - this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); + this._glprogram.setUniformLocationWith1i(this._uniform._location, this._value); break; case types.GL_FLOAT: - this._glprogram.setUniformLocationWith1f(this._uniform.location, this._value); + this._glprogram.setUniformLocationWith1f(this._uniform._location, this._value); break; case types.GL_FLOAT_VEC2: - this._glprogram.setUniformLocationWith2f(this._uniform.location, this._value[0], this._value[1]); + this._glprogram.setUniformLocationWith2fv(this._uniform._location, this._value); break; case types.GL_FLOAT_VEC3: - this._glprogram.setUniformLocationWith3f(this._uniform.location, this._value[0], - this._value[1], this._value[2]); + this._glprogram.setUniformLocationWith3fv(this._uniform._location, this._value); break; case types.GL_FLOAT_VEC4: - this._glprogram.setUniformLocationWith4f(this._uniform.location, this._value[0], - this._value[1], this._value[2], this._value[3]); + this._glprogram.setUniformLocationWith4fv(this._uniform._location, this._value); break; case types.GL_FLOAT_MAT4: - this._glprogram.setUniformLocationWithMatrix4fv(this._uniform.location, this._value); + this._glprogram.setUniformLocationWithMatrix4fv(this._uniform._location, this._value); break; case types.GL_CALLBACK: this._value(this._glprogram, this._uniform); break; case types.GL_TEXTURE: - this._glprogram.setUniformLocationWith1i(this._uniform.location, this._value); + this._glprogram.setUniformLocationWith1i(this._uniform._location, this._value); cc.glBindTexture2DN(this._value, this._textureId); break; default: @@ -140,27 +138,20 @@ cc.UniformValue.prototype = { cc.GLProgramState = function (glprogram) { this._glprogram = glprogram; - this._uniforms = []; - this._uniformsByName = {}; - this._uniformsByLocation = {}; + this._uniforms = {}; this._boundTextureUnits = {}; this._textureUnitIndex = 1; // Start at 1, as CC_Texture0 is bound to 0 var activeUniforms = glprogram._glContext.getProgramParameter(glprogram._programObj, glprogram._glContext.ACTIVE_UNIFORMS); - var count = 0; - for (var i = 0; i < activeUniforms; ++i) { - var uniform = glprogram._glContext.getActiveUniform(glprogram._programObj, i); + for (var i = 0; i < activeUniforms; i += 1) { + var uniform = glprogram._glContext.getActiveUniform(glprogram._programObj, i); if (uniform.name.indexOf("CC_") !== 0) { - uniform.location = glprogram._glContext.getUniformLocation(glprogram._programObj, - uniform.name); - uniform.name = uniform.name.replace("[]", ""); + uniform._location = glprogram._glContext.getUniformLocation(glprogram._programObj, uniform.name); + uniform._location._name = uniform.name; var uniformValue = new cc.UniformValue(uniform, glprogram); - this._uniforms.push(uniformValue); - this._uniformsByName[uniform.name] = count; - this._uniformsByLocation[uniform.location] = count; - count++; + this._uniforms[uniform.name] = uniformValue; } } }; @@ -171,10 +162,10 @@ cc.GLProgramState.prototype = { if (modelView) { this._glprogram._setUniformForMVPMatrixWithMat4(modelView); } - - for (var i = 0; i < this._uniforms.length; ++i) { - this._uniforms[i].apply(); - } + + Object.values(this._uniforms).forEach(function(uniform) { + uniform.apply(); + }); }, setGLProgram: function setGLProgram(glprogram) { @@ -189,16 +180,10 @@ cc.GLProgramState.prototype = { return this._uniforms.length; }, - getUniformValue: function getUniformValue(uniform) - { - if (typeof uniform === 'string') { - return this._uniforms[this._uniformsByName[uniform]]; - } else { - return this._uniforms[this._uniformsByLocation[uniform]]; - } + getUniformValue: function getUniformValue(uniform) { + return this._uniforms[uniform]; }, - // Accepts either string or uniform location setUniformInt: function setUniformInt(uniform, value) { var v = this.getUniformValue(uniform); if (v) { @@ -225,7 +210,7 @@ cc.GLProgramState.prototype = { cc.log("cocos2d: warning: Uniform not found: " + uniform); } }, - + setUniformVec2v: function setUniformVec2v(uniform, value) { var v = this.getUniformValue(uniform); if (v) { @@ -234,7 +219,7 @@ cc.GLProgramState.prototype = { cc.log("cocos2d: warning: Uniform not found: " + uniform); } }, - + setUniformVec3: function setUniformVec3(uniform, v1, v2, v3) { var v = this.getUniformValue(uniform); if (v) { @@ -252,7 +237,7 @@ cc.GLProgramState.prototype = { cc.log("cocos2d: warning: Uniform not found: " + uniform); } }, - + setUniformVec4: function setUniformVec4(uniform, v1, v2, v3, v4) { var v = this.getUniformValue(uniform); if (v) { @@ -271,7 +256,7 @@ cc.GLProgramState.prototype = { } }, - + setUniformMat4: function setUniformMat4(uniform, value) { var v = this.getUniformValue(uniform); if (v) { @@ -291,7 +276,7 @@ cc.GLProgramState.prototype = { } }, - + setUniformTexture: function setUniformTexture(uniform, texture) { var uniformValue = this.getUniformValue(uniform); if (uniformValue) { @@ -300,7 +285,7 @@ cc.GLProgramState.prototype = { uniformValue.setTexture(texture, textureUnit); } else { uniformValue.setTexture(texture, this._textureUnitIndex); - this._boundTextureUnits[uniform] = this._textureUnitIndex++; + this._boundTextureUnits[uniform] = this._textureUnitIndex++; } } } From d3ae8440757d720580aa66f425fdbfebdc8225a2 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 10:11:12 +0800 Subject: [PATCH 31/65] Improve loader listeners --- CCBoot.js | 76 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/CCBoot.js b/CCBoot.js index 06ec6e67df..9cfc1ae2db 100644 --- a/CCBoot.js +++ b/CCBoot.js @@ -801,25 +801,51 @@ cc.loader = (function () { }; } else { if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8"); - xhr.onload = function () { + var loadCallback = function () { + xhr.removeEventListener('load', loadCallback); + xhr.removeEventListener('error', errorCallback); if (xhr._timeoutId >= 0) { clearTimeout(xhr._timeoutId); } + else { + xhr.removeEventListener('timeout', timeoutCallback); + } if (xhr.readyState === 4) { xhr.status === 200 ? cb(null, xhr.responseText) : cb({status:xhr.status, errorMessage:errInfo}, null); } }; - xhr.onerror = function () { + var errorCallback = function () { + xhr.removeEventListener('load', loadCallback); + xhr.removeEventListener('error', errorCallback); + if (xhr._timeoutId >= 0) { + clearTimeout(xhr._timeoutId); + } + else { + xhr.removeEventListener('timeout', timeoutCallback); + } cb({status: xhr.status, errorMessage: errInfo}, null); }; + var timeoutCallback = function () { + xhr.removeEventListener('load', loadCallback); + xhr.removeEventListener('error', errorCallback); + if (xhr._timeoutId >= 0) { + clearTimeout(xhr._timeoutId); + } + else { + xhr.removeEventListener('timeout', timeoutCallback); + } + cb({status: xhr.status, errorMessage: "Request timeout: " + errInfo}, null); + }; + xhr.addEventListener('load', loadCallback); + xhr.addEventListener('error', errorCallback); if (xhr.ontimeout === undefined) { xhr._timeoutId = setTimeout(function () { - xhr.ontimeout(); + timeoutCallback(); }, xhr.timeout); } - xhr.ontimeout = function () { - cb({status: xhr.status, errorMessage: "Request timeout: " + errInfo}, null); - }; + else { + xhr.addEventListener('timeout', timeoutCallback); + } } xhr.send(null); } else { @@ -836,10 +862,15 @@ cc.loader = (function () { xhr.open("GET", url, true); xhr.responseType = "arraybuffer"; - xhr.onload = function () { + var loadCallback = function () { + xhr.removeEventListener('load', loadCallback); + xhr.removeEventListener('error', errorCallback); if (xhr._timeoutId >= 0) { clearTimeout(xhr._timeoutId); } + else { + xhr.removeEventListener('timeout', timeoutCallback); + } var arrayBuffer = xhr.response; // Note: not oReq.responseText if (arrayBuffer) { window.msg = arrayBuffer; @@ -848,17 +879,38 @@ cc.loader = (function () { xhr.status === 200 ? cb(null, xhr.response) : cb({status:xhr.status, errorMessage:errInfo}, null); } }; - xhr.onerror = function(){ + var errorCallback = function(){ + xhr.removeEventListener('load', loadCallback); + xhr.removeEventListener('error', errorCallback); + if (xhr._timeoutId >= 0) { + clearTimeout(xhr._timeoutId); + } + else { + xhr.removeEventListener('timeout', timeoutCallback); + } cb({status:xhr.status, errorMessage:errInfo}, null); }; + var timeoutCallback = function () { + xhr.removeEventListener('load', loadCallback); + xhr.removeEventListener('error', errorCallback); + if (xhr._timeoutId >= 0) { + clearTimeout(xhr._timeoutId); + } + else { + xhr.removeEventListener('timeout', timeoutCallback); + } + cb({status: xhr.status, errorMessage: "Request timeout: " + errInfo}, null); + }; + xhr.addEventListener('load', loadCallback); + xhr.addEventListener('error', errorCallback); if (xhr.ontimeout === undefined) { xhr._timeoutId = setTimeout(function () { - xhr.ontimeout(); + timeoutCallback(); }, xhr.timeout); } - xhr.ontimeout = function () { - cb({status: xhr.status, errorMessage: "Request timeout: " + errInfo}, null); - }; + else { + xhr.addEventListener('timeout', timeoutCallback); + } xhr.send(null); }, From bb603feefe03783397b14c40a36e43b71c22bcde Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 10:30:11 +0800 Subject: [PATCH 32/65] Fix leak --- cocos2d/core/CCScheduler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCScheduler.js b/cocos2d/core/CCScheduler.js index 0c75dc15af..1504bd70c0 100644 --- a/cocos2d/core/CCScheduler.js +++ b/cocos2d/core/CCScheduler.js @@ -385,7 +385,7 @@ cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{ _removeUpdateFromHash:function (entry) { var self = this; - element = self._hashForUpdates[entry.target.__instanceId]; + var element = self._hashForUpdates[entry.target.__instanceId]; if (element) { // Remove list entry from list var list = element.list, listEntry = element.entry; From d30a1361014fe525ed0ed7926f53f3c66e0d302e Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 10:30:46 +0800 Subject: [PATCH 33/65] Do not register accelerometer event by default --- cocos2d/core/platform/CCInputManager.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCInputManager.js b/cocos2d/core/platform/CCInputManager.js index 382b1f86ed..270c535c7d 100644 --- a/cocos2d/core/platform/CCInputManager.js +++ b/cocos2d/core/platform/CCInputManager.js @@ -601,7 +601,7 @@ cc.inputManager = /** @lends cc.inputManager# */{ this._registerKeyboardEvent(); //register Accelerometer event - this._registerAccelerometerEvent(); + // this._registerAccelerometerEvent(); this._isRegisterEvent = true; }, @@ -609,6 +609,10 @@ cc.inputManager = /** @lends cc.inputManager# */{ _registerKeyboardEvent: function () { }, + /** + * Register Accelerometer event + * @function + */ _registerAccelerometerEvent: function () { }, From 5a643248331a0fd976f3d799e35cd885242cca29 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 10:32:34 +0800 Subject: [PATCH 34/65] Fix spine issues --- cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js | 2 +- extensions/spine/CCSkeleton.js | 9 +++++++++ extensions/spine/CCSkeletonCanvasRenderCmd.js | 4 ++-- extensions/spine/CCSkeletonWebGLRenderCmd.js | 8 ++++---- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js b/cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js index 4a543a616c..51ea5024cb 100644 --- a/cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js +++ b/cocos2d/core/sprites/CCSpriteWebGLRenderCmd.js @@ -298,7 +298,7 @@ proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset) { var node = this._node, locTexture = node._texture; if (!(locTexture && locTexture._textureLoaded && node._rect.width && node._rect.height) || !this._displayedOpacity) - return false; + return 0; // Fill in vertex data with quad information (4 vertices for sprite) var opacity = this._displayedOpacity; diff --git a/extensions/spine/CCSkeleton.js b/extensions/spine/CCSkeleton.js index eec8aa2fbb..0f0d3ebdf3 100644 --- a/extensions/spine/CCSkeleton.js +++ b/extensions/spine/CCSkeleton.js @@ -106,9 +106,18 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ init: function () { cc.Node.prototype.init.call(this); this._premultipliedAlpha = (cc._renderType === cc.game.RENDER_TYPE_WEBGL && cc.OPTIMIZE_BLEND_FUNC_FOR_PREMULTIPLIED_ALPHA); + }, + + onEnter: function () { + cc.Node.prototype.onEnter.call(this); this.scheduleUpdate(); }, + onExit: function () { + this.unscheduleUpdate(); + cc.Node.prototype.onExit.call(this); + }, + /** * Sets whether open debug slots. * @param {boolean} enable true to open, false to close. diff --git a/extensions/spine/CCSkeletonCanvasRenderCmd.js b/extensions/spine/CCSkeletonCanvasRenderCmd.js index 0c37adb83d..1348ba920e 100644 --- a/extensions/spine/CCSkeletonCanvasRenderCmd.js +++ b/extensions/spine/CCSkeletonCanvasRenderCmd.js @@ -102,8 +102,8 @@ proto.rendering = function (wrapper, scaleX, scaleY) { proto.updateStatus = function() { this.originUpdateStatus(); this._updateCurrentRegions(); - this._regionFlag = _ccsg.Node.CanvasRenderCmd.RegionStatus.DirtyDouble; - this._dirtyFlag &= ~_ccsg.Node._dirtyFlags.contentDirty; + this._regionFlag = cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble; + this._dirtyFlag &= ~cc.Node._dirtyFlags.contentDirty; }; proto.getLocalBB = function() { diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js index 221546ed75..af232c1dbb 100644 --- a/extensions/spine/CCSkeletonWebGLRenderCmd.js +++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js @@ -246,8 +246,8 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph var srcIdx = i < 4 ? i % 3 : i - 2; var vx = vertices[srcIdx * 8], vy = vertices[srcIdx * 8 + 1]; - var x = vx * wa + vy * wb + wx, - y = vx * wc + vy * wd + wy; + var x = vx * wa + vy * wc + wx, + y = vx * wb + vy * wd + wy; var r = vertices[srcIdx * 8 + 2] * nodeR, g = vertices[srcIdx * 8 + 3] * nodeG, b = vertices[srcIdx * 8 + 4] * nodeB, @@ -290,8 +290,8 @@ proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, for (var i = 0, n = vertices.length; i < n; i += 8) { var vx = vertices[i], vy = vertices[i + 1]; - var x = vx * wa + vy * wb + wx, - y = vx * wc + vy * wd + wy; + var x = vx * wa + vy * wc + wx, + y = vx * wb + vy * wd + wy; var r = vertices[i + 2] * nodeR, g = vertices[i + 3] * nodeG, b = vertices[i + 4] * nodeB, From e9370a4d95c94e3c8e7eaf9e0ef89cd87e49d670 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 11:03:32 +0800 Subject: [PATCH 35/65] Update version --- cocos2d/core/platform/CCConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCConfig.js b/cocos2d/core/platform/CCConfig.js index 4fb22921f8..ceeddbf5d8 100644 --- a/cocos2d/core/platform/CCConfig.js +++ b/cocos2d/core/platform/CCConfig.js @@ -31,7 +31,7 @@ * @type {String} * @name cc.ENGINE_VERSION */ -window["CocosEngine"] = cc.ENGINE_VERSION = "Cocos2d-JS v3.15"; +window["CocosEngine"] = cc.ENGINE_VERSION = "Cocos2d-JS v3.16"; /** *

From cd3cb0063378eb23d5b18a375ba8a8ee05c5015f Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 14:14:47 +0800 Subject: [PATCH 36/65] Enable 3d projection --- cocos2d/core/CCDirector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCDirector.js b/cocos2d/core/CCDirector.js index bfc8481d68..d0a9cfa7b5 100644 --- a/cocos2d/core/CCDirector.js +++ b/cocos2d/core/CCDirector.js @@ -943,4 +943,4 @@ cc.Director.PROJECTION_CUSTOM = 3; * @constant * @type {Number} */ -cc.Director.PROJECTION_DEFAULT = cc.Director.PROJECTION_2D; +cc.Director.PROJECTION_DEFAULT = cc.Director.PROJECTION_3D; From eaa5199205b6020c77ba7539b4c05a24b65a2dd4 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 14:56:40 +0800 Subject: [PATCH 37/65] Fix glProgramState undefined issue in DrawingPrimitives --- cocos2d/core/CCDrawingPrimitivesWebGL.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/core/CCDrawingPrimitivesWebGL.js b/cocos2d/core/CCDrawingPrimitivesWebGL.js index e6fc9b7262..db8047aacc 100644 --- a/cocos2d/core/CCDrawingPrimitivesWebGL.js +++ b/cocos2d/core/CCDrawingPrimitivesWebGL.js @@ -61,6 +61,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# _t._shader = cc.shaderCache.programForKey(cc.SHADER_POSITION_UCOLOR); _t._shader._addUniformLocation(this._colorLocation); _t._shader._addUniformLocation(this._pointSizeLocation); + _t._glProgramState = new cc.GLProgramState(_t._shader); _t._initialized = true; } From b2b9b6e7d65e02a0be3e8a81cd3fdc324768596d Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 15:10:24 +0800 Subject: [PATCH 38/65] Use default scheduler to control action manager --- cocos2d/core/CCDirector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/CCDirector.js b/cocos2d/core/CCDirector.js index d0a9cfa7b5..b8a021f43c 100644 --- a/cocos2d/core/CCDirector.js +++ b/cocos2d/core/CCDirector.js @@ -136,6 +136,7 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ //action manager if (cc.ActionManager) { this._actionManager = new cc.ActionManager(); + this._scheduler.scheduleUpdate(this._actionManager, cc.Scheduler.PRIORITY_SYSTEM, false); } else { this._actionManager = null; } @@ -228,7 +229,6 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ //tick before glClear: issue #533 if (!this._paused) { - this._actionManager.update(this._deltaTime); this._scheduler.update(this._deltaTime); cc.eventManager.dispatchEvent(this._eventAfterUpdate); } From a3c5d98bfa11fdfb6213a3f2132b1aee3bae1f2e Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 16:23:01 +0800 Subject: [PATCH 39/65] reorderChild can update arrival order --- cocos2d/core/base-nodes/CCNode.js | 5 ++--- cocos2d/particle/CCParticleBatchNode.js | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cocos2d/core/base-nodes/CCNode.js b/cocos2d/core/base-nodes/CCNode.js index 62bd9e4a38..9d3e6f15e5 100644 --- a/cocos2d/core/base-nodes/CCNode.js +++ b/cocos2d/core/base-nodes/CCNode.js @@ -306,6 +306,8 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ * @param {Number} localZOrder */ setLocalZOrder: function (localZOrder) { + if (localZOrder === this._localZOrder) + return; if (this._parent) this._parent.reorderChild(this, localZOrder); else @@ -1365,9 +1367,6 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ cc.log(cc._LogInfos.Node_reorderChild_2); return; } - if (zOrder === child.zIndex) { - return; - } cc.renderer.childrenOrderDirty = this._reorderChildDirty = true; child.arrivalOrder = cc.s_globalOrderOfArrival; cc.s_globalOrderOfArrival++; diff --git a/cocos2d/particle/CCParticleBatchNode.js b/cocos2d/particle/CCParticleBatchNode.js index 3952bcdbbb..53c381fc30 100644 --- a/cocos2d/particle/CCParticleBatchNode.js +++ b/cocos2d/particle/CCParticleBatchNode.js @@ -278,9 +278,6 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ return; } - if (zOrder === child.zIndex) - return; - // no reordering if only 1 child if (this._children.length > 1) { var getIndexes = this._getCurrentIndex(child, zOrder); From 869af73494b0d2172b61b6ff0d75f0f4afdba6ca Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 8 Sep 2017 16:29:58 +0800 Subject: [PATCH 40/65] Fix infinite call stack in ArmatureWebGLRenderCmd --- cocos2d/core/CCDrawingPrimitivesWebGL.js | 2 +- extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/CCDrawingPrimitivesWebGL.js b/cocos2d/core/CCDrawingPrimitivesWebGL.js index db8047aacc..6daa60cb01 100644 --- a/cocos2d/core/CCDrawingPrimitivesWebGL.js +++ b/cocos2d/core/CCDrawingPrimitivesWebGL.js @@ -61,7 +61,7 @@ cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# _t._shader = cc.shaderCache.programForKey(cc.SHADER_POSITION_UCOLOR); _t._shader._addUniformLocation(this._colorLocation); _t._shader._addUniformLocation(this._pointSizeLocation); - _t._glProgramState = new cc.GLProgramState(_t._shader); + _t._glProgramState = cc.GLProgramState.getOrCreateWithGLProgram(_t._shader); _t._initialized = true; } diff --git a/extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js b/extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js index bf48084815..6f24c7b677 100644 --- a/extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js +++ b/extensions/cocostudio/armature/CCArmatureWebGLRenderCmd.js @@ -118,7 +118,7 @@ }; proto.setShaderProgram = function (shaderProgram) { - this._shaderProgram = shaderProgram; + this._glProgramState = cc.GLProgramState.getOrCreateWithGLProgram(shaderProgram); }; proto._updateColorAndOpacity = function (skinRenderCmd, bone) { From b08573693a9f3d7b102140d6b1e1706d48110a78 Mon Sep 17 00:00:00 2001 From: Stefan Nguyen Date: Sun, 10 Sep 2017 17:06:42 +0700 Subject: [PATCH 41/65] Fix label stroke is rendered ugly on web platform --- cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js index 8693c850d1..44c8f1866f 100644 --- a/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js +++ b/cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js @@ -387,8 +387,10 @@ cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9\-¿¡«À-ÖØ-öø-ʯ\u0300-\u034e\u03 var locStrLen = this._strings.length; for (var i = 0; i < locStrLen; i++) { var line = this._strings[i]; - if (locStrokeEnabled) + if (locStrokeEnabled) { + context.lineJoin = 'round'; context.strokeText(line, xOffset, yOffsetArray[i]); + } context.fillText(line, xOffset, yOffsetArray[i]); } cc.g_NumberOfDraws++; From 6adee332b9fdcaf90e94fe1395ab11777a133dfd Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 13 Sep 2017 11:30:27 +0800 Subject: [PATCH 42/65] Fix ProgressTimer vertex not updating when transform changing --- cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js b/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js index c78b0d5f9d..8a89913eed 100644 --- a/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js +++ b/cocos2d/progress-timer/CCProgressTimerWebGLRenderCmd.js @@ -35,6 +35,7 @@ this._bl = cc.p(); this._tr = cc.p(); + this._transformUpdating = false; this.initCmd(); }; @@ -55,7 +56,9 @@ this._tr.x = rx * wt.a + ty * wt.c + wt.tx; this._tr.y = rx * wt.b + ty * wt.d + wt.ty; + this._transformUpdating = true; this._updateProgressData(); + this._transformUpdating = false; }; proto.rendering = function (ctx) { @@ -449,7 +452,7 @@ this._updateColor(); var locVertexData = this._vertexData; - if (!sameIndexCount) { + if (this._transformUpdating || !sameIndexCount) { // First we populate the array with the m_tMidpoint, then all // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint this._textureCoordFromAlphaPoint(locVertexData[0].texCoords, locMidPoint.x, locMidPoint.y); From d67a8b3a8e34e02be91c9cfd2171961a57b889e4 Mon Sep 17 00:00:00 2001 From: danilo neves cruz Date: Wed, 13 Sep 2017 02:32:22 -0300 Subject: [PATCH 43/65] optimize uniform cache performance --- cocos2d/shaders/CCGLProgram.js | 26 ++++++++++++++++++-------- cocos2d/shaders/CCGLProgramState.js | 6 +++--- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/cocos2d/shaders/CCGLProgram.js b/cocos2d/shaders/CCGLProgram.js index 67e23db2d7..4e8301d50b 100644 --- a/cocos2d/shaders/CCGLProgram.js +++ b/cocos2d/shaders/CCGLProgram.js @@ -48,11 +48,18 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ var updated = false; var element = this._hashForUniforms[name]; - var args = Array.isArray(arguments[1]) ? arguments[1] : - Array.prototype.slice.call(arguments, 1); + var args; + if (Array.isArray(arguments[1])) { + args = arguments[1]; + } else { + args = new Array(arguments.length - 1); + for (var i = 1; i < arguments.length; i += 1) { + args[i - 1] = arguments[i]; + } + } if (!element || element.length !== args.length) { - this._hashForUniforms[name] = args.slice(); + this._hashForUniforms[name] = [].concat(args); updated = true; } else { for (var i = 0; i < args.length; i += 1) { @@ -260,11 +267,14 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ * cc.UNIFORM_SAMPLER */ updateUniforms: function () { - [cc.UNIFORM_PMATRIX_S, cc.UNIFORM_MVMATRIX_S, cc.UNIFORM_MVPMATRIX_S, - cc.UNIFORM_TIME_S, cc.UNIFORM_SINTIME_S, cc.UNIFORM_COSTIME_S, - cc.UNIFORM_RANDOM01_S, cc.UNIFORM_SAMPLER_S].forEach(function(name) { - this._addUniformLocation(name); - }.bind(this)); + this._addUniformLocation(cc.UNIFORM_PMATRIX_S); + this._addUniformLocation(cc.UNIFORM_MVMATRIX_S); + this._addUniformLocation(cc.UNIFORM_MVPMATRIX_S); + this._addUniformLocation(cc.UNIFORM_TIME_S); + this._addUniformLocation(cc.UNIFORM_SINTIME_S); + this._addUniformLocation(cc.UNIFORM_COSTIME_S); + this._addUniformLocation(cc.UNIFORM_RANDOM01_S); + this._addUniformLocation(cc.UNIFORM_SAMPLER_S); this._usesTime = (this._uniforms[cc.UNIFORM_TIME_S] != null || this._uniforms[cc.UNIFORM_SINTIME_S] != null || this._uniforms[cc.UNIFORM_COSTIME_S] != null); this.use(); diff --git a/cocos2d/shaders/CCGLProgramState.js b/cocos2d/shaders/CCGLProgramState.js index 2e9ec348ee..c5bc2fd428 100644 --- a/cocos2d/shaders/CCGLProgramState.js +++ b/cocos2d/shaders/CCGLProgramState.js @@ -163,9 +163,9 @@ cc.GLProgramState.prototype = { this._glprogram._setUniformForMVPMatrixWithMat4(modelView); } - Object.values(this._uniforms).forEach(function(uniform) { - uniform.apply(); - }); + for (var name in this._uniforms) { + this._uniforms[name].apply(); + }; }, setGLProgram: function setGLProgram(glprogram) { From 5db5d52126c7e4961dafb2cc971fa1641ab7b924 Mon Sep 17 00:00:00 2001 From: Minh Quy Date: Tue, 19 Sep 2017 14:22:13 +0700 Subject: [PATCH 44/65] Use the same family font in tmpEdTxt and edTxt --- extensions/editbox/CCEditBox.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/editbox/CCEditBox.js b/extensions/editbox/CCEditBox.js index ca112fdab4..3a535438f2 100644 --- a/extensions/editbox/CCEditBox.js +++ b/extensions/editbox/CCEditBox.js @@ -854,6 +854,7 @@ cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9Sp var thisPointer = this; var tmpEdTxt = this._edTxt = document.createElement('input'); tmpEdTxt.type = 'text'; + tmpEdTxt.style.fontFamily = this._edFontName; tmpEdTxt.style.fontSize = this._edFontSize + 'px'; tmpEdTxt.style.color = '#000000'; tmpEdTxt.style.border = 0; @@ -949,6 +950,7 @@ cc.EditBox.create = function (size, normal9SpriteBg, press9SpriteBg, disabled9Sp var thisPointer = this; var tmpEdTxt = this._edTxt = document.createElement('textarea'); tmpEdTxt.type = 'text'; + tmpEdTxt.style.fontFamily = this._edFontName; tmpEdTxt.style.fontSize = this._edFontSize + 'px'; tmpEdTxt.style.color = '#000000'; tmpEdTxt.style.border = 0; From 639073564df67c2f086d39abac469d56bb41ad4d Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 21 Sep 2017 22:45:35 +0800 Subject: [PATCH 45/65] Fix acceleration event crash --- cocos2d/core/platform/CCInputExtension.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/platform/CCInputExtension.js b/cocos2d/core/platform/CCInputExtension.js index 6f780104b1..e61f58459a 100644 --- a/cocos2d/core/platform/CCInputExtension.js +++ b/cocos2d/core/platform/CCInputExtension.js @@ -39,10 +39,12 @@ _p.setAccelerometerEnabled = function(isEnable){ var scheduler = cc.director.getScheduler(); if(_t._accelEnabled){ _t._accelCurTime = 0; + _t._registerAccelerometerEvent(); scheduler.scheduleUpdate(_t); } else { _t._accelCurTime = 0; - scheduler.scheduleUpdate(_t); + _t._unregisterAccelerometerEvent(); + scheduler.unscheduleUpdate(_t); } }; @@ -85,7 +87,14 @@ _p._registerAccelerometerEvent = function(){ _t._minus = -1; } - w.addEventListener(_deviceEventType, _t.didAccelerate.bind(_t), false); + _t.didAccelerateCallback = _t.didAccelerate.bind(_t); + w.addEventListener(_deviceEventType, _t.didAccelerateCallback, false); +}; + +_p._unregisterAccelerometerEvent = function () { + this._acceleration = null; + var _deviceEventType = (this._accelDeviceEvent === window.DeviceMotionEvent) ? "devicemotion" : "deviceorientation"; + window.removeEventListener(_deviceEventType, this.didAccelerateCallback, false); }; _p.didAccelerate = function (eventData) { From c27fa163cdcbda86101adaf77bf5cec2c7740c34 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 22 Sep 2017 01:21:00 +0800 Subject: [PATCH 46/65] Fix advanced release mode --- CCBoot.js | 2 +- .../core/base-nodes/CCNodeWebGLRenderCmd.js | 2 ++ cocos2d/core/platform/CCClass.js | 26 +++++++++---------- cocos2d/core/textures/TexturesWebGL.js | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/CCBoot.js b/CCBoot.js index 9cfc1ae2db..f6ec16bc1f 100644 --- a/CCBoot.js +++ b/CCBoot.js @@ -992,7 +992,7 @@ cc.loader = (function () { delete _queue[url]; } - if (ENABLE_IMAEG_POOL && cc._renderType === cc.game.RENDER_TYPE_WEBGL) { + if (window.ENABLE_IMAEG_POOL && cc._renderType === cc.game.RENDER_TYPE_WEBGL) { imagePool.put(img); } }; diff --git a/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js b/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js index 0506dd522b..7680017273 100644 --- a/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js +++ b/cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js @@ -60,4 +60,6 @@ set: function (value) { this.setShaderProgram(value); }, get: function () { return this.getShaderProgram(); } }); + /** @expose */ + proto._shaderProgram; })(); diff --git a/cocos2d/core/platform/CCClass.js b/cocos2d/core/platform/CCClass.js index 6b7a2e8043..be34ad92eb 100644 --- a/cocos2d/core/platform/CCClass.js +++ b/cocos2d/core/platform/CCClass.js @@ -140,19 +140,19 @@ cc.inject = function (srcPrototype, destPrototype) { * @namespace * @name ClassManager */ -var ClassManager = { - id : (0|(Math.random()*998)), +var ClassManager = function () { + var id = (0|(Math.random()*998)); + var instanceId = (0|(Math.random()*998)); - instanceId : (0|(Math.random()*998)), - - getNewID : function(){ - return this.id++; - }, + this.getNewID = function () { + return id++; + }; - getNewInstanceId : function(){ - return this.instanceId++; - } + this.getNewInstanceId = function () { + return instanceId++; + }; }; +var classManager = new ClassManager(); /* Managed JavaScript Inheritance * Based on John Resig's Simple JavaScript Inheritance http://ejohn.org/blog/simple-javascript-inheritance/ @@ -192,7 +192,7 @@ var ClassManager = { var Class; if (cc.game.config && cc.game.config[cc.game.CONFIG_KEY.exposeClassName]) { var constructor = "(function " + (props._className || "Class") + " (arg0, arg1, arg2, arg3, arg4, arg5) {\n"; - constructor += " this.__instanceId = ClassManager.getNewInstanceId();\n"; + constructor += " this.__instanceId = classManager.getNewInstanceId();\n"; constructor += " if (this.ctor) {\n"; constructor += " switch (arguments.length) {\n"; constructor += " case 0: this.ctor(); break;\n"; @@ -208,7 +208,7 @@ var ClassManager = { } else { Class = function (arg0, arg1, arg2, arg3, arg4) { - this.__instanceId = ClassManager.getNewInstanceId(); + this.__instanceId = classManager.getNewInstanceId(); if (this.ctor) { switch (arguments.length) { case 0: this.ctor(); break; @@ -223,7 +223,7 @@ var ClassManager = { }; } - desc.value = ClassManager.getNewID(); + desc.value = classManager.getNewID(); Object.defineProperty(prototype, '__pid', desc); // Populate our constructed prototype object diff --git a/cocos2d/core/textures/TexturesWebGL.js b/cocos2d/core/textures/TexturesWebGL.js index 5811f159ef..2dfe145e56 100644 --- a/cocos2d/core/textures/TexturesWebGL.js +++ b/cocos2d/core/textures/TexturesWebGL.js @@ -496,7 +496,7 @@ cc._tmp.WebGLTexture2D = function () { self._hasPremultipliedAlpha = premultiplied; self._hasMipmaps = false; - if (ENABLE_IMAEG_POOL) { + if (window.ENABLE_IMAEG_POOL) { self._htmlElementObj = null; } From ac10928ad55a8a799e47a9b7bfe3b8a484bc74be Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 22 Sep 2017 10:23:04 +0800 Subject: [PATCH 47/65] Revert "web UIButton support BMFont" --- extensions/ccui/uiwidgets/UIButton.js | 28 +++++++-------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/extensions/ccui/uiwidgets/UIButton.js b/extensions/ccui/uiwidgets/UIButton.js index 1c3f102a4f..4741e2e767 100644 --- a/extensions/ccui/uiwidgets/UIButton.js +++ b/extensions/ccui/uiwidgets/UIButton.js @@ -100,22 +100,12 @@ ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{ } }, - _createTitleRendererIfNeeded: function (fntFile) { + _createTitleRendererIfNeeded: function ( ) { if(!this._titleRenderer) { - if(fntFile != null) - { - this._titleRenderer = new cc.LabelBMFont("", fntFile); - this._titleRenderer.setAlignment(cc.TEXT_ALIGNMENT_CENTER); - } - else - { - this._titleRenderer = new cc.LabelTTF(""); - this._titleRenderer.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER); - } - - this._titleRenderer.setAnchorPoint(0.5, 0.4); + this._titleRenderer = new cc.LabelTTF(""); + this._titleRenderer.setAnchorPoint(0.5, 0.5); this._titleColor = cc.color.WHITE; - + this._titleRenderer.setVerticalAlignment(cc.VERTICAL_TEXT_ALIGNMENT_CENTER); this.addProtectedChild(this._titleRenderer, ccui.Button.TITLE_RENDERER_ZORDER, -1); } }, @@ -667,11 +657,7 @@ ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{ setTitleFontSize: function (size) { this._createTitleRendererIfNeeded(); - if(this._titleRenderer.setFontSize) - this._titleRenderer.setFontSize(size); - else - this._titleRenderer.setBoundingWidth(size); - + this._titleRenderer.setFontSize(size); this._fontSize = size; }, @@ -719,9 +705,9 @@ ccui.Button = ccui.Widget.extend(/** @lends ccui.Button# */{ * @param {String} fontName */ setTitleFontName: function (fontName) { - this._createTitleRendererIfNeeded(fontName); + this._createTitleRendererIfNeeded(); - this._titleRenderer.setFontName && this._titleRenderer.setFontName(fontName); + this._titleRenderer.setFontName(fontName); this._fontName = fontName; }, From 926dc6b24177ed72de93098a7b02010449e5bbc5 Mon Sep 17 00:00:00 2001 From: linkqjlin Date: Wed, 6 Sep 2017 21:14:19 +0800 Subject: [PATCH 48/65] Use arraybuffer responseType in BinaryLoader --- cocos2d/core/utils/BinaryLoader.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cocos2d/core/utils/BinaryLoader.js b/cocos2d/core/utils/BinaryLoader.js index 7127b1279c..01e5c6194b 100644 --- a/cocos2d/core/utils/BinaryLoader.js +++ b/cocos2d/core/utils/BinaryLoader.js @@ -37,6 +37,7 @@ cc.loader.loadBinary = function (url, cb) { var xhr = this.getXMLHttpRequest(), errInfo = "load " + url + " failed!"; xhr.open("GET", url, true); + xhr.responseType = 'arraybuffer'; if (cc.loader.loadBinary._IEFilter) { // IE-specific logic here xhr.setRequestHeader("Accept-Charset", "x-user-defined"); @@ -49,7 +50,7 @@ cc.loader.loadBinary = function (url, cb) { } else { if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=x-user-defined"); xhr.onload = function () { - xhr.readyState === 4 && xhr.status === 200 ? cb(null, self._str2Uint8Array(xhr.responseText)) : cb(errInfo); + xhr.readyState === 4 && xhr.status === 200 ? cb(null, xhr.response) : cb(errInfo); }; } xhr.send(null); @@ -80,6 +81,7 @@ cc.loader.loadBinarySync = function (url) { req.timeout = 0; var errInfo = "load " + url + " failed!"; req.open('GET', url, false); + req.responseType = 'arraybuffer'; var arrayInfo = null; if (cc.loader.loadBinary._IEFilter) { req.setRequestHeader("Accept-Charset", "x-user-defined"); @@ -102,7 +104,7 @@ cc.loader.loadBinarySync = function (url) { return null; } - arrayInfo = this._str2Uint8Array(req.responseText); + arrayInfo = req.response; } return arrayInfo; }; @@ -151,4 +153,4 @@ if (cc.loader.loadBinary._IEFilter) { return byteMapping[match]; }) + lastChr; }; -} \ No newline at end of file +} From 56118065f0b11b298aab41356688758d79b75f7b Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 29 Sep 2017 10:21:39 +0800 Subject: [PATCH 49/65] Return Uint8Array in BinaryLoader (keep consistency) --- cocos2d/core/utils/BinaryLoader.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/core/utils/BinaryLoader.js b/cocos2d/core/utils/BinaryLoader.js index 01e5c6194b..67f1a4ccff 100644 --- a/cocos2d/core/utils/BinaryLoader.js +++ b/cocos2d/core/utils/BinaryLoader.js @@ -50,7 +50,7 @@ cc.loader.loadBinary = function (url, cb) { } else { if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=x-user-defined"); xhr.onload = function () { - xhr.readyState === 4 && xhr.status === 200 ? cb(null, xhr.response) : cb(errInfo); + xhr.readyState === 4 && xhr.status === 200 ? cb(null, new Uint8Array(xhr.response)) : cb(errInfo); }; } xhr.send(null); @@ -104,7 +104,7 @@ cc.loader.loadBinarySync = function (url) { return null; } - arrayInfo = req.response; + arrayInfo = new Uint8Array(req.response); } return arrayInfo; }; From f63c49d0cef6cbefef5304a831b22670e6901a2f Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 29 Sep 2017 12:47:23 +0800 Subject: [PATCH 50/65] Fix matrix array not being updated in gl program issue (fix cocos2d/cocos2d-html5/3511) --- cocos2d/shaders/CCGLProgram.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/shaders/CCGLProgram.js b/cocos2d/shaders/CCGLProgram.js index 4e8301d50b..0cf9f4702d 100644 --- a/cocos2d/shaders/CCGLProgram.js +++ b/cocos2d/shaders/CCGLProgram.js @@ -63,7 +63,8 @@ cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ updated = true; } else { for (var i = 0; i < args.length; i += 1) { - if (args[i] !== element[i]) { + // Array and Typed Array inner values could be changed, so we must update them + if (args[i] !== element[i] || typeof args[i] === 'object') { element[i] = args[i]; updated = true; } From 0e6eda354422d1c3eb1e759db6d20f49d74d685a Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 29 Sep 2017 17:51:31 +0800 Subject: [PATCH 51/65] Revert wrong changes to Spine --- extensions/spine/CCSkeletonWebGLRenderCmd.js | 4 ++-- extensions/spine/Spine.js | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js index af232c1dbb..bbe4cd805d 100644 --- a/extensions/spine/CCSkeletonWebGLRenderCmd.js +++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js @@ -290,8 +290,8 @@ proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, for (var i = 0, n = vertices.length; i < n; i += 8) { var vx = vertices[i], vy = vertices[i + 1]; - var x = vx * wa + vy * wc + wx, - y = vx * wb + vy * wd + wy; + var x = vx * wa + vy * wb + wx, + y = vx * wc + vy * wd + wy; var r = vertices[i + 2] * nodeR, g = vertices[i + 3] * nodeG, b = vertices[i + 4] * nodeB, diff --git a/extensions/spine/Spine.js b/extensions/spine/Spine.js index c845c19f41..9da03c2974 100644 --- a/extensions/spine/Spine.js +++ b/extensions/spine/Spine.js @@ -4241,12 +4241,13 @@ var spine; var scale = this.scale; attachment.worldVerticesLength = verticesLength; var vertices = map.vertices; - if (verticesLength == vertices.length) { + var scaledVertices = spine.Utils.toFloatArray(vertices); + if (verticesLength == scaledVertices.length) { if (scale != 1) { for (var i = 0, n = vertices.length; i < n; i++) - vertices[i] *= scale; + scaledVertices[i] *= scale; } - attachment.vertices = spine.Utils.toFloatArray(vertices); + attachment.vertices = scaledVertices; return; } var weights = new Array(); From b2095577b23f06a168a3dd5e14fa56b7bf4e8e41 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Sat, 30 Sep 2017 12:38:15 +0800 Subject: [PATCH 52/65] Avoid setting responseType in synchronous xhr --- cocos2d/core/utils/BinaryLoader.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cocos2d/core/utils/BinaryLoader.js b/cocos2d/core/utils/BinaryLoader.js index 67f1a4ccff..46b82b65cf 100644 --- a/cocos2d/core/utils/BinaryLoader.js +++ b/cocos2d/core/utils/BinaryLoader.js @@ -81,7 +81,6 @@ cc.loader.loadBinarySync = function (url) { req.timeout = 0; var errInfo = "load " + url + " failed!"; req.open('GET', url, false); - req.responseType = 'arraybuffer'; var arrayInfo = null; if (cc.loader.loadBinary._IEFilter) { req.setRequestHeader("Accept-Charset", "x-user-defined"); @@ -104,7 +103,7 @@ cc.loader.loadBinarySync = function (url) { return null; } - arrayInfo = new Uint8Array(req.response); + arrayInfo = self._str2Uint8Array(req.responseText); } return arrayInfo; }; From 473efb56d38d2f6c70559cc30505c41fff653da8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Petre=CC=81re?= Date: Wed, 11 Oct 2017 09:32:57 -0300 Subject: [PATCH 53/65] Resize event on browser not working --- cocos2d/core/platform/CCEGLView.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cocos2d/core/platform/CCEGLView.js b/cocos2d/core/platform/CCEGLView.js index 448f1b2f1b..f91e54b8b8 100755 --- a/cocos2d/core/platform/CCEGLView.js +++ b/cocos2d/core/platform/CCEGLView.js @@ -187,6 +187,8 @@ cc.EGLView = cc.Class.extend(/** @lends cc.view# */{ if (sys.isMobile) { window.addEventListener('orientationchange', this._orientationChange); + } else { + this._orientationChanging = false; } }, From 749c764583f9d9e9d25598dc4d4527d5d8248fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Petre=CC=81re?= Date: Tue, 12 Dec 2017 18:10:23 -0200 Subject: [PATCH 54/65] Some few text fixes --- CCBoot.js | 2 +- cocos2d/actions/CCActionInterval.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CCBoot.js b/CCBoot.js index ebe862bedb..22c50494b6 100644 --- a/CCBoot.js +++ b/CCBoot.js @@ -1064,7 +1064,7 @@ cc.loader = (function () { loader = _register[type.toLowerCase()]; } if (!loader) { - cc.error("loader for [" + type + "] not exists!"); + cc.error("loader for [" + type + "] doesn't exist!"); return cb(); } var realUrl = url; diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index 7534d17fca..905d72b0a2 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -137,7 +137,7 @@ cc.ActionInterval = cc.FiniteTimeAction.extend(/** @lends cc.ActionInterval# */{ * * @example * //example - * action.easeing(cc.easeIn(3.0)); + * action.easing(cc.easeIn(3.0)); * @param {Object} easeObj * @returns {cc.ActionInterval} */ @@ -997,7 +997,7 @@ cc.Spawn = cc.ActionInterval.extend(/** @lends cc.Spawn# */{ * Create a spawn action which runs several actions in parallel. * @function * @param {Array|cc.FiniteTimeAction}tempArray - * @return {cc.FiniteTimeAction} + * @return {cc.Spawn} * @example * // example * var action = cc.spawn(cc.jumpBy(2, cc.p(300, 0), 50, 4), cc.rotateBy(2, 720)); @@ -1022,7 +1022,7 @@ cc.spawn = function (/*Multiple Arguments*/tempArray) { * @static * @deprecated since v3.0
Please use cc.spawn instead. * @param {Array|cc.FiniteTimeAction}tempArray - * @return {cc.FiniteTimeAction} + * @return {cc.Spawn} */ cc.Spawn.create = cc.spawn; From 71eac1e696200ccb835d98d1982faf5dcedf575d Mon Sep 17 00:00:00 2001 From: drelaptop Date: Tue, 10 Apr 2018 14:50:51 +0800 Subject: [PATCH 55/65] update spine-core to 3.6.39 --- extensions/spine/Spine.js | 2884 +++++++++++++++++++++++++------------ 1 file changed, 1990 insertions(+), 894 deletions(-) diff --git a/extensions/spine/Spine.js b/extensions/spine/Spine.js index 9da03c2974..b4ffec4b15 100644 --- a/extensions/spine/Spine.js +++ b/extensions/spine/Spine.js @@ -1,10 +1,15 @@ -// Spine runtime version 3.5.35 +// Spine runtime version 3.6.39 -var __extends = (this && this.__extends) || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); -}; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); var spine; (function (spine) { var Animation = (function () { @@ -17,7 +22,7 @@ var spine; this.timelines = timelines; this.duration = duration; } - Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, setupPose, mixingOut) { + Animation.prototype.apply = function (skeleton, lastTime, time, loop, events, alpha, pose, direction) { if (skeleton == null) throw new Error("skeleton cannot be null."); if (loop && this.duration != 0) { @@ -27,7 +32,7 @@ var spine; } var timelines = this.timelines; for (var i = 0, n = timelines.length; i < n; i++) - timelines[i].apply(skeleton, lastTime, time, events, alpha, setupPose, mixingOut); + timelines[i].apply(skeleton, lastTime, time, events, alpha, pose, direction); }; Animation.binarySearch = function (values, target, step) { if (step === void 0) { step = 1; } @@ -55,6 +60,18 @@ var spine; return Animation; }()); spine.Animation = Animation; + var MixPose; + (function (MixPose) { + MixPose[MixPose["setup"] = 0] = "setup"; + MixPose[MixPose["current"] = 1] = "current"; + MixPose[MixPose["currentLayered"] = 2] = "currentLayered"; + })(MixPose = spine.MixPose || (spine.MixPose = {})); + var MixDirection; + (function (MixDirection) { + MixDirection[MixDirection["in"] = 0] = "in"; + MixDirection[MixDirection["out"] = 1] = "out"; + })(MixDirection = spine.MixDirection || (spine.MixDirection = {})); + var TimelineType; (function (TimelineType) { TimelineType[TimelineType["rotate"] = 0] = "rotate"; TimelineType[TimelineType["translate"] = 1] = "translate"; @@ -70,8 +87,8 @@ var spine; TimelineType[TimelineType["pathConstraintPosition"] = 11] = "pathConstraintPosition"; TimelineType[TimelineType["pathConstraintSpacing"] = 12] = "pathConstraintSpacing"; TimelineType[TimelineType["pathConstraintMix"] = 13] = "pathConstraintMix"; - })(spine.TimelineType || (spine.TimelineType = {})); - var TimelineType = spine.TimelineType; + TimelineType[TimelineType["twoColor"] = 14] = "twoColor"; + })(TimelineType = spine.TimelineType || (spine.TimelineType = {})); var CurveTimeline = (function () { function CurveTimeline(frameCount) { if (frameCount <= 0) @@ -147,18 +164,19 @@ var spine; var y = curves[i - 1]; return y + (1 - y) * (percent - x) / (1 - x); }; - CurveTimeline.LINEAR = 0; - CurveTimeline.STEPPED = 1; - CurveTimeline.BEZIER = 2; - CurveTimeline.BEZIER_SIZE = 10 * 2 - 1; return CurveTimeline; }()); + CurveTimeline.LINEAR = 0; + CurveTimeline.STEPPED = 1; + CurveTimeline.BEZIER = 2; + CurveTimeline.BEZIER_SIZE = 10 * 2 - 1; spine.CurveTimeline = CurveTimeline; var RotateTimeline = (function (_super) { __extends(RotateTimeline, _super); function RotateTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount << 1); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount << 1); + return _this; } RotateTimeline.prototype.getPropertyId = function () { return (TimelineType.rotate << 24) + this.boneIndex; @@ -168,21 +186,28 @@ var spine; this.frames[frameIndex] = time; this.frames[frameIndex + RotateTimeline.ROTATION] = degrees; }; - RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + RotateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var frames = this.frames; var bone = skeleton.bones[this.boneIndex]; if (time < frames[0]) { - if (setupPose) - bone.rotation = bone.data.rotation; + switch (pose) { + case MixPose.setup: + bone.rotation = bone.data.rotation; + return; + case MixPose.current: + var r_1 = bone.data.rotation - bone.rotation; + r_1 -= (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360; + bone.rotation += r_1 * alpha; + } return; } if (time >= frames[frames.length - RotateTimeline.ENTRIES]) { - if (setupPose) + if (pose == MixPose.setup) bone.rotation = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] * alpha; else { - var r_1 = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation; - r_1 -= (16384 - ((16384.499999999996 - r_1 / 360) | 0)) * 360; - bone.rotation += r_1 * alpha; + var r_2 = bone.data.rotation + frames[frames.length + RotateTimeline.PREV_ROTATION] - bone.rotation; + r_2 -= (16384 - ((16384.499999999996 - r_2 / 360) | 0)) * 360; + bone.rotation += r_2 * alpha; } return; } @@ -193,7 +218,7 @@ var spine; var r = frames[frame + RotateTimeline.ROTATION] - prevRotation; r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; r = prevRotation + r * percent; - if (setupPose) { + if (pose == MixPose.setup) { r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; bone.rotation = bone.data.rotation + r * alpha; } @@ -203,18 +228,19 @@ var spine; bone.rotation += r * alpha; } }; - RotateTimeline.ENTRIES = 2; - RotateTimeline.PREV_TIME = -2; - RotateTimeline.PREV_ROTATION = -1; - RotateTimeline.ROTATION = 1; return RotateTimeline; }(CurveTimeline)); + RotateTimeline.ENTRIES = 2; + RotateTimeline.PREV_TIME = -2; + RotateTimeline.PREV_ROTATION = -1; + RotateTimeline.ROTATION = 1; spine.RotateTimeline = RotateTimeline; var TranslateTimeline = (function (_super) { __extends(TranslateTimeline, _super); function TranslateTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TranslateTimeline.ENTRIES); + return _this; } TranslateTimeline.prototype.getPropertyId = function () { return (TimelineType.translate << 24) + this.boneIndex; @@ -225,13 +251,18 @@ var spine; this.frames[frameIndex + TranslateTimeline.X] = x; this.frames[frameIndex + TranslateTimeline.Y] = y; }; - TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + TranslateTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var frames = this.frames; var bone = skeleton.bones[this.boneIndex]; if (time < frames[0]) { - if (setupPose) { - bone.x = bone.data.x; - bone.y = bone.data.y; + switch (pose) { + case MixPose.setup: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case MixPose.current: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; } return; } @@ -249,7 +280,7 @@ var spine; x += (frames[frame + TranslateTimeline.X] - x) * percent; y += (frames[frame + TranslateTimeline.Y] - y) * percent; } - if (setupPose) { + if (pose == MixPose.setup) { bone.x = bone.data.x + x * alpha; bone.y = bone.data.y + y * alpha; } @@ -258,30 +289,35 @@ var spine; bone.y += (bone.data.y + y - bone.y) * alpha; } }; - TranslateTimeline.ENTRIES = 3; - TranslateTimeline.PREV_TIME = -3; - TranslateTimeline.PREV_X = -2; - TranslateTimeline.PREV_Y = -1; - TranslateTimeline.X = 1; - TranslateTimeline.Y = 2; return TranslateTimeline; }(CurveTimeline)); + TranslateTimeline.ENTRIES = 3; + TranslateTimeline.PREV_TIME = -3; + TranslateTimeline.PREV_X = -2; + TranslateTimeline.PREV_Y = -1; + TranslateTimeline.X = 1; + TranslateTimeline.Y = 2; spine.TranslateTimeline = TranslateTimeline; var ScaleTimeline = (function (_super) { __extends(ScaleTimeline, _super); function ScaleTimeline(frameCount) { - _super.call(this, frameCount); + return _super.call(this, frameCount) || this; } ScaleTimeline.prototype.getPropertyId = function () { return (TimelineType.scale << 24) + this.boneIndex; }; - ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + ScaleTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var frames = this.frames; var bone = skeleton.bones[this.boneIndex]; if (time < frames[0]) { - if (setupPose) { - bone.scaleX = bone.data.scaleX; - bone.scaleY = bone.data.scaleY; + switch (pose) { + case MixPose.setup: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case MixPose.current: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; } return; } @@ -305,7 +341,7 @@ var spine; } else { var bx = 0, by = 0; - if (setupPose) { + if (pose == MixPose.setup) { bx = bone.data.scaleX; by = bone.data.scaleY; } @@ -313,7 +349,7 @@ var spine; bx = bone.scaleX; by = bone.scaleY; } - if (mixingOut) { + if (direction == MixDirection.out) { x = Math.abs(x) * spine.MathUtils.signum(bx); y = Math.abs(y) * spine.MathUtils.signum(by); } @@ -331,18 +367,23 @@ var spine; var ShearTimeline = (function (_super) { __extends(ShearTimeline, _super); function ShearTimeline(frameCount) { - _super.call(this, frameCount); + return _super.call(this, frameCount) || this; } ShearTimeline.prototype.getPropertyId = function () { return (TimelineType.shear << 24) + this.boneIndex; }; - ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + ShearTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var frames = this.frames; var bone = skeleton.bones[this.boneIndex]; if (time < frames[0]) { - if (setupPose) { - bone.shearX = bone.data.shearX; - bone.shearY = bone.data.shearY; + switch (pose) { + case MixPose.setup: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case MixPose.current: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; } return; } @@ -360,7 +401,7 @@ var spine; x = x + (frames[frame + ShearTimeline.X] - x) * percent; y = y + (frames[frame + ShearTimeline.Y] - y) * percent; } - if (setupPose) { + if (pose == MixPose.setup) { bone.shearX = bone.data.shearX + x * alpha; bone.shearY = bone.data.shearY + y * alpha; } @@ -375,8 +416,9 @@ var spine; var ColorTimeline = (function (_super) { __extends(ColorTimeline, _super); function ColorTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * ColorTimeline.ENTRIES); + return _this; } ColorTimeline.prototype.getPropertyId = function () { return (TimelineType.color << 24) + this.slotIndex; @@ -389,12 +431,18 @@ var spine; this.frames[frameIndex + ColorTimeline.B] = b; this.frames[frameIndex + ColorTimeline.A] = a; }; - ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + ColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var slot = skeleton.slots[this.slotIndex]; var frames = this.frames; if (time < frames[0]) { - if (setupPose) - slot.color.setFromColor(slot.data.color); + switch (pose) { + case MixPose.setup: + slot.color.setFromColor(slot.data.color); + return; + case MixPose.current: + var color = slot.color, setup = slot.data.color; + color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha); + } return; } var r = 0, g = 0, b = 0, a = 0; @@ -422,24 +470,124 @@ var spine; slot.color.set(r, g, b, a); else { var color = slot.color; - if (setupPose) + if (pose == MixPose.setup) color.setFromColor(slot.data.color); color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); } }; - ColorTimeline.ENTRIES = 5; - ColorTimeline.PREV_TIME = -5; - ColorTimeline.PREV_R = -4; - ColorTimeline.PREV_G = -3; - ColorTimeline.PREV_B = -2; - ColorTimeline.PREV_A = -1; - ColorTimeline.R = 1; - ColorTimeline.G = 2; - ColorTimeline.B = 3; - ColorTimeline.A = 4; return ColorTimeline; }(CurveTimeline)); + ColorTimeline.ENTRIES = 5; + ColorTimeline.PREV_TIME = -5; + ColorTimeline.PREV_R = -4; + ColorTimeline.PREV_G = -3; + ColorTimeline.PREV_B = -2; + ColorTimeline.PREV_A = -1; + ColorTimeline.R = 1; + ColorTimeline.G = 2; + ColorTimeline.B = 3; + ColorTimeline.A = 4; spine.ColorTimeline = ColorTimeline; + var TwoColorTimeline = (function (_super) { + __extends(TwoColorTimeline, _super); + function TwoColorTimeline(frameCount) { + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TwoColorTimeline.ENTRIES); + return _this; + } + TwoColorTimeline.prototype.getPropertyId = function () { + return (TimelineType.twoColor << 24) + this.slotIndex; + }; + TwoColorTimeline.prototype.setFrame = function (frameIndex, time, r, g, b, a, r2, g2, b2) { + frameIndex *= TwoColorTimeline.ENTRIES; + this.frames[frameIndex] = time; + this.frames[frameIndex + TwoColorTimeline.R] = r; + this.frames[frameIndex + TwoColorTimeline.G] = g; + this.frames[frameIndex + TwoColorTimeline.B] = b; + this.frames[frameIndex + TwoColorTimeline.A] = a; + this.frames[frameIndex + TwoColorTimeline.R2] = r2; + this.frames[frameIndex + TwoColorTimeline.G2] = g2; + this.frames[frameIndex + TwoColorTimeline.B2] = b2; + }; + TwoColorTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { + var slot = skeleton.slots[this.slotIndex]; + var frames = this.frames; + if (time < frames[0]) { + switch (pose) { + case MixPose.setup: + slot.color.setFromColor(slot.data.color); + slot.darkColor.setFromColor(slot.data.darkColor); + return; + case MixPose.current: + var light = slot.color, dark = slot.darkColor, setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, (setupLight.a - light.a) * alpha); + dark.add((setupDark.r - dark.r) * alpha, (setupDark.g - dark.g) * alpha, (setupDark.b - dark.b) * alpha, 0); + } + return; + } + var r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + if (time >= frames[frames.length - TwoColorTimeline.ENTRIES]) { + var i = frames.length; + r = frames[i + TwoColorTimeline.PREV_R]; + g = frames[i + TwoColorTimeline.PREV_G]; + b = frames[i + TwoColorTimeline.PREV_B]; + a = frames[i + TwoColorTimeline.PREV_A]; + r2 = frames[i + TwoColorTimeline.PREV_R2]; + g2 = frames[i + TwoColorTimeline.PREV_G2]; + b2 = frames[i + TwoColorTimeline.PREV_B2]; + } + else { + var frame = Animation.binarySearch(frames, time, TwoColorTimeline.ENTRIES); + r = frames[frame + TwoColorTimeline.PREV_R]; + g = frames[frame + TwoColorTimeline.PREV_G]; + b = frames[frame + TwoColorTimeline.PREV_B]; + a = frames[frame + TwoColorTimeline.PREV_A]; + r2 = frames[frame + TwoColorTimeline.PREV_R2]; + g2 = frames[frame + TwoColorTimeline.PREV_G2]; + b2 = frames[frame + TwoColorTimeline.PREV_B2]; + var frameTime = frames[frame]; + var percent = this.getCurvePercent(frame / TwoColorTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + TwoColorTimeline.PREV_TIME] - frameTime)); + r += (frames[frame + TwoColorTimeline.R] - r) * percent; + g += (frames[frame + TwoColorTimeline.G] - g) * percent; + b += (frames[frame + TwoColorTimeline.B] - b) * percent; + a += (frames[frame + TwoColorTimeline.A] - a) * percent; + r2 += (frames[frame + TwoColorTimeline.R2] - r2) * percent; + g2 += (frames[frame + TwoColorTimeline.G2] - g2) * percent; + b2 += (frames[frame + TwoColorTimeline.B2] - b2) * percent; + } + if (alpha == 1) { + slot.color.set(r, g, b, a); + slot.darkColor.set(r2, g2, b2, 1); + } + else { + var light = slot.color, dark = slot.darkColor; + if (pose == MixPose.setup) { + light.setFromColor(slot.data.color); + dark.setFromColor(slot.data.darkColor); + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0); + } + }; + return TwoColorTimeline; + }(CurveTimeline)); + TwoColorTimeline.ENTRIES = 8; + TwoColorTimeline.PREV_TIME = -8; + TwoColorTimeline.PREV_R = -7; + TwoColorTimeline.PREV_G = -6; + TwoColorTimeline.PREV_B = -5; + TwoColorTimeline.PREV_A = -4; + TwoColorTimeline.PREV_R2 = -3; + TwoColorTimeline.PREV_G2 = -2; + TwoColorTimeline.PREV_B2 = -1; + TwoColorTimeline.R = 1; + TwoColorTimeline.G = 2; + TwoColorTimeline.B = 3; + TwoColorTimeline.A = 4; + TwoColorTimeline.R2 = 5; + TwoColorTimeline.G2 = 6; + TwoColorTimeline.B2 = 7; + spine.TwoColorTimeline = TwoColorTimeline; var AttachmentTimeline = (function () { function AttachmentTimeline(frameCount) { this.frames = spine.Utils.newFloatArray(frameCount); @@ -455,16 +603,16 @@ var spine; this.frames[frameIndex] = time; this.attachmentNames[frameIndex] = attachmentName; }; - AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, setupPose, mixingOut) { + AttachmentTimeline.prototype.apply = function (skeleton, lastTime, time, events, alpha, pose, direction) { var slot = skeleton.slots[this.slotIndex]; - if (mixingOut && setupPose) { + if (direction == MixDirection.out && pose == MixPose.setup) { var attachmentName_1 = slot.data.attachmentName; slot.setAttachment(attachmentName_1 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_1)); return; } var frames = this.frames; if (time < frames[0]) { - if (setupPose) { + if (pose == MixPose.setup) { var attachmentName_2 = slot.data.attachmentName; slot.setAttachment(attachmentName_2 == null ? null : skeleton.getAttachment(this.slotIndex, attachmentName_2)); } @@ -482,59 +630,87 @@ var spine; return AttachmentTimeline; }()); spine.AttachmentTimeline = AttachmentTimeline; + var zeros = null; var DeformTimeline = (function (_super) { __extends(DeformTimeline, _super); function DeformTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount); - this.frameVertices = new Array(frameCount); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount); + _this.frameVertices = new Array(frameCount); + if (zeros == null) + zeros = spine.Utils.newFloatArray(64); + return _this; } DeformTimeline.prototype.getPropertyId = function () { - return (TimelineType.deform << 24) + this.slotIndex; + return (TimelineType.deform << 27) + +this.attachment.id + this.slotIndex; }; DeformTimeline.prototype.setFrame = function (frameIndex, time, vertices) { this.frames[frameIndex] = time; this.frameVertices[frameIndex] = vertices; }; - DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + DeformTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var slot = skeleton.slots[this.slotIndex]; var slotAttachment = slot.getAttachment(); if (!(slotAttachment instanceof spine.VertexAttachment) || !slotAttachment.applyDeform(this.attachment)) return; - var frames = this.frames; var verticesArray = slot.attachmentVertices; - if (time < frames[0]) { - if (setupPose) - spine.Utils.setArraySize(verticesArray, 0); - return; - } var frameVertices = this.frameVertices; var vertexCount = frameVertices[0].length; - if (verticesArray.length != vertexCount) - alpha = 1; var vertices = spine.Utils.setArraySize(verticesArray, vertexCount); + var frames = this.frames; + if (time < frames[0]) { + var vertexAttachment = slotAttachment; + switch (pose) { + case MixPose.setup: + var zeroVertices; + if (vertexAttachment.bones == null) { + zeroVertices = vertexAttachment.vertices; + } + else { + zeroVertices = zeros; + if (zeroVertices.length < vertexCount) + zeros = zeroVertices = spine.Utils.newFloatArray(vertexCount); + } + spine.Utils.arrayCopy(zeroVertices, 0, vertices, 0, vertexCount); + return; + case MixPose.current: + if (alpha == 1) + break; + if (vertexAttachment.bones == null) { + var setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + vertices[i] += (setupVertices[i] - vertices[i]) * alpha; + } + else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + vertices[i] *= alpha; + } + } + return; + } if (time >= frames[frames.length - 1]) { var lastVertices = frameVertices[frames.length - 1]; if (alpha == 1) { spine.Utils.arrayCopy(lastVertices, 0, vertices, 0, vertexCount); } - else if (setupPose) { + else if (pose == MixPose.setup) { var vertexAttachment = slotAttachment; if (vertexAttachment.bones == null) { - var setupVertices = vertexAttachment.vertices; - for (var i = 0; i < vertexCount; i++) { - var setup = setupVertices[i]; - vertices[i] = setup + (lastVertices[i] - setup) * alpha; + var setupVertices_1 = vertexAttachment.vertices; + for (var i_1 = 0; i_1 < vertexCount; i_1++) { + var setup = setupVertices_1[i_1]; + vertices[i_1] = setup + (lastVertices[i_1] - setup) * alpha; } } else { - for (var i = 0; i < vertexCount; i++) - vertices[i] = lastVertices[i] * alpha; + for (var i_2 = 0; i_2 < vertexCount; i_2++) + vertices[i_2] = lastVertices[i_2] * alpha; } } else { - for (var i = 0; i < vertexCount; i++) - vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + for (var i_3 = 0; i_3 < vertexCount; i_3++) + vertices[i_3] += (lastVertices[i_3] - vertices[i_3]) * alpha; } return; } @@ -544,31 +720,31 @@ var spine; var frameTime = frames[frame]; var percent = this.getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); if (alpha == 1) { - for (var i = 0; i < vertexCount; i++) { - var prev = prevVertices[i]; - vertices[i] = prev + (nextVertices[i] - prev) * percent; + for (var i_4 = 0; i_4 < vertexCount; i_4++) { + var prev = prevVertices[i_4]; + vertices[i_4] = prev + (nextVertices[i_4] - prev) * percent; } } - else if (setupPose) { + else if (pose == MixPose.setup) { var vertexAttachment = slotAttachment; if (vertexAttachment.bones == null) { - var setupVertices = vertexAttachment.vertices; - for (var i = 0; i < vertexCount; i++) { - var prev = prevVertices[i], setup = setupVertices[i]; - vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + var setupVertices_2 = vertexAttachment.vertices; + for (var i_5 = 0; i_5 < vertexCount; i_5++) { + var prev = prevVertices[i_5], setup = setupVertices_2[i_5]; + vertices[i_5] = setup + (prev + (nextVertices[i_5] - prev) * percent - setup) * alpha; } } else { - for (var i = 0; i < vertexCount; i++) { - var prev = prevVertices[i]; - vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + for (var i_6 = 0; i_6 < vertexCount; i_6++) { + var prev = prevVertices[i_6]; + vertices[i_6] = (prev + (nextVertices[i_6] - prev) * percent) * alpha; } } } else { - for (var i = 0; i < vertexCount; i++) { - var prev = prevVertices[i]; - vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + for (var i_7 = 0; i_7 < vertexCount; i_7++) { + var prev = prevVertices[i_7]; + vertices[i_7] += (prev + (nextVertices[i_7] - prev) * percent - vertices[i_7]) * alpha; } } }; @@ -590,13 +766,13 @@ var spine; this.frames[frameIndex] = event.time; this.events[frameIndex] = event; }; - EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + EventTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { if (firedEvents == null) return; var frames = this.frames; var frameCount = this.frames.length; if (lastTime > time) { - this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, setupPose, mixingOut); + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, pose, direction); lastTime = -1; } else if (lastTime >= frames[frameCount - 1]) @@ -636,16 +812,16 @@ var spine; this.frames[frameIndex] = time; this.drawOrders[frameIndex] = drawOrder; }; - DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + DrawOrderTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var drawOrder = skeleton.drawOrder; var slots = skeleton.slots; - if (mixingOut && setupPose) { + if (direction == MixDirection.out && pose == MixPose.setup) { spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); return; } var frames = this.frames; if (time < frames[0]) { - if (setupPose) + if (pose == MixPose.setup) spine.Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); return; } @@ -668,8 +844,9 @@ var spine; var IkConstraintTimeline = (function (_super) { __extends(IkConstraintTimeline, _super); function IkConstraintTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * IkConstraintTimeline.ENTRIES); + return _this; } IkConstraintTimeline.prototype.getPropertyId = function () { return (TimelineType.ikConstraint << 24) + this.ikConstraintIndex; @@ -680,25 +857,30 @@ var spine; this.frames[frameIndex + IkConstraintTimeline.MIX] = mix; this.frames[frameIndex + IkConstraintTimeline.BEND_DIRECTION] = bendDirection; }; - IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + IkConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.ikConstraints[this.ikConstraintIndex]; if (time < frames[0]) { - if (setupPose) { - constraint.mix = constraint.data.mix; - constraint.bendDirection = constraint.data.bendDirection; + switch (pose) { + case MixPose.setup: + constraint.mix = constraint.data.mix; + constraint.bendDirection = constraint.data.bendDirection; + return; + case MixPose.current: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.bendDirection = constraint.data.bendDirection; } return; } if (time >= frames[frames.length - IkConstraintTimeline.ENTRIES]) { - if (setupPose) { + if (pose == MixPose.setup) { constraint.mix = constraint.data.mix + (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.data.mix) * alpha; - constraint.bendDirection = mixingOut ? constraint.data.bendDirection + constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection : frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; } else { constraint.mix += (frames[frames.length + IkConstraintTimeline.PREV_MIX] - constraint.mix) * alpha; - if (!mixingOut) + if (direction == MixDirection["in"]) constraint.bendDirection = frames[frames.length + IkConstraintTimeline.PREV_BEND_DIRECTION]; } return; @@ -707,30 +889,31 @@ var spine; var mix = frames[frame + IkConstraintTimeline.PREV_MIX]; var frameTime = frames[frame]; var percent = this.getCurvePercent(frame / IkConstraintTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + IkConstraintTimeline.PREV_TIME] - frameTime)); - if (setupPose) { + if (pose == MixPose.setup) { constraint.mix = constraint.data.mix + (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.data.mix) * alpha; - constraint.bendDirection = mixingOut ? constraint.data.bendDirection : frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; + constraint.bendDirection = direction == MixDirection.out ? constraint.data.bendDirection : frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; } else { constraint.mix += (mix + (frames[frame + IkConstraintTimeline.MIX] - mix) * percent - constraint.mix) * alpha; - if (!mixingOut) + if (direction == MixDirection["in"]) constraint.bendDirection = frames[frame + IkConstraintTimeline.PREV_BEND_DIRECTION]; } }; - IkConstraintTimeline.ENTRIES = 3; - IkConstraintTimeline.PREV_TIME = -3; - IkConstraintTimeline.PREV_MIX = -2; - IkConstraintTimeline.PREV_BEND_DIRECTION = -1; - IkConstraintTimeline.MIX = 1; - IkConstraintTimeline.BEND_DIRECTION = 2; return IkConstraintTimeline; }(CurveTimeline)); + IkConstraintTimeline.ENTRIES = 3; + IkConstraintTimeline.PREV_TIME = -3; + IkConstraintTimeline.PREV_MIX = -2; + IkConstraintTimeline.PREV_BEND_DIRECTION = -1; + IkConstraintTimeline.MIX = 1; + IkConstraintTimeline.BEND_DIRECTION = 2; spine.IkConstraintTimeline = IkConstraintTimeline; var TransformConstraintTimeline = (function (_super) { __extends(TransformConstraintTimeline, _super); function TransformConstraintTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * TransformConstraintTimeline.ENTRIES); + return _this; } TransformConstraintTimeline.prototype.getPropertyId = function () { return (TimelineType.transformConstraint << 24) + this.transformConstraintIndex; @@ -743,16 +926,23 @@ var spine; this.frames[frameIndex + TransformConstraintTimeline.SCALE] = scaleMix; this.frames[frameIndex + TransformConstraintTimeline.SHEAR] = shearMix; }; - TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + TransformConstraintTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.transformConstraints[this.transformConstraintIndex]; if (time < frames[0]) { - if (setupPose) { - var data = constraint.data; - constraint.rotateMix = data.rotateMix; - constraint.translateMix = data.rotateMix; - constraint.scaleMix = data.scaleMix; - constraint.shearMix = data.shearMix; + var data = constraint.data; + switch (pose) { + case MixPose.setup: + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + return; + case MixPose.current: + constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; + constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; + constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; } return; } @@ -777,7 +967,7 @@ var spine; scale += (frames[frame + TransformConstraintTimeline.SCALE] - scale) * percent; shear += (frames[frame + TransformConstraintTimeline.SHEAR] - shear) * percent; } - if (setupPose) { + if (pose == MixPose.setup) { var data = constraint.data; constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; @@ -791,24 +981,25 @@ var spine; constraint.shearMix += (shear - constraint.shearMix) * alpha; } }; - TransformConstraintTimeline.ENTRIES = 5; - TransformConstraintTimeline.PREV_TIME = -5; - TransformConstraintTimeline.PREV_ROTATE = -4; - TransformConstraintTimeline.PREV_TRANSLATE = -3; - TransformConstraintTimeline.PREV_SCALE = -2; - TransformConstraintTimeline.PREV_SHEAR = -1; - TransformConstraintTimeline.ROTATE = 1; - TransformConstraintTimeline.TRANSLATE = 2; - TransformConstraintTimeline.SCALE = 3; - TransformConstraintTimeline.SHEAR = 4; return TransformConstraintTimeline; }(CurveTimeline)); + TransformConstraintTimeline.ENTRIES = 5; + TransformConstraintTimeline.PREV_TIME = -5; + TransformConstraintTimeline.PREV_ROTATE = -4; + TransformConstraintTimeline.PREV_TRANSLATE = -3; + TransformConstraintTimeline.PREV_SCALE = -2; + TransformConstraintTimeline.PREV_SHEAR = -1; + TransformConstraintTimeline.ROTATE = 1; + TransformConstraintTimeline.TRANSLATE = 2; + TransformConstraintTimeline.SCALE = 3; + TransformConstraintTimeline.SHEAR = 4; spine.TransformConstraintTimeline = TransformConstraintTimeline; var PathConstraintPositionTimeline = (function (_super) { __extends(PathConstraintPositionTimeline, _super); function PathConstraintPositionTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintPositionTimeline.ENTRIES); + return _this; } PathConstraintPositionTimeline.prototype.getPropertyId = function () { return (TimelineType.pathConstraintPosition << 24) + this.pathConstraintIndex; @@ -818,12 +1009,17 @@ var spine; this.frames[frameIndex] = time; this.frames[frameIndex + PathConstraintPositionTimeline.VALUE] = value; }; - PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + PathConstraintPositionTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; if (time < frames[0]) { - if (setupPose) - constraint.position = constraint.data.position; + switch (pose) { + case MixPose.setup: + constraint.position = constraint.data.position; + return; + case MixPose.current: + constraint.position += (constraint.data.position - constraint.position) * alpha; + } return; } var position = 0; @@ -836,32 +1032,37 @@ var spine; var percent = this.getCurvePercent(frame / PathConstraintPositionTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintPositionTimeline.PREV_TIME] - frameTime)); position += (frames[frame + PathConstraintPositionTimeline.VALUE] - position) * percent; } - if (setupPose) + if (pose == MixPose.setup) constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; else constraint.position += (position - constraint.position) * alpha; }; - PathConstraintPositionTimeline.ENTRIES = 2; - PathConstraintPositionTimeline.PREV_TIME = -2; - PathConstraintPositionTimeline.PREV_VALUE = -1; - PathConstraintPositionTimeline.VALUE = 1; return PathConstraintPositionTimeline; }(CurveTimeline)); + PathConstraintPositionTimeline.ENTRIES = 2; + PathConstraintPositionTimeline.PREV_TIME = -2; + PathConstraintPositionTimeline.PREV_VALUE = -1; + PathConstraintPositionTimeline.VALUE = 1; spine.PathConstraintPositionTimeline = PathConstraintPositionTimeline; var PathConstraintSpacingTimeline = (function (_super) { __extends(PathConstraintSpacingTimeline, _super); function PathConstraintSpacingTimeline(frameCount) { - _super.call(this, frameCount); + return _super.call(this, frameCount) || this; } PathConstraintSpacingTimeline.prototype.getPropertyId = function () { return (TimelineType.pathConstraintSpacing << 24) + this.pathConstraintIndex; }; - PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + PathConstraintSpacingTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; if (time < frames[0]) { - if (setupPose) - constraint.spacing = constraint.data.spacing; + switch (pose) { + case MixPose.setup: + constraint.spacing = constraint.data.spacing; + return; + case MixPose.current: + constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; + } return; } var spacing = 0; @@ -874,7 +1075,7 @@ var spine; var percent = this.getCurvePercent(frame / PathConstraintSpacingTimeline.ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PathConstraintSpacingTimeline.PREV_TIME] - frameTime)); spacing += (frames[frame + PathConstraintSpacingTimeline.VALUE] - spacing) * percent; } - if (setupPose) + if (pose == MixPose.setup) constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; else constraint.spacing += (spacing - constraint.spacing) * alpha; @@ -885,8 +1086,9 @@ var spine; var PathConstraintMixTimeline = (function (_super) { __extends(PathConstraintMixTimeline, _super); function PathConstraintMixTimeline(frameCount) { - _super.call(this, frameCount); - this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + var _this = _super.call(this, frameCount) || this; + _this.frames = spine.Utils.newFloatArray(frameCount * PathConstraintMixTimeline.ENTRIES); + return _this; } PathConstraintMixTimeline.prototype.getPropertyId = function () { return (TimelineType.pathConstraintMix << 24) + this.pathConstraintIndex; @@ -897,13 +1099,18 @@ var spine; this.frames[frameIndex + PathConstraintMixTimeline.ROTATE] = rotateMix; this.frames[frameIndex + PathConstraintMixTimeline.TRANSLATE] = translateMix; }; - PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, setupPose, mixingOut) { + PathConstraintMixTimeline.prototype.apply = function (skeleton, lastTime, time, firedEvents, alpha, pose, direction) { var frames = this.frames; var constraint = skeleton.pathConstraints[this.pathConstraintIndex]; if (time < frames[0]) { - if (setupPose) { - constraint.rotateMix = constraint.data.rotateMix; - constraint.translateMix = constraint.data.translateMix; + switch (pose) { + case MixPose.setup: + constraint.rotateMix = constraint.data.rotateMix; + constraint.translateMix = constraint.data.translateMix; + return; + case MixPose.current: + constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; } return; } @@ -921,7 +1128,7 @@ var spine; rotate += (frames[frame + PathConstraintMixTimeline.ROTATE] - rotate) * percent; translate += (frames[frame + PathConstraintMixTimeline.TRANSLATE] - translate) * percent; } - if (setupPose) { + if (pose == MixPose.setup) { constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; } @@ -930,14 +1137,14 @@ var spine; constraint.translateMix += (translate - constraint.translateMix) * alpha; } }; - PathConstraintMixTimeline.ENTRIES = 3; - PathConstraintMixTimeline.PREV_TIME = -3; - PathConstraintMixTimeline.PREV_ROTATE = -2; - PathConstraintMixTimeline.PREV_TRANSLATE = -1; - PathConstraintMixTimeline.ROTATE = 1; - PathConstraintMixTimeline.TRANSLATE = 2; return PathConstraintMixTimeline; }(CurveTimeline)); + PathConstraintMixTimeline.ENTRIES = 3; + PathConstraintMixTimeline.PREV_TIME = -3; + PathConstraintMixTimeline.PREV_ROTATE = -2; + PathConstraintMixTimeline.PREV_TRANSLATE = -1; + PathConstraintMixTimeline.ROTATE = 1; + PathConstraintMixTimeline.TRANSLATE = 2; spine.PathConstraintMixTimeline = PathConstraintMixTimeline; })(spine || (spine = {})); var spine; @@ -949,6 +1156,7 @@ var spine; this.listeners = new Array(); this.queue = new EventQueue(this); this.propertyIDs = new spine.IntSet(); + this.mixingTo = new Array(); this.animationsChanged = false; this.timeScale = 1; this.trackEntryPool = new spine.Pool(function () { return new TrackEntry(); }); @@ -986,33 +1194,42 @@ var spine; continue; } } - else { - if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { - tracks[i] = null; - this.queue.end(current); - this.disposeNext(current); - continue; + else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { + tracks[i] = null; + this.queue.end(current); + this.disposeNext(current); + continue; + } + if (current.mixingFrom != null && this.updateMixingFrom(current, delta)) { + var from = current.mixingFrom; + current.mixingFrom = null; + while (from != null) { + this.queue.end(from); + from = from.mixingFrom; } } - this.updateMixingFrom(current, delta); current.trackTime += currentDelta; } this.queue.drain(); }; - AnimationState.prototype.updateMixingFrom = function (entry, delta) { - var from = entry.mixingFrom; + AnimationState.prototype.updateMixingFrom = function (to, delta) { + var from = to.mixingFrom; if (from == null) - return; - this.updateMixingFrom(from, delta); - if (entry.mixTime >= entry.mixDuration && from.mixingFrom != null && entry.mixTime > 0) { - entry.mixingFrom = null; - this.queue.end(from); - return; + return true; + var finished = this.updateMixingFrom(from, delta); + if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; } from.animationLast = from.nextAnimationLast; from.trackLast = from.nextTrackLast; from.trackTime += delta * from.timeScale; - entry.mixTime += delta * from.timeScale; + to.mixTime += delta * to.timeScale; + return false; }; AnimationState.prototype.apply = function (skeleton) { if (skeleton == null) @@ -1021,35 +1238,39 @@ var spine; this._animationsChanged(); var events = this.events; var tracks = this.tracks; + var applied = false; for (var i = 0, n = tracks.length; i < n; i++) { var current = tracks[i]; if (current == null || current.delay > 0) continue; + applied = true; + var currentPose = i == 0 ? spine.MixPose.current : spine.MixPose.currentLayered; var mix = current.alpha; if (current.mixingFrom != null) - mix *= this.applyMixingFrom(current, skeleton); - else if (current.trackTime >= current.trackEnd) + mix *= this.applyMixingFrom(current, skeleton, currentPose); + else if (current.trackTime >= current.trackEnd && current.next == null) mix = 0; var animationLast = current.animationLast, animationTime = current.getAnimationTime(); var timelineCount = current.animation.timelines.length; var timelines = current.animation.timelines; if (mix == 1) { for (var ii = 0; ii < timelineCount; ii++) - timelines[ii].apply(skeleton, animationLast, animationTime, events, 1, true, false); + timelines[ii].apply(skeleton, animationLast, animationTime, events, 1, spine.MixPose.setup, spine.MixDirection["in"]); } else { + var timelineData = current.timelineData; var firstFrame = current.timelinesRotation.length == 0; if (firstFrame) spine.Utils.setArraySize(current.timelinesRotation, timelineCount << 1, null); var timelinesRotation = current.timelinesRotation; - var timelinesFirst = current.timelinesFirst; for (var ii = 0; ii < timelineCount; ii++) { var timeline = timelines[ii]; + var pose = timelineData[ii] >= AnimationState.FIRST ? spine.MixPose.setup : currentPose; if (timeline instanceof spine.RotateTimeline) { - this.applyRotateTimeline(timeline, skeleton, animationTime, mix, timelinesFirst[ii], timelinesRotation, ii << 1, firstFrame); + this.applyRotateTimeline(timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); } else - timeline.apply(skeleton, animationLast, animationTime, events, mix, timelinesFirst[ii], false); + timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, spine.MixDirection["in"]); } } this.queueEvents(current, animationTime); @@ -1058,16 +1279,17 @@ var spine; current.nextTrackLast = current.trackTime; } this.queue.drain(); + return applied; }; - AnimationState.prototype.applyMixingFrom = function (entry, skeleton) { - var from = entry.mixingFrom; + AnimationState.prototype.applyMixingFrom = function (to, skeleton, currentPose) { + var from = to.mixingFrom; if (from.mixingFrom != null) - this.applyMixingFrom(from, skeleton); + this.applyMixingFrom(from, skeleton, currentPose); var mix = 0; - if (entry.mixDuration == 0) + if (to.mixDuration == 0) mix = 1; else { - mix = entry.mixTime / entry.mixDuration; + mix = to.mixTime / to.mixDuration; if (mix > 1) mix = 1; } @@ -1076,46 +1298,67 @@ var spine; var animationLast = from.animationLast, animationTime = from.getAnimationTime(); var timelineCount = from.animation.timelines.length; var timelines = from.animation.timelines; - var timelinesFirst = from.timelinesFirst; - var alpha = from.alpha * entry.mixAlpha * (1 - mix); + var timelineData = from.timelineData; + var timelineDipMix = from.timelineDipMix; var firstFrame = from.timelinesRotation.length == 0; if (firstFrame) spine.Utils.setArraySize(from.timelinesRotation, timelineCount << 1, null); var timelinesRotation = from.timelinesRotation; + var pose; + var alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha = 0; + from.totalAlpha = 0; for (var i = 0; i < timelineCount; i++) { var timeline = timelines[i]; - var setupPose = timelinesFirst[i]; - if (timeline instanceof spine.RotateTimeline) - this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, setupPose, timelinesRotation, i << 1, firstFrame); - else { - if (!setupPose) { + switch (timelineData[i]) { + case AnimationState.SUBSEQUENT: if (!attachments && timeline instanceof spine.AttachmentTimeline) continue; if (!drawOrder && timeline instanceof spine.DrawOrderTimeline) continue; - } - timeline.apply(skeleton, animationLast, animationTime, events, alpha, setupPose, true); + pose = currentPose; + alpha = alphaMix; + break; + case AnimationState.FIRST: + pose = spine.MixPose.setup; + alpha = alphaMix; + break; + case AnimationState.DIP: + pose = spine.MixPose.setup; + alpha = alphaDip; + break; + default: + pose = spine.MixPose.setup; + alpha = alphaDip; + var dipMix = timelineDipMix[i]; + alpha *= Math.max(0, 1 - dipMix.mixTime / dipMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (timeline instanceof spine.RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); + else { + timeline.apply(skeleton, animationLast, animationTime, events, alpha, pose, spine.MixDirection.out); } } - if (entry.mixDuration > 0) + if (to.mixDuration > 0) this.queueEvents(from, animationTime); this.events.length = 0; from.nextAnimationLast = animationTime; from.nextTrackLast = from.trackTime; return mix; }; - AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, setupPose, timelinesRotation, i, firstFrame) { + AnimationState.prototype.applyRotateTimeline = function (timeline, skeleton, time, alpha, pose, timelinesRotation, i, firstFrame) { if (firstFrame) timelinesRotation[i] = 0; if (alpha == 1) { - timeline.apply(skeleton, 0, time, null, 1, setupPose, false); + timeline.apply(skeleton, 0, time, null, 1, pose, spine.MixDirection["in"]); return; } var rotateTimeline = timeline; var frames = rotateTimeline.frames; var bone = skeleton.bones[rotateTimeline.boneIndex]; if (time < frames[0]) { - if (setupPose) + if (pose == spine.MixPose.setup) bone.rotation = bone.data.rotation; return; } @@ -1132,7 +1375,7 @@ var spine; r2 = prevRotation + r2 * percent + bone.data.rotation; r2 -= (16384 - ((16384.499999999996 - r2 / 360) | 0)) * 360; } - var r1 = setupPose ? bone.data.rotation : bone.rotation; + var r1 = pose == spine.MixPose.setup ? bone.data.rotation : bone.rotation; var total = 0, diff = r2 - r1; if (diff == 0) { total = timelinesRotation[i]; @@ -1189,11 +1432,12 @@ var spine; } }; AnimationState.prototype.clearTracks = function () { + var oldDrainDisabled = this.queue.drainDisabled; this.queue.drainDisabled = true; for (var i = 0, n = this.tracks.length; i < n; i++) this.clearTrack(i); this.tracks.length = 0; - this.queue.drainDisabled = false; + this.queue.drainDisabled = oldDrainDisabled; this.queue.drain(); }; AnimationState.prototype.clearTrack = function (trackIndex) { @@ -1224,9 +1468,9 @@ var spine; this.queue.interrupt(from); current.mixingFrom = from; current.mixTime = 0; - from.timelinesRotation.length = 0; if (from.mixingFrom != null && from.mixDuration > 0) - current.mixAlpha *= Math.min(from.mixTime / from.mixDuration, 1); + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; } this.queue.start(current); }; @@ -1305,13 +1549,14 @@ var spine; return entry; }; AnimationState.prototype.setEmptyAnimations = function (mixDuration) { + var oldDrainDisabled = this.queue.drainDisabled; this.queue.drainDisabled = true; for (var i = 0, n = this.tracks.length; i < n; i++) { var current = this.tracks[i]; if (current != null) this.setEmptyAnimation(current.trackIndex, mixDuration); } - this.queue.drainDisabled = false; + this.queue.drainDisabled = oldDrainDisabled; this.queue.drain(); }; AnimationState.prototype.expandToIndex = function (index) { @@ -1340,7 +1585,7 @@ var spine; entry.trackEnd = Number.MAX_VALUE; entry.timeScale = 1; entry.alpha = 1; - entry.mixAlpha = 1; + entry.interruptAlpha = 1; entry.mixTime = 0; entry.mixDuration = last == null ? 0 : this.data.getMix(last.animation, animation); return entry; @@ -1356,50 +1601,14 @@ var spine; AnimationState.prototype._animationsChanged = function () { this.animationsChanged = false; var propertyIDs = this.propertyIDs; - var i = 0, n = this.tracks.length; propertyIDs.clear(); - for (; i < n; i++) { - var entry = this.tracks[i]; - if (entry == null) - continue; - this.setTimelinesFirst(entry); - i++; - break; - } - for (; i < n; i++) { + var mixingTo = this.mixingTo; + for (var i = 0, n = this.tracks.length; i < n; i++) { var entry = this.tracks[i]; if (entry != null) - this.checkTimelinesFirst(entry); - } - }; - AnimationState.prototype.setTimelinesFirst = function (entry) { - if (entry.mixingFrom != null) { - this.setTimelinesFirst(entry.mixingFrom); - this.checkTimelinesUsage(entry, entry.timelinesFirst); - return; - } - var propertyIDs = this.propertyIDs; - var timelines = entry.animation.timelines; - var n = timelines.length; - var usage = spine.Utils.setArraySize(entry.timelinesFirst, n, false); - for (var i = 0; i < n; i++) { - propertyIDs.add(timelines[i].getPropertyId()); - usage[i] = true; + entry.setTimelineData(null, mixingTo, propertyIDs); } }; - AnimationState.prototype.checkTimelinesFirst = function (entry) { - if (entry.mixingFrom != null) - this.checkTimelinesFirst(entry.mixingFrom); - this.checkTimelinesUsage(entry, entry.timelinesFirst); - }; - AnimationState.prototype.checkTimelinesUsage = function (entry, usageArray) { - var propertyIDs = this.propertyIDs; - var timelines = entry.animation.timelines; - var n = timelines.length; - var usage = spine.Utils.setArraySize(usageArray, n); - for (var i = 0; i < n; i++) - usage[i] = propertyIDs.add(timelines[i].getPropertyId()); - }; AnimationState.prototype.getCurrent = function (trackIndex) { if (trackIndex >= this.tracks.length) return null; @@ -1421,13 +1630,18 @@ var spine; AnimationState.prototype.clearListenerNotifications = function () { this.queue.clear(); }; - AnimationState.emptyAnimation = new spine.Animation("", [], 0); return AnimationState; }()); + AnimationState.emptyAnimation = new spine.Animation("", [], 0); + AnimationState.SUBSEQUENT = 0; + AnimationState.FIRST = 1; + AnimationState.DIP = 2; + AnimationState.DIP_MIX = 3; spine.AnimationState = AnimationState; var TrackEntry = (function () { function TrackEntry() { - this.timelinesFirst = new Array(); + this.timelineData = new Array(); + this.timelineDipMix = new Array(); this.timelinesRotation = new Array(); } TrackEntry.prototype.reset = function () { @@ -1435,9 +1649,52 @@ var spine; this.mixingFrom = null; this.animation = null; this.listener = null; - this.timelinesFirst.length = 0; + this.timelineData.length = 0; + this.timelineDipMix.length = 0; this.timelinesRotation.length = 0; }; + TrackEntry.prototype.setTimelineData = function (to, mixingToArray, propertyIDs) { + if (to != null) + mixingToArray.push(to); + var lastEntry = this.mixingFrom != null ? this.mixingFrom.setTimelineData(this, mixingToArray, propertyIDs) : this; + if (to != null) + mixingToArray.pop(); + var mixingTo = mixingToArray; + var mixingToLast = mixingToArray.length - 1; + var timelines = this.animation.timelines; + var timelinesCount = this.animation.timelines.length; + var timelineData = spine.Utils.setArraySize(this.timelineData, timelinesCount); + this.timelineDipMix.length = 0; + var timelineDipMix = spine.Utils.setArraySize(this.timelineDipMix, timelinesCount); + outer: for (var i = 0; i < timelinesCount; i++) { + var id = timelines[i].getPropertyId(); + if (!propertyIDs.add(id)) + timelineData[i] = AnimationState.SUBSEQUENT; + else if (to == null || !to.hasTimeline(id)) + timelineData[i] = AnimationState.FIRST; + else { + for (var ii = mixingToLast; ii >= 0; ii--) { + var entry = mixingTo[ii]; + if (!entry.hasTimeline(id)) { + if (entry.mixDuration > 0) { + timelineData[i] = AnimationState.DIP_MIX; + timelineDipMix[i] = entry; + continue outer; + } + } + } + timelineData[i] = AnimationState.DIP; + } + } + return lastEntry; + }; + TrackEntry.prototype.hasTimeline = function (id) { + var timelines = this.animation.timelines; + for (var i = 0, n = timelines.length; i < n; i++) + if (timelines[i].getPropertyId() == id) + return true; + return false; + }; TrackEntry.prototype.getAnimationTime = function () { if (this.loop) { var duration = this.animationEnd - this.animationStart; @@ -1557,6 +1814,7 @@ var spine; return EventQueue; }()); spine.EventQueue = EventQueue; + var EventType; (function (EventType) { EventType[EventType["start"] = 0] = "start"; EventType[EventType["interrupt"] = 1] = "interrupt"; @@ -1564,8 +1822,7 @@ var spine; EventType[EventType["dispose"] = 3] = "dispose"; EventType[EventType["complete"] = 4] = "complete"; EventType[EventType["event"] = 5] = "event"; - })(spine.EventType || (spine.EventType = {})); - var EventType = spine.EventType; + })(EventType = spine.EventType || (spine.EventType = {})); var AnimationStateAdapter2 = (function () { function AnimationStateAdapter2() { } @@ -1667,7 +1924,30 @@ var spine; this.toLoad++; var img = new Image(); img.crossOrigin = "anonymous"; + img.onload = function (ev) { + var texture = _this.textureLoader(img); + _this.assets[path] = texture; + _this.toLoad--; + _this.loaded++; + if (success) + success(path, img); + }; + img.onerror = function (ev) { + _this.errors[path] = "Couldn't load image " + path; + _this.toLoad--; + _this.loaded++; + if (error) + error(path, "Couldn't load image " + path); + }; img.src = path; + }; + AssetManager.prototype.loadTextureData = function (path, data, success, error) { + var _this = this; + if (success === void 0) { success = null; } + if (error === void 0) { error = null; } + path = this.pathPrefix + path; + this.toLoad++; + var img = new Image(); img.onload = function (ev) { var texture = _this.textureLoader(img); _this.assets[path] = texture; @@ -1683,6 +1963,7 @@ var spine; if (error) error(path, "Couldn't load image " + path); }; + img.src = data; }; AssetManager.prototype.get = function (path) { path = this.pathPrefix + path; @@ -1755,511 +2036,102 @@ var spine; AtlasAttachmentLoader.prototype.newPathAttachment = function (skin, name) { return new spine.PathAttachment(name); }; + AtlasAttachmentLoader.prototype.newPointAttachment = function (skin, name) { + return new spine.PointAttachment(name); + }; + AtlasAttachmentLoader.prototype.newClippingAttachment = function (skin, name) { + return new spine.ClippingAttachment(name); + }; return AtlasAttachmentLoader; }()); spine.AtlasAttachmentLoader = AtlasAttachmentLoader; })(spine || (spine = {})); var spine; (function (spine) { - var Attachment = (function () { - function Attachment(name) { - if (name == null) - throw new Error("name cannot be null."); - this.name = name; - } - return Attachment; - }()); - spine.Attachment = Attachment; - var VertexAttachment = (function (_super) { - __extends(VertexAttachment, _super); - function VertexAttachment(name) { - _super.call(this, name); - this.worldVerticesLength = 0; + var BlendMode; + (function (BlendMode) { + BlendMode[BlendMode["Normal"] = 0] = "Normal"; + BlendMode[BlendMode["Additive"] = 1] = "Additive"; + BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; + BlendMode[BlendMode["Screen"] = 3] = "Screen"; + })(BlendMode = spine.BlendMode || (spine.BlendMode = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var Bone = (function () { + function Bone(data, skeleton, parent) { + this.children = new Array(); + this.x = 0; + this.y = 0; + this.rotation = 0; + this.scaleX = 0; + this.scaleY = 0; + this.shearX = 0; + this.shearY = 0; + this.ax = 0; + this.ay = 0; + this.arotation = 0; + this.ascaleX = 0; + this.ascaleY = 0; + this.ashearX = 0; + this.ashearY = 0; + this.appliedValid = false; + this.a = 0; + this.b = 0; + this.worldX = 0; + this.c = 0; + this.d = 0; + this.worldY = 0; + this.sorted = false; + if (data == null) + throw new Error("data cannot be null."); + if (skeleton == null) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); } - VertexAttachment.prototype.computeWorldVertices = function (slot, worldVertices) { - this.computeWorldVerticesWith(slot, 0, this.worldVerticesLength, worldVertices, 0); + Bone.prototype.update = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); }; - VertexAttachment.prototype.computeWorldVerticesWith = function (slot, start, count, worldVertices, offset) { - count += offset; - var skeleton = slot.bone.skeleton; - var deformArray = slot.attachmentVertices; - var vertices = this.vertices; - var bones = this.bones; - if (bones == null) { - if (deformArray.length > 0) - vertices = deformArray; - var bone = slot.bone; - var x = bone.worldX; - var y = bone.worldY; - var a = bone.a, b = bone.b, c = bone.c, d = bone.d; - for (var v_1 = start, w = offset; w < count; v_1 += 2, w += 2) { - var vx = vertices[v_1], vy = vertices[v_1 + 1]; - worldVertices[w] = vx * a + vy * b + x; - worldVertices[w + 1] = vx * c + vy * d + y; + Bone.prototype.updateWorldTransform = function () { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + }; + Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + this.appliedValid = true; + var parent = this.parent; + if (parent == null) { + var rotationY = rotation + 90 + shearY; + var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; + var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; + var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; + var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; + var skeleton = this.skeleton; + if (skeleton.flipX) { + x = -x; + la = -la; + lb = -lb; } - return; - } - var v = 0, skip = 0; - for (var i = 0; i < start; i += 2) { - var n = bones[v]; - v += n + 1; - skip += n; - } - var skeletonBones = skeleton.bones; - if (deformArray.length == 0) { - for (var w = offset, b = skip * 3; w < count; w += 2) { - var wx = 0, wy = 0; - var n = bones[v++]; - n += v; - for (; v < n; v++, b += 3) { - var bone = skeletonBones[bones[v]]; - var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; - wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; - } - worldVertices[w] = wx; - worldVertices[w + 1] = wy; + if (skeleton.flipY) { + y = -y; + lc = -lc; + ld = -ld; } - } - else { - var deform = deformArray; - for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) { - var wx = 0, wy = 0; - var n = bones[v++]; - n += v; - for (; v < n; v++, b += 3, f += 2) { - var bone = skeletonBones[bones[v]]; - var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; - wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; - } - worldVertices[w] = wx; - worldVertices[w + 1] = wy; - } - } - }; - VertexAttachment.prototype.applyDeform = function (sourceAttachment) { - return this == sourceAttachment; - }; - return VertexAttachment; - }(Attachment)); - spine.VertexAttachment = VertexAttachment; -})(spine || (spine = {})); -var spine; -(function (spine) { - (function (AttachmentType) { - AttachmentType[AttachmentType["Region"] = 0] = "Region"; - AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; - AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; - AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; - AttachmentType[AttachmentType["Path"] = 4] = "Path"; - })(spine.AttachmentType || (spine.AttachmentType = {})); - var AttachmentType = spine.AttachmentType; -})(spine || (spine = {})); -var spine; -(function (spine) { - var BoundingBoxAttachment = (function (_super) { - __extends(BoundingBoxAttachment, _super); - function BoundingBoxAttachment(name) { - _super.call(this, name); - this.color = new spine.Color(1, 1, 1, 1); - } - return BoundingBoxAttachment; - }(spine.VertexAttachment)); - spine.BoundingBoxAttachment = BoundingBoxAttachment; -})(spine || (spine = {})); -var spine; -(function (spine) { - var MeshAttachment = (function (_super) { - __extends(MeshAttachment, _super); - function MeshAttachment(name) { - _super.call(this, name); - this.color = new spine.Color(1, 1, 1, 1); - this.inheritDeform = false; - this.tempColor = new spine.Color(0, 0, 0, 0); - } - MeshAttachment.prototype.updateUVs = function () { - var regionUVs = this.regionUVs; - var verticesLength = regionUVs.length; - var worldVerticesLength = (verticesLength >> 1) * 8; - if (this.worldVertices == null || this.worldVertices.length != worldVerticesLength) - this.worldVertices = spine.Utils.newFloatArray(worldVerticesLength); - var u = 0, v = 0, width = 0, height = 0; - if (this.region == null) { - u = v = 0; - width = height = 1; - } - else { - u = this.region.u; - v = this.region.v; - width = this.region.u2 - u; - height = this.region.v2 - v; - } - if (this.region.rotate) { - for (var i = 0, w = 6; i < verticesLength; i += 2, w += 8) { - this.worldVertices[w] = u + regionUVs[i + 1] * width; - this.worldVertices[w + 1] = v + height - regionUVs[i] * height; - } - } - else { - for (var i = 0, w = 6; i < verticesLength; i += 2, w += 8) { - this.worldVertices[w] = u + regionUVs[i] * width; - this.worldVertices[w + 1] = v + regionUVs[i + 1] * height; - } - } - }; - MeshAttachment.prototype.updateWorldVertices = function (slot, premultipliedAlpha) { - var skeleton = slot.bone.skeleton; - var skeletonColor = skeleton.color, slotColor = slot.color, meshColor = this.color; - var alpha = skeletonColor.a * slotColor.a * meshColor.a; - var multiplier = premultipliedAlpha ? alpha : 1; - var color = this.tempColor; - color.set(skeletonColor.r * slotColor.r * meshColor.r * multiplier, skeletonColor.g * slotColor.g * meshColor.g * multiplier, skeletonColor.b * slotColor.b * meshColor.b * multiplier, alpha); - var deformArray = slot.attachmentVertices; - var vertices = this.vertices, worldVertices = this.worldVertices; - var bones = this.bones; - if (bones == null) { - var verticesLength = vertices.length; - if (deformArray.length > 0) - vertices = deformArray; - var bone = slot.bone; - var x = bone.worldX; - var y = bone.worldY; - var a = bone.a, b = bone.b, c = bone.c, d = bone.d; - for (var v = 0, w = 0; v < verticesLength; v += 2, w += 8) { - var vx = vertices[v], vy = vertices[v + 1]; - worldVertices[w] = vx * a + vy * b + x; - worldVertices[w + 1] = vx * c + vy * d + y; - worldVertices[w + 2] = color.r; - worldVertices[w + 3] = color.g; - worldVertices[w + 4] = color.b; - worldVertices[w + 5] = color.a; - } - return worldVertices; - } - var skeletonBones = skeleton.bones; - if (deformArray.length == 0) { - for (var w = 0, v = 0, b = 0, n = bones.length; v < n; w += 8) { - var wx = 0, wy = 0; - var nn = bones[v++] + v; - for (; v < nn; v++, b += 3) { - var bone = skeletonBones[bones[v]]; - var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; - wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; - } - worldVertices[w] = wx; - worldVertices[w + 1] = wy; - worldVertices[w + 2] = color.r; - worldVertices[w + 3] = color.g; - worldVertices[w + 4] = color.b; - worldVertices[w + 5] = color.a; - } - } - else { - var deform = deformArray; - for (var w = 0, v = 0, b = 0, f = 0, n = bones.length; v < n; w += 8) { - var wx = 0, wy = 0; - var nn = bones[v++] + v; - for (; v < nn; v++, b += 3, f += 2) { - var bone = skeletonBones[bones[v]]; - var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; - wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; - } - worldVertices[w] = wx; - worldVertices[w + 1] = wy; - worldVertices[w + 2] = color.r; - worldVertices[w + 3] = color.g; - worldVertices[w + 4] = color.b; - worldVertices[w + 5] = color.a; - } - } - return worldVertices; - }; - MeshAttachment.prototype.applyDeform = function (sourceAttachment) { - return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment); - }; - MeshAttachment.prototype.getParentMesh = function () { - return this.parentMesh; - }; - MeshAttachment.prototype.setParentMesh = function (parentMesh) { - this.parentMesh = parentMesh; - if (parentMesh != null) { - this.bones = parentMesh.bones; - this.vertices = parentMesh.vertices; - this.regionUVs = parentMesh.regionUVs; - this.triangles = parentMesh.triangles; - this.hullLength = parentMesh.hullLength; - } - }; - return MeshAttachment; - }(spine.VertexAttachment)); - spine.MeshAttachment = MeshAttachment; -})(spine || (spine = {})); -var spine; -(function (spine) { - var PathAttachment = (function (_super) { - __extends(PathAttachment, _super); - function PathAttachment(name) { - _super.call(this, name); - this.closed = false; - this.constantSpeed = false; - this.color = new spine.Color(1, 1, 1, 1); - } - return PathAttachment; - }(spine.VertexAttachment)); - spine.PathAttachment = PathAttachment; -})(spine || (spine = {})); -var spine; -(function (spine) { - var RegionAttachment = (function (_super) { - __extends(RegionAttachment, _super); - function RegionAttachment(name) { - _super.call(this, name); - this.x = 0; - this.y = 0; - this.scaleX = 1; - this.scaleY = 1; - this.rotation = 0; - this.width = 0; - this.height = 0; - this.color = new spine.Color(1, 1, 1, 1); - this.offset = spine.Utils.newFloatArray(8); - this.vertices = spine.Utils.newFloatArray(8 * 4); - this.tempColor = new spine.Color(1, 1, 1, 1); - } - RegionAttachment.prototype.setRegion = function (region) { - var vertices = this.vertices; - if (region.rotate) { - vertices[RegionAttachment.U2] = region.u; - vertices[RegionAttachment.V2] = region.v2; - vertices[RegionAttachment.U3] = region.u; - vertices[RegionAttachment.V3] = region.v; - vertices[RegionAttachment.U4] = region.u2; - vertices[RegionAttachment.V4] = region.v; - vertices[RegionAttachment.U1] = region.u2; - vertices[RegionAttachment.V1] = region.v2; - } - else { - vertices[RegionAttachment.U1] = region.u; - vertices[RegionAttachment.V1] = region.v2; - vertices[RegionAttachment.U2] = region.u; - vertices[RegionAttachment.V2] = region.v; - vertices[RegionAttachment.U3] = region.u2; - vertices[RegionAttachment.V3] = region.v; - vertices[RegionAttachment.U4] = region.u2; - vertices[RegionAttachment.V4] = region.v2; - } - this.region = region; - }; - RegionAttachment.prototype.updateOffset = function () { - var regionScaleX = this.width / this.region.originalWidth * this.scaleX; - var regionScaleY = this.height / this.region.originalHeight * this.scaleY; - var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; - var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; - var localX2 = localX + this.region.width * regionScaleX; - var localY2 = localY + this.region.height * regionScaleY; - var radians = this.rotation * Math.PI / 180; - var cos = Math.cos(radians); - var sin = Math.sin(radians); - var localXCos = localX * cos + this.x; - var localXSin = localX * sin; - var localYCos = localY * cos + this.y; - var localYSin = localY * sin; - var localX2Cos = localX2 * cos + this.x; - var localX2Sin = localX2 * sin; - var localY2Cos = localY2 * cos + this.y; - var localY2Sin = localY2 * sin; - var offset = this.offset; - offset[RegionAttachment.OX1] = localXCos - localYSin; - offset[RegionAttachment.OY1] = localYCos + localXSin; - offset[RegionAttachment.OX2] = localXCos - localY2Sin; - offset[RegionAttachment.OY2] = localY2Cos + localXSin; - offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; - offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; - offset[RegionAttachment.OX4] = localX2Cos - localYSin; - offset[RegionAttachment.OY4] = localYCos + localX2Sin; - }; - RegionAttachment.prototype.updateWorldVertices = function (slot, premultipliedAlpha) { - var skeleton = slot.bone.skeleton; - var skeletonColor = skeleton.color; - var slotColor = slot.color; - var regionColor = this.color; - var alpha = skeletonColor.a * slotColor.a * regionColor.a; - var multiplier = premultipliedAlpha ? alpha : 1; - var color = this.tempColor; - color.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha); - var vertices = this.vertices; - var offset = this.offset; - var bone = slot.bone; - var x = bone.worldX, y = bone.worldY; - var a = bone.a, b = bone.b, c = bone.c, d = bone.d; - var offsetX = 0, offsetY = 0; - offsetX = offset[RegionAttachment.OX1]; - offsetY = offset[RegionAttachment.OY1]; - vertices[RegionAttachment.X1] = offsetX * a + offsetY * b + x; - vertices[RegionAttachment.Y1] = offsetX * c + offsetY * d + y; - vertices[RegionAttachment.C1R] = color.r; - vertices[RegionAttachment.C1G] = color.g; - vertices[RegionAttachment.C1B] = color.b; - vertices[RegionAttachment.C1A] = color.a; - offsetX = offset[RegionAttachment.OX2]; - offsetY = offset[RegionAttachment.OY2]; - vertices[RegionAttachment.X2] = offsetX * a + offsetY * b + x; - vertices[RegionAttachment.Y2] = offsetX * c + offsetY * d + y; - vertices[RegionAttachment.C2R] = color.r; - vertices[RegionAttachment.C2G] = color.g; - vertices[RegionAttachment.C2B] = color.b; - vertices[RegionAttachment.C2A] = color.a; - offsetX = offset[RegionAttachment.OX3]; - offsetY = offset[RegionAttachment.OY3]; - vertices[RegionAttachment.X3] = offsetX * a + offsetY * b + x; - vertices[RegionAttachment.Y3] = offsetX * c + offsetY * d + y; - vertices[RegionAttachment.C3R] = color.r; - vertices[RegionAttachment.C3G] = color.g; - vertices[RegionAttachment.C3B] = color.b; - vertices[RegionAttachment.C3A] = color.a; - offsetX = offset[RegionAttachment.OX4]; - offsetY = offset[RegionAttachment.OY4]; - vertices[RegionAttachment.X4] = offsetX * a + offsetY * b + x; - vertices[RegionAttachment.Y4] = offsetX * c + offsetY * d + y; - vertices[RegionAttachment.C4R] = color.r; - vertices[RegionAttachment.C4G] = color.g; - vertices[RegionAttachment.C4B] = color.b; - vertices[RegionAttachment.C4A] = color.a; - return vertices; - }; - RegionAttachment.OX1 = 0; - RegionAttachment.OY1 = 1; - RegionAttachment.OX2 = 2; - RegionAttachment.OY2 = 3; - RegionAttachment.OX3 = 4; - RegionAttachment.OY3 = 5; - RegionAttachment.OX4 = 6; - RegionAttachment.OY4 = 7; - RegionAttachment.X1 = 0; - RegionAttachment.Y1 = 1; - RegionAttachment.C1R = 2; - RegionAttachment.C1G = 3; - RegionAttachment.C1B = 4; - RegionAttachment.C1A = 5; - RegionAttachment.U1 = 6; - RegionAttachment.V1 = 7; - RegionAttachment.X2 = 8; - RegionAttachment.Y2 = 9; - RegionAttachment.C2R = 10; - RegionAttachment.C2G = 11; - RegionAttachment.C2B = 12; - RegionAttachment.C2A = 13; - RegionAttachment.U2 = 14; - RegionAttachment.V2 = 15; - RegionAttachment.X3 = 16; - RegionAttachment.Y3 = 17; - RegionAttachment.C3R = 18; - RegionAttachment.C3G = 19; - RegionAttachment.C3B = 20; - RegionAttachment.C3A = 21; - RegionAttachment.U3 = 22; - RegionAttachment.V3 = 23; - RegionAttachment.X4 = 24; - RegionAttachment.Y4 = 25; - RegionAttachment.C4R = 26; - RegionAttachment.C4G = 27; - RegionAttachment.C4B = 28; - RegionAttachment.C4A = 29; - RegionAttachment.U4 = 30; - RegionAttachment.V4 = 31; - return RegionAttachment; - }(spine.Attachment)); - spine.RegionAttachment = RegionAttachment; -})(spine || (spine = {})); -var spine; -(function (spine) { - (function (BlendMode) { - BlendMode[BlendMode["Normal"] = 0] = "Normal"; - BlendMode[BlendMode["Additive"] = 1] = "Additive"; - BlendMode[BlendMode["Multiply"] = 2] = "Multiply"; - BlendMode[BlendMode["Screen"] = 3] = "Screen"; - })(spine.BlendMode || (spine.BlendMode = {})); - var BlendMode = spine.BlendMode; -})(spine || (spine = {})); -var spine; -(function (spine) { - var Bone = (function () { - function Bone(data, skeleton, parent) { - this.children = new Array(); - this.x = 0; - this.y = 0; - this.rotation = 0; - this.scaleX = 0; - this.scaleY = 0; - this.shearX = 0; - this.shearY = 0; - this.ax = 0; - this.ay = 0; - this.arotation = 0; - this.ascaleX = 0; - this.ascaleY = 0; - this.ashearX = 0; - this.ashearY = 0; - this.appliedValid = false; - this.a = 0; - this.b = 0; - this.worldX = 0; - this.c = 0; - this.d = 0; - this.worldY = 0; - this.sorted = false; - if (data == null) - throw new Error("data cannot be null."); - if (skeleton == null) - throw new Error("skeleton cannot be null."); - this.data = data; - this.skeleton = skeleton; - this.parent = parent; - this.setToSetupPose(); - } - Bone.prototype.update = function () { - this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); - }; - Bone.prototype.updateWorldTransform = function () { - this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); - }; - Bone.prototype.updateWorldTransformWith = function (x, y, rotation, scaleX, scaleY, shearX, shearY) { - this.ax = x; - this.ay = y; - this.arotation = rotation; - this.ascaleX = scaleX; - this.ascaleY = scaleY; - this.ashearX = shearX; - this.ashearY = shearY; - this.appliedValid = true; - var parent = this.parent; - if (parent == null) { - var rotationY = rotation + 90 + shearY; - var la = spine.MathUtils.cosDeg(rotation + shearX) * scaleX; - var lb = spine.MathUtils.cosDeg(rotationY) * scaleY; - var lc = spine.MathUtils.sinDeg(rotation + shearX) * scaleX; - var ld = spine.MathUtils.sinDeg(rotationY) * scaleY; - var skeleton = this.skeleton; - if (skeleton.flipX) { - x = -x; - la = -la; - lb = -lb; - } - if (skeleton.flipY) { - y = -y; - lc = -lc; - ld = -ld; - } - this.a = la; - this.b = lb; - this.c = lc; - this.d = ld; - this.worldX = x + skeleton.x; - this.worldY = y + skeleton.y; - return; + this.a = la; + this.b = lb; + this.c = lc; + this.d = ld; + this.worldX = x + skeleton.x; + this.worldY = y + skeleton.y; + return; } var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; this.worldX = pa * x + pb * y + parent.worldX; @@ -2330,14 +2202,14 @@ var spine; var lb = spine.MathUtils.cosDeg(90 + shearY) * scaleY; var lc = spine.MathUtils.sinDeg(shearX) * scaleX; var ld = spine.MathUtils.sinDeg(90 + shearY) * scaleY; + if (this.data.transformMode != spine.TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : this.skeleton.flipX != this.skeleton.flipY) { + zb = -zb; + zd = -zd; + } this.a = za * la + zb * lc; this.b = za * lb + zb * ld; this.c = zc * la + zd * lc; this.d = zc * lb + zd * ld; - if (this.data.transformMode != spine.TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : this.skeleton.flipX != this.skeleton.flipY) { - this.b = -this.b; - this.d = -this.d; - } return; } } @@ -2372,29 +2244,6 @@ var spine; Bone.prototype.getWorldScaleY = function () { return Math.sqrt(this.b * this.b + this.d * this.d); }; - Bone.prototype.worldToLocalRotationX = function () { - var parent = this.parent; - if (parent == null) - return this.arotation; - var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c; - return Math.atan2(pa * c - pc * a, pd * a - pb * c) * spine.MathUtils.radDeg; - }; - Bone.prototype.worldToLocalRotationY = function () { - var parent = this.parent; - if (parent == null) - return this.arotation; - var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d; - return Math.atan2(pa * d - pc * b, pd * b - pb * d) * spine.MathUtils.radDeg; - }; - Bone.prototype.rotateWorld = function (degrees) { - var a = this.a, b = this.b, c = this.c, d = this.d; - var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); - this.a = cos * a - sin * c; - this.b = cos * b - sin * d; - this.c = sin * a + cos * c; - this.d = sin * b + cos * d; - this.appliedValid = false; - }; Bone.prototype.updateAppliedTransform = function () { this.appliedValid = true; var parent = this.parent; @@ -2450,6 +2299,23 @@ var spine; local.y = x * this.c + y * this.d + this.worldY; return local; }; + Bone.prototype.worldToLocalRotation = function (worldRotation) { + var sin = spine.MathUtils.sinDeg(worldRotation), cos = spine.MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * spine.MathUtils.radDeg; + }; + Bone.prototype.localToWorldRotation = function (localRotation) { + var sin = spine.MathUtils.sinDeg(localRotation), cos = spine.MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * spine.MathUtils.radDeg; + }; + Bone.prototype.rotateWorld = function (degrees) { + var a = this.a, b = this.b, c = this.c, d = this.d; + var cos = spine.MathUtils.cosDeg(degrees), sin = spine.MathUtils.sinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + this.appliedValid = false; + }; return Bone; }()); spine.Bone = Bone; @@ -2477,14 +2343,14 @@ var spine; return BoneData; }()); spine.BoneData = BoneData; + var TransformMode; (function (TransformMode) { TransformMode[TransformMode["Normal"] = 0] = "Normal"; TransformMode[TransformMode["OnlyTranslation"] = 1] = "OnlyTranslation"; TransformMode[TransformMode["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; TransformMode[TransformMode["NoScale"] = 3] = "NoScale"; TransformMode[TransformMode["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; - })(spine.TransformMode || (spine.TransformMode = {})); - var TransformMode = spine.TransformMode; + })(TransformMode = spine.TransformMode || (spine.TransformMode = {})); })(spine || (spine = {})); var spine; (function (spine) { @@ -2647,37 +2513,26 @@ var spine; break outer; } } - var minAngle = 0, minDist = Number.MAX_VALUE, minX = 0, minY = 0; - var maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0; - x = l1 + a; - d = x * x; - if (d > maxDist) { - maxAngle = 0; - maxDist = d; - maxX = x; - } - x = l1 - a; - d = x * x; - if (d < minDist) { - minAngle = spine.MathUtils.PI; - minDist = d; - minX = x; - } - var angle = Math.acos(-a * l1 / (aa - bb)); - x = a * Math.cos(angle) + l1; - y = b * Math.sin(angle); - d = x * x + y * y; - if (d < minDist) { - minAngle = angle; - minDist = d; - minX = x; - minY = y; - } - if (d > maxDist) { - maxAngle = angle; - maxDist = d; - maxX = x; - maxY = y; + var minAngle = spine.MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + var maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } } if (dd <= (minDist + maxDist) / 2) { a1 = ta - Math.atan2(minY * bendDir, minX); @@ -2775,11 +2630,14 @@ var spine; lengths = spine.Utils.setArraySize(this.lengths, boneCount); for (var i = 0, n = spacesCount - 1; i < n;) { var bone = bones[i]; - var length_1 = bone.data.length, x = length_1 * bone.a, y = length_1 * bone.c; - length_1 = Math.sqrt(x * x + y * y); + var setupLength = bone.data.length; + if (setupLength == 0) + setupLength = 0.0000001; + var x = setupLength * bone.a, y = setupLength * bone.c; + var length_1 = Math.sqrt(x * x + y * y); if (scale) lengths[i] = length_1; - spaces[++i] = lengthSpacing ? Math.max(0, length_1 + spacing) : spacing; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length_1 / setupLength; } } else { @@ -2875,7 +2733,7 @@ var spine; else if (p < 0) { if (prevCurve != PathConstraint.BEFORE) { prevCurve = PathConstraint.BEFORE; - path.computeWorldVerticesWith(target, 2, 4, world, 0); + path.computeWorldVertices(target, 2, 4, world, 0, 2); } this.addBeforePosition(p, world, 0, out, o); continue; @@ -2883,7 +2741,7 @@ var spine; else if (p > pathLength_1) { if (prevCurve != PathConstraint.AFTER) { prevCurve = PathConstraint.AFTER; - path.computeWorldVerticesWith(target, verticesLength - 6, 4, world, 0); + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); } this.addAfterPosition(p - pathLength_1, world, 0, out, o); continue; @@ -2903,11 +2761,11 @@ var spine; if (curve != prevCurve) { prevCurve = curve; if (closed && curve == curveCount) { - path.computeWorldVerticesWith(target, verticesLength - 4, 4, world, 0); - path.computeWorldVerticesWith(target, 0, 4, world, 4); + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); } else - path.computeWorldVerticesWith(target, curve * 6 + 2, 8, world, 0); + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); } this.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o, tangents || (i > 0 && space == 0)); } @@ -2916,8 +2774,8 @@ var spine; if (closed) { verticesLength += 2; world = spine.Utils.setArraySize(this.world, verticesLength); - path.computeWorldVerticesWith(target, 2, verticesLength - 4, world, 0); - path.computeWorldVerticesWith(target, 0, 2, world, verticesLength - 4); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); world[verticesLength - 2] = world[0]; world[verticesLength - 1] = world[1]; } @@ -2925,7 +2783,7 @@ var spine; curveCount--; verticesLength -= 4; world = spine.Utils.setArraySize(this.world, verticesLength); - path.computeWorldVerticesWith(target, 2, verticesLength, world, 0); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); } var curves = spine.Utils.setArraySize(this.curves, curveCount); var pathLength = 0; @@ -3082,11 +2940,11 @@ var spine; PathConstraint.prototype.getOrder = function () { return this.data.order; }; - PathConstraint.NONE = -1; - PathConstraint.BEFORE = -2; - PathConstraint.AFTER = -3; return PathConstraint; }()); + PathConstraint.NONE = -1; + PathConstraint.BEFORE = -2; + PathConstraint.AFTER = -3; spine.PathConstraint = PathConstraint; })(spine || (spine = {})); var spine; @@ -3100,24 +2958,33 @@ var spine; return PathConstraintData; }()); spine.PathConstraintData = PathConstraintData; + var PositionMode; (function (PositionMode) { PositionMode[PositionMode["Fixed"] = 0] = "Fixed"; PositionMode[PositionMode["Percent"] = 1] = "Percent"; - })(spine.PositionMode || (spine.PositionMode = {})); - var PositionMode = spine.PositionMode; + })(PositionMode = spine.PositionMode || (spine.PositionMode = {})); + var SpacingMode; (function (SpacingMode) { SpacingMode[SpacingMode["Length"] = 0] = "Length"; SpacingMode[SpacingMode["Fixed"] = 1] = "Fixed"; SpacingMode[SpacingMode["Percent"] = 2] = "Percent"; - })(spine.SpacingMode || (spine.SpacingMode = {})); - var SpacingMode = spine.SpacingMode; + })(SpacingMode = spine.SpacingMode || (spine.SpacingMode = {})); + var RotateMode; (function (RotateMode) { RotateMode[RotateMode["Tangent"] = 0] = "Tangent"; RotateMode[RotateMode["Chain"] = 1] = "Chain"; RotateMode[RotateMode["ChainScale"] = 2] = "ChainScale"; - })(spine.RotateMode || (spine.RotateMode = {})); - var RotateMode = spine.RotateMode; + })(RotateMode = spine.RotateMode || (spine.RotateMode = {})); })(spine || (spine = {})); +(function () { + if (!Math.fround) { + Math.fround = (function (array) { + return function (x) { + return array[0] = x, array[0]; + }; + })(new Float32Array(1)); + } +})(); var spine; (function (spine) { var Assets = (function () { @@ -3313,6 +3180,7 @@ var spine; Skeleton.prototype.updateCache = function () { var updateCache = this._updateCache; updateCache.length = 0; + this.updateCacheReset.length = 0; var bones = this.bones; for (var i = 0, n = bones.length; i < n; i++) bones[i].sorted = false; @@ -3370,27 +3238,38 @@ var spine; this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin) this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); - for (var ii = 0, nn = this.data.skins.length; ii < nn; ii++) - this.sortPathConstraintAttachment(this.data.skins[ii], slotIndex, slotBone); + for (var i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); var attachment = slot.getAttachment(); if (attachment instanceof spine.PathAttachment) this.sortPathConstraintAttachmentWith(attachment, slotBone); var constrained = constraint.bones; var boneCount = constrained.length; - for (var ii = 0; ii < boneCount; ii++) - this.sortBone(constrained[ii]); + for (var i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); this._updateCache.push(constraint); - for (var ii = 0; ii < boneCount; ii++) - this.sortReset(constrained[ii].children); - for (var ii = 0; ii < boneCount; ii++) - constrained[ii].sorted = true; + for (var i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (var i = 0; i < boneCount; i++) + constrained[i].sorted = true; }; Skeleton.prototype.sortTransformConstraint = function (constraint) { this.sortBone(constraint.target); var constrained = constraint.bones; var boneCount = constrained.length; - for (var ii = 0; ii < boneCount; ii++) - this.sortBone(constrained[ii]); + if (constraint.data.local) { + for (var i = 0; i < boneCount; i++) { + var child = constrained[i]; + this.sortBone(child.parent); + if (!(this._updateCache.indexOf(child) > -1)) + this.updateCacheReset.push(child); + } + } + else { + for (var i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } this._updateCache.push(constraint); for (var ii = 0; ii < boneCount; ii++) this.sortReset(constrained[ii].children); @@ -3633,7 +3512,7 @@ var spine; } return null; }; - Skeleton.prototype.getBounds = function (offset, size) { + Skeleton.prototype.getBounds = function (offset, size, temp) { if (offset == null) throw new Error("offset cannot be null."); if (size == null) @@ -3642,14 +3521,22 @@ var spine; var minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; for (var i = 0, n = drawOrder.length; i < n; i++) { var slot = drawOrder[i]; + var verticesLength = 0; var vertices = null; var attachment = slot.getAttachment(); - if (attachment instanceof spine.RegionAttachment) - vertices = attachment.updateWorldVertices(slot, false); - else if (attachment instanceof spine.MeshAttachment) - vertices = attachment.updateWorldVertices(slot, true); + if (attachment instanceof spine.RegionAttachment) { + verticesLength = 8; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); + } + else if (attachment instanceof spine.MeshAttachment) { + var mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = spine.Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + } if (vertices != null) { - for (var ii = 0, nn = vertices.length; ii < nn; ii += 8) { + for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) { var x = vertices[ii], y = vertices[ii + 1]; minX = Math.min(minX, x); minY = Math.min(minY, y); @@ -3704,7 +3591,7 @@ var spine; polygon = spine.Utils.newFloatArray(boundingBox.worldVerticesLength); } polygons.push(polygon); - boundingBox.computeWorldVertices(slot, polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); } } if (updateAabb) { @@ -3835,6 +3722,286 @@ var spine; spine.SkeletonBounds = SkeletonBounds; })(spine || (spine = {})); var spine; +(function (spine) { + var SkeletonClipping = (function () { + function SkeletonClipping() { + this.triangulator = new spine.Triangulator(); + this.clippingPolygon = new Array(); + this.clipOutput = new Array(); + this.clippedVertices = new Array(); + this.clippedTriangles = new Array(); + this.scratch = new Array(); + } + SkeletonClipping.prototype.clipStart = function (slot, clip) { + if (this.clipAttachment != null) + return 0; + this.clipAttachment = clip; + var n = clip.worldVerticesLength; + var vertices = spine.Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + var clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + var clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (var i = 0, n_1 = clippingPolygons.length; i < n_1; i++) { + var polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + }; + SkeletonClipping.prototype.clipEndWithSlot = function (slot) { + if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + }; + SkeletonClipping.prototype.clipEnd = function () { + if (this.clipAttachment == null) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + }; + SkeletonClipping.prototype.isClipping = function () { + return this.clipAttachment != null; + }; + SkeletonClipping.prototype.clipTriangles = function (vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) { + var clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + var clippedTriangles = this.clippedTriangles; + var polygons = this.clippingPolygons; + var polygonsCount = this.clippingPolygons.length; + var vertexSize = twoColor ? 12 : 8; + var index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + outer: for (var i = 0; i < trianglesLength; i += 3) { + var vertexOffset = triangles[i] << 1; + var x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + var u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + var x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + var u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + var x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + var u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (var p = 0; p < polygonsCount; p++) { + var s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + var clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + var d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + var d = 1 / (d0 * d2 + d1 * (y1 - y3)); + var clipOutputCount = clipOutputLength >> 1; + var clipOutputItems = this.clipOutput; + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (var ii = 0; ii < clipOutputLength; ii += 2) { + var x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + var c0 = x - x3, c1 = y - y3; + var a = (d0 * c0 + d1 * c1) * d; + var b = (d4 * c0 + d2 * c1) * d; + var c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + s += vertexSize; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (var ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + ii); + clippedTrianglesItems[s + 2] = (index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + } + else { + var clippedVerticesItems = spine.Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } + else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + var clippedTrianglesItems = spine.Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (index + 1); + clippedTrianglesItems[s + 2] = (index + 2); + index += 3; + continue outer; + } + } + } + }; + SkeletonClipping.prototype.clip = function (x1, y1, x2, y2, x3, y3, clippingArea, output) { + var originalOutput = output; + var clipped = false; + var input = null; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } + else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + var clippingVertices = clippingArea; + var clippingVerticesLast = clippingArea.length - 4; + for (var i = 0;; i += 2) { + var edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + var edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + var deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + var inputVertices = input; + var inputVerticesLength = input.length - 2, outputStart = output.length; + for (var ii = 0; ii < inputVerticesLength; ii += 2) { + var inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + var inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + var side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + } + else if (side2) { + var c0 = inputY2 - inputY, c2 = inputX2 - inputX; + var ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + output.push(edgeX + (edgeX2 - edgeX) * ua); + output.push(edgeY + (edgeY2 - edgeY) * ua); + output.push(inputX2); + output.push(inputY2); + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + var temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (var i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } + else + originalOutput.length = originalOutput.length - 2; + return clipped; + }; + SkeletonClipping.makeClockwise = function (polygon) { + var vertices = polygon; + var verticeslength = polygon.length; + var area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (var i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (var i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + var x = vertices[i], y = vertices[i + 1]; + var other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + }; + return SkeletonClipping; + }()); + spine.SkeletonClipping = SkeletonClipping; +})(spine || (spine = {})); +var spine; (function (spine) { var SkeletonData = (function () { function SkeletonData() { @@ -4023,6 +4190,11 @@ var spine; var color = this.getValue(slotMap, "color", null); if (color != null) data.color.setFromString(color); + var dark = this.getValue(slotMap, "dark", null); + if (dark != null) { + data.darkColor = new spine.Color(1, 1, 1, 1); + data.darkColor.setFromString(dark); + } data.attachmentName = this.getValue(slotMap, "attachment", null); data.blendMode = SkeletonJson.blendModeFromString(this.getValue(slotMap, "blend", "normal")); skeletonData.slots.push(data); @@ -4065,6 +4237,8 @@ var spine; data.target = skeletonData.findBone(targetName); if (data.target == null) throw new Error("Transform constraint target bone not found: " + targetName); + data.local = this.getValue(constraintMap, "local", false); + data.relative = this.getValue(constraintMap, "relative", false); data.offsetRotation = this.getValue(constraintMap, "rotation", 0); data.offsetX = this.getValue(constraintMap, "x", 0) * scale; data.offsetY = this.getValue(constraintMap, "y", 0) * scale; @@ -4119,7 +4293,7 @@ var spine; throw new Error("Slot not found: " + slotName); var slotMap = skinMap[slotName]; for (var entryName in slotMap) { - var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName); + var attachment = this.readAttachment(slotMap[entryName], skin, slotIndex, entryName, skeletonData); if (attachment != null) skin.addAttachment(slotIndex, entryName, attachment); } @@ -4159,7 +4333,7 @@ var spine; } return skeletonData; }; - SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name) { + SkeletonJson.prototype.readAttachment = function (map, skin, slotIndex, name, skeletonData) { var scale = this.scale; name = this.getValue(map, "name", name); var type = this.getValue(map, "type", "region"); @@ -4227,13 +4401,43 @@ var spine; this.readVertices(map, path, vertexCount << 1); var lengths = spine.Utils.newArray(vertexCount / 3, 0); for (var i = 0; i < map.lengths.length; i++) - lengths[i++] = map.lengths[i] * scale; + lengths[i] = map.lengths[i] * scale; path.lengths = lengths; var color = this.getValue(map, "color", null); if (color != null) path.color.setFromString(color); return path; } + case "point": { + var point = this.attachmentLoader.newPointAttachment(skin, name); + if (point == null) + return null; + point.x = this.getValue(map, "x", 0) * scale; + point.y = this.getValue(map, "y", 0) * scale; + point.rotation = this.getValue(map, "rotation", 0); + var color = this.getValue(map, "color", null); + if (color != null) + point.color.setFromString(color); + return point; + } + case "clipping": { + var clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (clip == null) + return null; + var end = this.getValue(map, "end", null); + if (end != null) { + var slot = skeletonData.findSlot(end); + if (slot == null) + throw new Error("Clipping end slot not found: " + end); + clip.endSlot = slot; + } + var vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + var color = this.getValue(map, "color", null); + if (color != null) + clip.color.setFromString(color); + return clip; + } } return null; }; @@ -4241,8 +4445,8 @@ var spine; var scale = this.scale; attachment.worldVerticesLength = verticesLength; var vertices = map.vertices; - var scaledVertices = spine.Utils.toFloatArray(vertices); - if (verticesLength == scaledVertices.length) { + if (verticesLength == vertices.length) { + var scaledVertices = spine.Utils.toFloatArray(vertices); if (scale != 1) { for (var i = 0, n = vertices.length; i < n; i++) scaledVertices[i] *= scale; @@ -4277,7 +4481,18 @@ var spine; throw new Error("Slot not found: " + slotName); for (var timelineName in slotMap) { var timelineMap = slotMap[timelineName]; - if (timelineName == "color") { + if (timelineName == "attachment") { + var timeline = new spine.AttachmentTimeline(timelineMap.length); + timeline.slotIndex = slotIndex; + var frameIndex = 0; + for (var i = 0; i < timelineMap.length; i++) { + var valueMap = timelineMap[i]; + timeline.setFrame(frameIndex++, valueMap.time, valueMap.name); + } + timelines.push(timeline); + duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + } + else if (timelineName == "color") { var timeline = new spine.ColorTimeline(timelineMap.length); timeline.slotIndex = slotIndex; var frameIndex = 0; @@ -4292,16 +4507,22 @@ var spine; timelines.push(timeline); duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.ColorTimeline.ENTRIES]); } - else if (timelineName = "attachment") { - var timeline = new spine.AttachmentTimeline(timelineMap.length); + else if (timelineName == "twoColor") { + var timeline = new spine.TwoColorTimeline(timelineMap.length); timeline.slotIndex = slotIndex; var frameIndex = 0; for (var i = 0; i < timelineMap.length; i++) { var valueMap = timelineMap[i]; - timeline.setFrame(frameIndex++, valueMap.time, valueMap.name); + var light = new spine.Color(); + var dark = new spine.Color(); + light.setFromString(valueMap.light); + dark.setFromString(valueMap.dark); + timeline.setFrame(frameIndex, valueMap.time, light.r, light.g, light.b, light.a, dark.r, dark.g, dark.b); + this.readCurve(valueMap, timeline, frameIndex); + frameIndex++; } timelines.push(timeline); - duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]); + duration = Math.max(duration, timeline.frames[(timeline.getFrameCount() - 1) * spine.TwoColorTimeline.ENTRIES]); } else throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); @@ -4535,7 +4756,7 @@ var spine; var eventData = skeletonData.findEvent(eventMap.name); if (eventData == null) throw new Error("Event not found: " + eventMap.name); - var event_5 = new spine.Event(eventMap.time, eventData); + var event_5 = new spine.Event(spine.Utils.toSinglePrecision(eventMap.time), eventData); event_5.intValue = this.getValue(eventMap, "int", eventData.intValue); event_5.floatValue = this.getValue(eventMap, "float", eventData.floatValue); event_5.stringValue = this.getValue(eventMap, "string", eventData.stringValue); @@ -4688,6 +4909,7 @@ var spine; this.data = data; this.bone = bone; this.color = new spine.Color(); + this.darkColor = data.darkColor == null ? null : new spine.Color(); this.setToSetupPose(); } Slot.prototype.getAttachment = function () { @@ -4708,6 +4930,8 @@ var spine; }; Slot.prototype.setToSetupPose = function () { this.color.setFromColor(this.data.color); + if (this.darkColor != null) + this.darkColor.setFromColor(this.data.darkColor); if (this.data.attachmentName == null) this.attachment = null; else { @@ -4770,6 +4994,7 @@ var spine; return Texture; }()); spine.Texture = Texture; + var TextureFilter; (function (TextureFilter) { TextureFilter[TextureFilter["Nearest"] = 9728] = "Nearest"; TextureFilter[TextureFilter["Linear"] = 9729] = "Linear"; @@ -4778,14 +5003,13 @@ var spine; TextureFilter[TextureFilter["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; TextureFilter[TextureFilter["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; TextureFilter[TextureFilter["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; - })(spine.TextureFilter || (spine.TextureFilter = {})); - var TextureFilter = spine.TextureFilter; + })(TextureFilter = spine.TextureFilter || (spine.TextureFilter = {})); + var TextureWrap; (function (TextureWrap) { TextureWrap[TextureWrap["MirroredRepeat"] = 33648] = "MirroredRepeat"; TextureWrap[TextureWrap["ClampToEdge"] = 33071] = "ClampToEdge"; TextureWrap[TextureWrap["Repeat"] = 10497] = "Repeat"; - })(spine.TextureWrap || (spine.TextureWrap = {})); - var TextureWrap = spine.TextureWrap; + })(TextureWrap = spine.TextureWrap || (spine.TextureWrap = {})); var TextureRegion = (function () { function TextureRegion() { this.u = 0; @@ -4953,7 +5177,7 @@ var spine; var TextureAtlasRegion = (function (_super) { __extends(TextureAtlasRegion, _super); function TextureAtlasRegion() { - _super.apply(this, arguments); + return _super !== null && _super.apply(this, arguments) || this; } return TextureAtlasRegion; }(spine.TextureRegion)); @@ -4986,6 +5210,20 @@ var spine; this.update(); }; TransformConstraint.prototype.update = function () { + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } + else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + }; + TransformConstraint.prototype.applyAbsoluteWorld = function () { var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; var target = this.target; var ta = target.a, tb = target.b, tc = target.c, td = target.d; @@ -5051,6 +5289,132 @@ var spine; bone.appliedValid = false; } }; + TransformConstraint.prototype.applyRelativeWorld = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + var ta = target.a, tb = target.b, tc = target.c, td = target.d; + var degRadReflect = ta * td - tb * tc > 0 ? spine.MathUtils.degRad : -spine.MathUtils.degRad; + var offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + var modified = false; + if (rotateMix != 0) { + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var r = Math.atan2(tc, ta) + offsetRotation; + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + r *= rotateMix; + var cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + modified = true; + } + if (translateMix != 0) { + var temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * translateMix; + bone.worldY += temp.y * translateMix; + modified = true; + } + if (scaleMix > 0) { + var s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * scaleMix + 1; + bone.a *= s; + bone.c *= s; + s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * scaleMix + 1; + bone.b *= s; + bone.d *= s; + modified = true; + } + if (shearMix > 0) { + var r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > spine.MathUtils.PI) + r -= spine.MathUtils.PI2; + else if (r < -spine.MathUtils.PI) + r += spine.MathUtils.PI2; + var b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - spine.MathUtils.PI / 2 + offsetShearY) * shearMix; + var s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + modified = true; + } + if (modified) + bone.appliedValid = false; + } + }; + TransformConstraint.prototype.applyAbsoluteLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) { + var r = target.arotation - rotation + this.data.offsetRotation; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + rotation += r * rotateMix; + } + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax - x + this.data.offsetX) * translateMix; + y += (target.ay - y + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix > 0) { + if (scaleX > 0.00001) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * scaleMix) / scaleX; + if (scaleY > 0.00001) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * scaleMix) / scaleY; + } + var shearY = bone.ashearY; + if (shearMix > 0) { + var r = target.ashearY - shearY + this.data.offsetShearY; + r -= (16384 - ((16384.499999999996 - r / 360) | 0)) * 360; + bone.shearY += r * shearMix; + } + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; + TransformConstraint.prototype.applyRelativeLocal = function () { + var rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; + var target = this.target; + if (!target.appliedValid) + target.updateAppliedTransform(); + var bones = this.bones; + for (var i = 0, n = bones.length; i < n; i++) { + var bone = bones[i]; + if (!bone.appliedValid) + bone.updateAppliedTransform(); + var rotation = bone.arotation; + if (rotateMix != 0) + rotation += (target.arotation + this.data.offsetRotation) * rotateMix; + var x = bone.ax, y = bone.ay; + if (translateMix != 0) { + x += (target.ax + this.data.offsetX) * translateMix; + y += (target.ay + this.data.offsetY) * translateMix; + } + var scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (scaleMix > 0) { + if (scaleX > 0.00001) + scaleX *= ((target.ascaleX - 1 + this.data.offsetScaleX) * scaleMix) + 1; + if (scaleY > 0.00001) + scaleY *= ((target.ascaleY - 1 + this.data.offsetScaleY) * scaleMix) + 1; + } + var shearY = bone.ashearY; + if (shearMix > 0) + shearY += (target.ashearY + this.data.offsetShearY) * shearMix; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + }; TransformConstraint.prototype.getOrder = function () { return this.data.order; }; @@ -5074,13 +5438,227 @@ var spine; this.offsetScaleX = 0; this.offsetScaleY = 0; this.offsetShearY = 0; + this.relative = false; + this.local = false; if (name == null) throw new Error("name cannot be null."); this.name = name; } return TransformConstraintData; }()); - spine.TransformConstraintData = TransformConstraintData; + spine.TransformConstraintData = TransformConstraintData; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Triangulator = (function () { + function Triangulator() { + this.convexPolygons = new Array(); + this.convexPolygonsIndices = new Array(); + this.indicesArray = new Array(); + this.isConcaveArray = new Array(); + this.triangles = new Array(); + this.polygonPool = new spine.Pool(function () { + return new Array(); + }); + this.polygonIndicesPool = new spine.Pool(function () { + return new Array(); + }); + } + Triangulator.prototype.triangulate = function (verticesArray) { + var vertices = verticesArray; + var vertexCount = verticesArray.length >> 1; + var indices = this.indicesArray; + indices.length = 0; + for (var i = 0; i < vertexCount; i++) + indices[i] = i; + var isConcave = this.isConcaveArray; + isConcave.length = 0; + for (var i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + var triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + var previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: if (!isConcave[i]) { + var p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + var p1x = vertices[p1], p1y = vertices[p1 + 1]; + var p2x = vertices[p2], p2y = vertices[p2 + 1]; + var p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (var ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + var v = indices[ii] << 1; + var vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + var previousIndex = (vertexCount + i - 1) % vertexCount; + var nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + }; + Triangulator.prototype.decompose = function (verticesArray, triangles) { + var vertices = verticesArray; + var convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + var convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + var polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + var polygon = this.polygonPool.obtain(); + polygon.length = 0; + var fanBaseIndex = -1, lastWinding = 0; + for (var i = 0, n = triangles.length; i < n; i += 3) { + var t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + var x1 = vertices[t1], y1 = vertices[t1 + 1]; + var x2 = vertices[t2], y2 = vertices[t2 + 1]; + var x3 = vertices[t3], y3 = vertices[t3 + 1]; + var merged = false; + if (fanBaseIndex == t1) { + var o = polygon.length - 4; + var winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + var winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (var i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + var firstIndex = polygonIndices[0]; + var lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + var o = polygon.length - 4; + var prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + var prevX = polygon[o + 2], prevY = polygon[o + 3]; + var firstX = polygon[0], firstY = polygon[1]; + var secondX = polygon[2], secondY = polygon[3]; + var winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (var ii = 0; ii < n; ii++) { + if (ii == i) + continue; + var otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + var otherFirstIndex = otherIndices[0]; + var otherSecondIndex = otherIndices[1]; + var otherLastIndex = otherIndices[2]; + var otherPoly = convexPolygons[ii]; + var x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + var winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + var winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (var i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + }; + Triangulator.isConcave = function (index, vertexCount, vertices, indices) { + var previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + var current = indices[index] << 1; + var next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); + }; + Triangulator.positiveArea = function (p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + }; + Triangulator.winding = function (p1x, p1y, p2x, p2y, p3x, p3y) { + var px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + }; + return Triangulator; + }()); + spine.Triangulator = Triangulator; })(spine || (spine = {})); var spine; (function (spine) { @@ -5166,13 +5744,13 @@ var spine; this.a = 1; return this; }; - Color.WHITE = new Color(1, 1, 1, 1); - Color.RED = new Color(1, 0, 0, 1); - Color.GREEN = new Color(0, 1, 0, 1); - Color.BLUE = new Color(0, 0, 1, 1); - Color.MAGENTA = new Color(1, 0, 1, 1); return Color; }()); + Color.WHITE = new Color(1, 1, 1, 1); + Color.RED = new Color(1, 0, 0, 1); + Color.GREEN = new Color(0, 1, 0, 1); + Color.BLUE = new Color(0, 0, 1, 1); + Color.MAGENTA = new Color(1, 0, 1, 1); spine.Color = Color; var MathUtils = (function () { function MathUtils() { @@ -5200,15 +5778,61 @@ var spine; var y = Math.pow(Math.abs(x), 1 / 3); return x < 0 ? -y : y; }; - MathUtils.PI = 3.1415927; - MathUtils.PI2 = MathUtils.PI * 2; - MathUtils.radiansToDegrees = 180 / MathUtils.PI; - MathUtils.radDeg = MathUtils.radiansToDegrees; - MathUtils.degreesToRadians = MathUtils.PI / 180; - MathUtils.degRad = MathUtils.degreesToRadians; + MathUtils.randomTriangular = function (min, max) { + return MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + }; + MathUtils.randomTriangularWith = function (min, max, mode) { + var u = Math.random(); + var d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + }; return MathUtils; }()); + MathUtils.PI = 3.1415927; + MathUtils.PI2 = MathUtils.PI * 2; + MathUtils.radiansToDegrees = 180 / MathUtils.PI; + MathUtils.radDeg = MathUtils.radiansToDegrees; + MathUtils.degreesToRadians = MathUtils.PI / 180; + MathUtils.degRad = MathUtils.degreesToRadians; spine.MathUtils = MathUtils; + var Interpolation = (function () { + function Interpolation() { + } + Interpolation.prototype.apply = function (start, end, a) { + return start + (end - start) * this.applyInternal(a); + }; + return Interpolation; + }()); + spine.Interpolation = Interpolation; + var Pow = (function (_super) { + __extends(Pow, _super); + function Pow(power) { + var _this = _super.call(this) || this; + _this.power = 2; + _this.power = power; + return _this; + } + Pow.prototype.applyInternal = function (a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + }; + return Pow; + }(Interpolation)); + spine.Pow = Pow; + var PowOut = (function (_super) { + __extends(PowOut, _super); + function PowOut(power) { + return _super.call(this, power) || this; + } + PowOut.prototype.applyInternal = function (a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + }; + return PowOut; + }(Pow)); + spine.PowOut = PowOut; var Utils = (function () { function Utils() { } @@ -5252,12 +5876,26 @@ var spine; return array; } }; + Utils.newShortArray = function (size) { + if (Utils.SUPPORTS_TYPED_ARRAYS) { + return new Int16Array(size); + } + else { + var array = new Array(size); + for (var i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + }; Utils.toFloatArray = function (array) { return Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; }; - Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; + Utils.toSinglePrecision = function (value) { + return Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + }; return Utils; }()); + Utils.SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== "undefined"; spine.Utils = Utils; var DebugUtils = (function () { function DebugUtils() { @@ -5353,7 +5991,465 @@ var spine; return TimeKeeper; }()); spine.TimeKeeper = TimeKeeper; + var WindowedMean = (function () { + function WindowedMean(windowSize) { + if (windowSize === void 0) { windowSize = 32; } + this.addedValues = 0; + this.lastValue = 0; + this.mean = 0; + this.dirty = true; + this.values = new Array(windowSize); + } + WindowedMean.prototype.hasEnoughData = function () { + return this.addedValues >= this.values.length; + }; + WindowedMean.prototype.addValue = function (value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + }; + WindowedMean.prototype.getMean = function () { + if (this.hasEnoughData()) { + if (this.dirty) { + var mean = 0; + for (var i = 0; i < this.values.length; i++) { + mean += this.values[i]; + } + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + else { + return 0; + } + }; + return WindowedMean; + }()); + spine.WindowedMean = WindowedMean; +})(spine || (spine = {})); +var spine; +(function (spine) { + var Attachment = (function () { + function Attachment(name) { + if (name == null) + throw new Error("name cannot be null."); + this.name = name; + } + return Attachment; + }()); + spine.Attachment = Attachment; + var VertexAttachment = (function (_super) { + __extends(VertexAttachment, _super); + function VertexAttachment(name) { + var _this = _super.call(this, name) || this; + _this.id = (VertexAttachment.nextID++ & 65535) << 11; + _this.worldVerticesLength = 0; + return _this; + } + VertexAttachment.prototype.computeWorldVertices = function (slot, start, count, worldVertices, offset, stride) { + count = offset + (count >> 1) * stride; + var skeleton = slot.bone.skeleton; + var deformArray = slot.attachmentVertices; + var vertices = this.vertices; + var bones = this.bones; + if (bones == null) { + if (deformArray.length > 0) + vertices = deformArray; + var bone = slot.bone; + var x = bone.worldX; + var y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (var v_1 = start, w = offset; w < count; v_1 += 2, w += stride) { + var vx = vertices[v_1], vy = vertices[v_1 + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + var v = 0, skip = 0; + for (var i = 0; i < start; i += 2) { + var n = bones[v]; + v += n + 1; + skip += n; + } + var skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (var w = offset, b = skip * 3; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + else { + var deform = deformArray; + for (var w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + var wx = 0, wy = 0; + var n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + var bone = skeletonBones[bones[v]]; + var vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices[w] = wx; + worldVertices[w + 1] = wy; + } + } + }; + VertexAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment; + }; + return VertexAttachment; + }(Attachment)); + VertexAttachment.nextID = 0; + spine.VertexAttachment = VertexAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var AttachmentType; + (function (AttachmentType) { + AttachmentType[AttachmentType["Region"] = 0] = "Region"; + AttachmentType[AttachmentType["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType[AttachmentType["Mesh"] = 2] = "Mesh"; + AttachmentType[AttachmentType["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType[AttachmentType["Path"] = 4] = "Path"; + AttachmentType[AttachmentType["Point"] = 5] = "Point"; + })(AttachmentType = spine.AttachmentType || (spine.AttachmentType = {})); +})(spine || (spine = {})); +var spine; +(function (spine) { + var BoundingBoxAttachment = (function (_super) { + __extends(BoundingBoxAttachment, _super); + function BoundingBoxAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; + } + return BoundingBoxAttachment; + }(spine.VertexAttachment)); + spine.BoundingBoxAttachment = BoundingBoxAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var ClippingAttachment = (function (_super) { + __extends(ClippingAttachment, _super); + function ClippingAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.2275, 0.2275, 0.8078, 1); + return _this; + } + return ClippingAttachment; + }(spine.VertexAttachment)); + spine.ClippingAttachment = ClippingAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var MeshAttachment = (function (_super) { + __extends(MeshAttachment, _super); + function MeshAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(1, 1, 1, 1); + _this.inheritDeform = false; + _this.tempColor = new spine.Color(0, 0, 0, 0); + return _this; + } + MeshAttachment.prototype.updateUVs = function () { + var u = 0, v = 0, width = 0, height = 0; + if (this.region == null) { + u = v = 0; + width = height = 1; + } + else { + u = this.region.u; + v = this.region.v; + width = this.region.u2 - u; + height = this.region.v2 - v; + } + var regionUVs = this.regionUVs; + if (this.uvs == null || this.uvs.length != regionUVs.length) + this.uvs = spine.Utils.newFloatArray(regionUVs.length); + var uvs = this.uvs; + if (this.region.rotate) { + for (var i = 0, n = uvs.length; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + height - regionUVs[i] * height; + } + } + else { + for (var i = 0, n = uvs.length; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + } + }; + MeshAttachment.prototype.applyDeform = function (sourceAttachment) { + return this == sourceAttachment || (this.inheritDeform && this.parentMesh == sourceAttachment); + }; + MeshAttachment.prototype.getParentMesh = function () { + return this.parentMesh; + }; + MeshAttachment.prototype.setParentMesh = function (parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh != null) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + }; + return MeshAttachment; + }(spine.VertexAttachment)); + spine.MeshAttachment = MeshAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PathAttachment = (function (_super) { + __extends(PathAttachment, _super); + function PathAttachment(name) { + var _this = _super.call(this, name) || this; + _this.closed = false; + _this.constantSpeed = false; + _this.color = new spine.Color(1, 1, 1, 1); + return _this; + } + return PathAttachment; + }(spine.VertexAttachment)); + spine.PathAttachment = PathAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var PointAttachment = (function (_super) { + __extends(PointAttachment, _super); + function PointAttachment(name) { + var _this = _super.call(this, name) || this; + _this.color = new spine.Color(0.38, 0.94, 0, 1); + return _this; + } + PointAttachment.prototype.computeWorldPosition = function (bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + }; + PointAttachment.prototype.computeWorldRotation = function (bone) { + var cos = spine.MathUtils.cosDeg(this.rotation), sin = spine.MathUtils.sinDeg(this.rotation); + var x = cos * bone.a + sin * bone.b; + var y = cos * bone.c + sin * bone.d; + return Math.atan2(y, x) * spine.MathUtils.radDeg; + }; + return PointAttachment; + }(spine.VertexAttachment)); + spine.PointAttachment = PointAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var RegionAttachment = (function (_super) { + __extends(RegionAttachment, _super); + function RegionAttachment(name) { + var _this = _super.call(this, name) || this; + _this.x = 0; + _this.y = 0; + _this.scaleX = 1; + _this.scaleY = 1; + _this.rotation = 0; + _this.width = 0; + _this.height = 0; + _this.color = new spine.Color(1, 1, 1, 1); + _this.offset = spine.Utils.newFloatArray(8); + _this.uvs = spine.Utils.newFloatArray(8); + _this.tempColor = new spine.Color(1, 1, 1, 1); + return _this; + } + RegionAttachment.prototype.updateOffset = function () { + var regionScaleX = this.width / this.region.originalWidth * this.scaleX; + var regionScaleY = this.height / this.region.originalHeight * this.scaleY; + var localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + var localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + var localX2 = localX + this.region.width * regionScaleX; + var localY2 = localY + this.region.height * regionScaleY; + var radians = this.rotation * Math.PI / 180; + var cos = Math.cos(radians); + var sin = Math.sin(radians); + var localXCos = localX * cos + this.x; + var localXSin = localX * sin; + var localYCos = localY * cos + this.y; + var localYSin = localY * sin; + var localX2Cos = localX2 * cos + this.x; + var localX2Sin = localX2 * sin; + var localY2Cos = localY2 * cos + this.y; + var localY2Sin = localY2 * sin; + var offset = this.offset; + offset[RegionAttachment.OX1] = localXCos - localYSin; + offset[RegionAttachment.OY1] = localYCos + localXSin; + offset[RegionAttachment.OX2] = localXCos - localY2Sin; + offset[RegionAttachment.OY2] = localY2Cos + localXSin; + offset[RegionAttachment.OX3] = localX2Cos - localY2Sin; + offset[RegionAttachment.OY3] = localY2Cos + localX2Sin; + offset[RegionAttachment.OX4] = localX2Cos - localYSin; + offset[RegionAttachment.OY4] = localYCos + localX2Sin; + }; + RegionAttachment.prototype.setRegion = function (region) { + this.region = region; + var uvs = this.uvs; + if (region.rotate) { + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + uvs[0] = region.u2; + uvs[1] = region.v2; + } + else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + }; + RegionAttachment.prototype.computeWorldVertices = function (bone, worldVertices, offset, stride) { + var vertexOffset = this.offset; + var x = bone.worldX, y = bone.worldY; + var a = bone.a, b = bone.b, c = bone.c, d = bone.d; + var offsetX = 0, offsetY = 0; + offsetX = vertexOffset[RegionAttachment.OX1]; + offsetY = vertexOffset[RegionAttachment.OY1]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX2]; + offsetY = vertexOffset[RegionAttachment.OY2]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX3]; + offsetY = vertexOffset[RegionAttachment.OY3]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[RegionAttachment.OX4]; + offsetY = vertexOffset[RegionAttachment.OY4]; + worldVertices[offset] = offsetX * a + offsetY * b + x; + worldVertices[offset + 1] = offsetX * c + offsetY * d + y; + }; + return RegionAttachment; + }(spine.Attachment)); + RegionAttachment.OX1 = 0; + RegionAttachment.OY1 = 1; + RegionAttachment.OX2 = 2; + RegionAttachment.OY2 = 3; + RegionAttachment.OX3 = 4; + RegionAttachment.OY3 = 5; + RegionAttachment.OX4 = 6; + RegionAttachment.OY4 = 7; + RegionAttachment.X1 = 0; + RegionAttachment.Y1 = 1; + RegionAttachment.C1R = 2; + RegionAttachment.C1G = 3; + RegionAttachment.C1B = 4; + RegionAttachment.C1A = 5; + RegionAttachment.U1 = 6; + RegionAttachment.V1 = 7; + RegionAttachment.X2 = 8; + RegionAttachment.Y2 = 9; + RegionAttachment.C2R = 10; + RegionAttachment.C2G = 11; + RegionAttachment.C2B = 12; + RegionAttachment.C2A = 13; + RegionAttachment.U2 = 14; + RegionAttachment.V2 = 15; + RegionAttachment.X3 = 16; + RegionAttachment.Y3 = 17; + RegionAttachment.C3R = 18; + RegionAttachment.C3G = 19; + RegionAttachment.C3B = 20; + RegionAttachment.C3A = 21; + RegionAttachment.U3 = 22; + RegionAttachment.V3 = 23; + RegionAttachment.X4 = 24; + RegionAttachment.Y4 = 25; + RegionAttachment.C4R = 26; + RegionAttachment.C4G = 27; + RegionAttachment.C4B = 28; + RegionAttachment.C4A = 29; + RegionAttachment.U4 = 30; + RegionAttachment.V4 = 31; + spine.RegionAttachment = RegionAttachment; +})(spine || (spine = {})); +var spine; +(function (spine) { + var JitterEffect = (function () { + function JitterEffect(jitterX, jitterY) { + this.jitterX = 0; + this.jitterY = 0; + this.jitterX = jitterX; + this.jitterY = jitterY; + } + JitterEffect.prototype.begin = function (skeleton) { + }; + JitterEffect.prototype.transform = function (position, uv, light, dark) { + position.x += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + position.y += spine.MathUtils.randomTriangular(-this.jitterX, this.jitterY); + }; + JitterEffect.prototype.end = function () { + }; + return JitterEffect; + }()); + spine.JitterEffect = JitterEffect; +})(spine || (spine = {})); +var spine; +(function (spine) { + var SwirlEffect = (function () { + function SwirlEffect(radius) { + this.centerX = 0; + this.centerY = 0; + this.radius = 0; + this.angle = 0; + this.worldX = 0; + this.worldY = 0; + this.radius = radius; + } + SwirlEffect.prototype.begin = function (skeleton) { + this.worldX = skeleton.x + this.centerX; + this.worldY = skeleton.y + this.centerY; + }; + SwirlEffect.prototype.transform = function (position, uv, light, dark) { + var radAngle = this.angle * spine.MathUtils.degreesToRadians; + var x = position.x - this.worldX; + var y = position.y - this.worldY; + var dist = Math.sqrt(x * x + y * y); + if (dist < this.radius) { + var theta = SwirlEffect.interpolation.apply(0, radAngle, (this.radius - dist) / this.radius); + var cos = Math.cos(theta); + var sin = Math.sin(theta); + position.x = cos * x - sin * y + this.worldX; + position.y = sin * x + cos * y + this.worldY; + } + }; + SwirlEffect.prototype.end = function () { + }; + return SwirlEffect; + }()); + SwirlEffect.interpolation = new spine.PowOut(2); + spine.SwirlEffect = SwirlEffect; })(spine || (spine = {})); - -var sp = sp || {}; -sp.spine = spine; From bf393b9856e86fc3154aa9e9ebf7b2376385a988 Mon Sep 17 00:00:00 2001 From: drelaptop Date: Tue, 10 Apr 2018 18:13:21 +0800 Subject: [PATCH 56/65] run success, but effect wrong --- extensions/spine/CCSkeleton.js | 4 +++- extensions/spine/CCSkeletonCanvasRenderCmd.js | 5 ++++- extensions/spine/CCSkeletonWebGLRenderCmd.js | 13 ++++++++++--- extensions/spine/Spine.js | 3 +++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/extensions/spine/CCSkeleton.js b/extensions/spine/CCSkeleton.js index 0f0d3ebdf3..0ab0ad2b72 100644 --- a/extensions/spine/CCSkeleton.js +++ b/extensions/spine/CCSkeleton.js @@ -228,7 +228,9 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ var attachment = slot.attachment; if (!attachment || !(attachment instanceof spine.RegionAttachment)) continue; - vertices = attachment.updateWorldVertices(slot, false); + // 3.5 vertices = attachment.updateWorldVertices(slot, false); + vertices = spine.Utils.setArraySize(new Array(), 8, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 8); minX = Math.min(minX, vertices[VERTEX.X1] * scaleX, vertices[VERTEX.X4] * scaleX, vertices[VERTEX.X2] * scaleX, vertices[VERTEX.X3] * scaleX); minY = Math.min(minY, vertices[VERTEX.Y1] * scaleY, vertices[VERTEX.Y4] * scaleY, vertices[VERTEX.Y2] * scaleY, vertices[VERTEX.Y3] * scaleY); maxX = Math.max(maxX, vertices[VERTEX.X1] * scaleX, vertices[VERTEX.X4] * scaleX, vertices[VERTEX.X2] * scaleX, vertices[VERTEX.X3] * scaleX); diff --git a/extensions/spine/CCSkeletonCanvasRenderCmd.js b/extensions/spine/CCSkeletonCanvasRenderCmd.js index 1348ba920e..96de903a55 100644 --- a/extensions/spine/CCSkeletonCanvasRenderCmd.js +++ b/extensions/spine/CCSkeletonCanvasRenderCmd.js @@ -87,6 +87,7 @@ proto.rendering = function (wrapper, scaleX, scaleY) { } // Bone origins. + // FIXME: point position wrong, might due to scale drawingUtil.setPointSize(4); drawingUtil.setDrawColor(0, 0, 255, 255); // Root bone is blue. @@ -114,7 +115,9 @@ proto._updateRegionAttachmentSlot = function (attachment, slot, points) { if (!points) return; - var vertices = attachment.updateWorldVertices(slot, false); + // 3.5 var vertices = attachment.updateWorldVertices(slot, false); + var vertices = spine.Utils.setArraySize(new Array(), 8, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 8); var VERTEX = spine.RegionAttachment; points.length = 0; points.push(cc.p(vertices[VERTEX.X1], vertices[VERTEX.Y1])); diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js index bbe4cd805d..6204b12bb5 100644 --- a/extensions/spine/CCSkeletonWebGLRenderCmd.js +++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js @@ -233,7 +233,11 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph nodeG = nodeColor.g, nodeB = nodeColor.b, nodeA = this._displayedOpacity; - var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); + // 3.5 var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); + // FIXME: lose premultipliedAlpha? + var vertices = spine.Utils.setArraySize(new Array(), 8, 0); + attachment.computeWorldVertices(slot.bone, vertices, 0, 8); + var wt = this._worldTransform, wa = wt.a, wb = wt.b, wc = wt.c, wd = wt.d, wx = wt.tx, wy = wt.ty, @@ -280,14 +284,17 @@ proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, wx = wt.tx, wy = wt.ty, z = this._node.vertexZ; // get the vertex data - var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); + // 3.5 var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); + var verticesLength = attachment.worldVerticesLength; + var vertices = spine.Utils.setArraySize(new Array(), verticesLength, 0); + attachment.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); var offset = vertexDataOffset; var nodeColor = this._displayedColor; var nodeR = nodeColor.r, nodeG = nodeColor.g, nodeB = nodeColor.b, nodeA = this._displayedOpacity; - for (var i = 0, n = vertices.length; i < n; i += 8) { + for (var i = 0, n = vertices.length; i < n; i += 2) { var vx = vertices[i], vy = vertices[i + 1]; var x = vx * wa + vy * wb + wx, diff --git a/extensions/spine/Spine.js b/extensions/spine/Spine.js index b4ffec4b15..e7c0d894ea 100644 --- a/extensions/spine/Spine.js +++ b/extensions/spine/Spine.js @@ -6453,3 +6453,6 @@ var spine; SwirlEffect.interpolation = new spine.PowOut(2); spine.SwirlEffect = SwirlEffect; })(spine || (spine = {})); + +var sp = sp || {}; +sp.spine = spine; From 72e75f3e46747f0462616d57f076d88de0e48b48 Mon Sep 17 00:00:00 2001 From: drelaptop Date: Thu, 12 Apr 2018 10:08:05 +0800 Subject: [PATCH 57/65] adapts uvs --- extensions/spine/CCSkeleton.js | 5 ++- extensions/spine/CCSkeletonCanvasRenderCmd.js | 11 +++---- extensions/spine/CCSkeletonWebGLRenderCmd.js | 32 +++++++++++-------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/extensions/spine/CCSkeleton.js b/extensions/spine/CCSkeleton.js index 0ab0ad2b72..1317a31ffb 100644 --- a/extensions/spine/CCSkeleton.js +++ b/extensions/spine/CCSkeleton.js @@ -56,7 +56,10 @@ sp.ATTACHMENT_TYPE = { REGION: 0, BOUNDING_BOX: 1, MESH: 2, - SKINNED_MESH:3 + SKINNED_MESH:3, + PATH:4, + POINT:5, + CLIPPING:6 }; var spine = sp.spine; diff --git a/extensions/spine/CCSkeletonCanvasRenderCmd.js b/extensions/spine/CCSkeletonCanvasRenderCmd.js index 96de903a55..285eb463b7 100644 --- a/extensions/spine/CCSkeletonCanvasRenderCmd.js +++ b/extensions/spine/CCSkeletonCanvasRenderCmd.js @@ -115,15 +115,14 @@ proto._updateRegionAttachmentSlot = function (attachment, slot, points) { if (!points) return; - // 3.5 var vertices = attachment.updateWorldVertices(slot, false); var vertices = spine.Utils.setArraySize(new Array(), 8, 0); - attachment.computeWorldVertices(slot.bone, vertices, 0, 8); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); var VERTEX = spine.RegionAttachment; points.length = 0; - points.push(cc.p(vertices[VERTEX.X1], vertices[VERTEX.Y1])); - points.push(cc.p(vertices[VERTEX.X4], vertices[VERTEX.Y4])); - points.push(cc.p(vertices[VERTEX.X3], vertices[VERTEX.Y3])); - points.push(cc.p(vertices[VERTEX.X2], vertices[VERTEX.Y2])); + points.push(cc.p(vertices[VERTEX.OX1], vertices[VERTEX.OY1])); + points.push(cc.p(vertices[VERTEX.OX4], vertices[VERTEX.OY4])); + points.push(cc.p(vertices[VERTEX.OX3], vertices[VERTEX.OY3])); + points.push(cc.p(vertices[VERTEX.OX2], vertices[VERTEX.OY2])); }; proto._createChildFormSkeletonData = function () { diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js index 6204b12bb5..323eb583e4 100644 --- a/extensions/spine/CCSkeletonWebGLRenderCmd.js +++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js @@ -234,9 +234,12 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph nodeB = nodeColor.b, nodeA = this._displayedOpacity; // 3.5 var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); - // FIXME: lose premultipliedAlpha? + // FIXME: lose premultipliedAlpha? alpha impl innner, "vertices, 0, 8);" -> "vertices, 0, 2);" var vertices = spine.Utils.setArraySize(new Array(), 8, 0); - attachment.computeWorldVertices(slot.bone, vertices, 0, 8); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); + + var uvs = attachment.uvs; + var color = attachment.color; var wt = this._worldTransform, wa = wt.a, wb = wt.b, wc = wt.c, wd = wt.d, @@ -248,21 +251,21 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph // using two angles : (0, 1, 2) & (0, 2, 3) for (var i = 0; i < 6; i++) { var srcIdx = i < 4 ? i % 3 : i - 2; - var vx = vertices[srcIdx * 8], - vy = vertices[srcIdx * 8 + 1]; + var vx = vertices[srcIdx * 2], + vy = vertices[srcIdx * 2 + 1]; var x = vx * wa + vy * wc + wx, y = vx * wb + vy * wd + wy; - var r = vertices[srcIdx * 8 + 2] * nodeR, - g = vertices[srcIdx * 8 + 3] * nodeG, - b = vertices[srcIdx * 8 + 4] * nodeB, - a = vertices[srcIdx * 8 + 5] * nodeA; + var r = color.r * nodeR, + g = color.g * nodeG, + b = color.b * nodeB, + a = color.a * nodeA; var color = ((a<<24) | (b<<16) | (g<<8) | r); f32buffer[offset] = x; f32buffer[offset + 1] = y; f32buffer[offset + 2] = z; ui32buffer[offset + 3] = color; - f32buffer[offset + 4] = vertices[srcIdx * 8 + 6]; - f32buffer[offset + 5] = vertices[srcIdx * 8 + 7]; + f32buffer[offset + 4] = uvs[srcIdx * 2]; + f32buffer[offset + 5] = uvs[srcIdx * 2 + 1]; offset += 6; } @@ -270,10 +273,10 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph // return the quad points info if debug slot enabled var VERTEX = spine.RegionAttachment; return [ - cc.p(vertices[VERTEX.X1], vertices[VERTEX.Y1]), - cc.p(vertices[VERTEX.X2], vertices[VERTEX.Y2]), - cc.p(vertices[VERTEX.X3], vertices[VERTEX.Y3]), - cc.p(vertices[VERTEX.X4], vertices[VERTEX.Y4]) + cc.p(vertices[VERTEX.OX1], vertices[VERTEX.OY1]), + cc.p(vertices[VERTEX.OX2], vertices[VERTEX.OY2]), + cc.p(vertices[VERTEX.OX3], vertices[VERTEX.OY3]), + cc.p(vertices[VERTEX.OX4], vertices[VERTEX.OY4]) ]; } }; @@ -285,6 +288,7 @@ proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, z = this._node.vertexZ; // get the vertex data // 3.5 var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); + // FIXME, NOT USED THIS FUNCTION? var verticesLength = attachment.worldVerticesLength; var vertices = spine.Utils.setArraySize(new Array(), verticesLength, 0); attachment.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); From fef59ea825c380a3412e94869059d19e6319f27d Mon Sep 17 00:00:00 2001 From: drelaptop Date: Thu, 12 Apr 2018 10:39:52 +0800 Subject: [PATCH 58/65] adapt region render color --- extensions/spine/CCSkeletonWebGLRenderCmd.js | 21 +++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js index 323eb583e4..e29a3c468a 100644 --- a/extensions/spine/CCSkeletonWebGLRenderCmd.js +++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js @@ -233,13 +233,20 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph nodeG = nodeColor.g, nodeB = nodeColor.b, nodeA = this._displayedOpacity; - // 3.5 var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); - // FIXME: lose premultipliedAlpha? alpha impl innner, "vertices, 0, 8);" -> "vertices, 0, 2);" + var vertices = spine.Utils.setArraySize(new Array(), 8, 0); attachment.computeWorldVertices(slot.bone, vertices, 0, 2); var uvs = attachment.uvs; - var color = attachment.color; + + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color; + var slotColor = slot.color; + var regionColor = attachment.color; + var alpha = skeletonColor.a * slotColor.a * regionColor.a; + var multiplier = premultipliedAlpha ? alpha : 1; + var colors = attachment.tempColor; + colors.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha); var wt = this._worldTransform, wa = wt.a, wb = wt.b, wc = wt.c, wd = wt.d, @@ -255,10 +262,10 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph vy = vertices[srcIdx * 2 + 1]; var x = vx * wa + vy * wc + wx, y = vx * wb + vy * wd + wy; - var r = color.r * nodeR, - g = color.g * nodeG, - b = color.b * nodeB, - a = color.a * nodeA; + var r = colors.r * nodeR, + g = colors.g * nodeG, + b = colors.b * nodeB, + a = colors.a * nodeA; var color = ((a<<24) | (b<<16) | (g<<8) | r); f32buffer[offset] = x; f32buffer[offset + 1] = y; From e14b5727b766d78222cceea422a0ac76e67940e2 Mon Sep 17 00:00:00 2001 From: drelaptop Date: Thu, 12 Apr 2018 11:18:30 +0800 Subject: [PATCH 59/65] adapt mesh render clolor --- extensions/spine/CCSkeletonWebGLRenderCmd.js | 34 ++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js index e29a3c468a..13a6946032 100644 --- a/extensions/spine/CCSkeletonWebGLRenderCmd.js +++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js @@ -239,6 +239,7 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph var uvs = attachment.uvs; + // get the colors data var skeleton = slot.bone.skeleton; var skeletonColor = skeleton.color; var slotColor = slot.color; @@ -246,7 +247,10 @@ proto._uploadRegionAttachmentData = function(attachment, slot, premultipliedAlph var alpha = skeletonColor.a * slotColor.a * regionColor.a; var multiplier = premultipliedAlpha ? alpha : 1; var colors = attachment.tempColor; - colors.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, skeletonColor.g * slotColor.g * regionColor.g * multiplier, skeletonColor.b * slotColor.b * regionColor.b * multiplier, alpha); + colors.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier, + skeletonColor.g * slotColor.g * regionColor.g * multiplier, + skeletonColor.b * slotColor.b * regionColor.b * multiplier, + alpha); var wt = this._worldTransform, wa = wt.a, wb = wt.b, wc = wt.c, wd = wt.d, @@ -294,11 +298,23 @@ proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, wx = wt.tx, wy = wt.ty, z = this._node.vertexZ; // get the vertex data - // 3.5 var vertices = attachment.updateWorldVertices(slot, premultipliedAlpha); - // FIXME, NOT USED THIS FUNCTION? var verticesLength = attachment.worldVerticesLength; var vertices = spine.Utils.setArraySize(new Array(), verticesLength, 0); attachment.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + + var uvs = attachment.uvs; + + // get the colors data + var skeleton = slot.bone.skeleton; + var skeletonColor = skeleton.color, slotColor = slot.color, meshColor = attachment.color; + var alpha = skeletonColor.a * slotColor.a * meshColor.a; + var multiplier = premultipliedAlpha ? alpha : 1; + var colors = attachment.tempColor; + colors.set(skeletonColor.r * slotColor.r * meshColor.r * multiplier, + skeletonColor.g * slotColor.g * meshColor.g * multiplier, + skeletonColor.b * slotColor.b * meshColor.b * multiplier, + alpha); + var offset = vertexDataOffset; var nodeColor = this._displayedColor; var nodeR = nodeColor.r, @@ -310,18 +326,18 @@ proto._uploadMeshAttachmentData = function(attachment, slot, premultipliedAlpha, vy = vertices[i + 1]; var x = vx * wa + vy * wb + wx, y = vx * wc + vy * wd + wy; - var r = vertices[i + 2] * nodeR, - g = vertices[i + 3] * nodeG, - b = vertices[i + 4] * nodeB, - a = vertices[i + 5] * nodeA; + var r = colors.r * nodeR, + g = colors.g * nodeG, + b = colors.b * nodeB, + a = colors.a * nodeA; var color = ((a<<24) | (b<<16) | (g<<8) | r); f32buffer[offset] = x; f32buffer[offset + 1] = y; f32buffer[offset + 2] = z; ui32buffer[offset + 3] = color; - f32buffer[offset + 4] = vertices[i + 6]; - f32buffer[offset + 5] = vertices[i + 7]; + f32buffer[offset + 4] = uvs[i]; + f32buffer[offset + 5] = uvs[i + 1]; offset += 6; } }; From 7eb4663aa522edf8254bec60fa99278c7cd3b381 Mon Sep 17 00:00:00 2001 From: drelaptop Date: Thu, 12 Apr 2018 11:33:14 +0800 Subject: [PATCH 60/65] change version number --- cocos2d/core/platform/CCConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/core/platform/CCConfig.js b/cocos2d/core/platform/CCConfig.js index ceeddbf5d8..b4795155ed 100644 --- a/cocos2d/core/platform/CCConfig.js +++ b/cocos2d/core/platform/CCConfig.js @@ -31,7 +31,7 @@ * @type {String} * @name cc.ENGINE_VERSION */ -window["CocosEngine"] = cc.ENGINE_VERSION = "Cocos2d-JS v3.16"; +window["CocosEngine"] = cc.ENGINE_VERSION = "Cocos2d-JS v3.17"; /** *

From 4b19b786845f549d79948e746b51d20a5289e1ef Mon Sep 17 00:00:00 2001 From: drelaptop Date: Thu, 12 Apr 2018 14:36:05 +0800 Subject: [PATCH 61/65] fix canvas draw point error --- cocos2d/core/CCDrawingPrimitivesCanvas.js | 15 +++++---------- extensions/spine/CCSkeletonCanvasRenderCmd.js | 5 ++--- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/cocos2d/core/CCDrawingPrimitivesCanvas.js b/cocos2d/core/CCDrawingPrimitivesCanvas.js index ce4c914a85..f94b4ca297 100644 --- a/cocos2d/core/CCDrawingPrimitivesCanvas.js +++ b/cocos2d/core/CCDrawingPrimitivesCanvas.js @@ -56,11 +56,9 @@ cc.DrawingPrimitiveCanvas = cc.Class.extend(/** @lends cc.DrawingPrimitiveCanvas if (!size) { size = 1; } - var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); - var newPoint = cc.p(point.x * locScaleX, point.y * locScaleY); var ctx = this._renderContext.getContext(); ctx.beginPath(); - ctx.arc(newPoint.x, -newPoint.y, size * locScaleX, 0, Math.PI * 2, false); + ctx.arc(point.x, -point.y, size, 0, Math.PI * 2, false); ctx.closePath(); ctx.fill(); }, @@ -79,11 +77,11 @@ cc.DrawingPrimitiveCanvas = cc.Class.extend(/** @lends cc.DrawingPrimitiveCanvas if (!size) { size = 1; } - var locContext = this._renderContext.getContext(),locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); + var locContext = this._renderContext.getContext(); locContext.beginPath(); for (var i = 0, len = points.length; i < len; i++) - locContext.arc(points[i].x * locScaleX, -points[i].y * locScaleY, size * locScaleX, 0, Math.PI * 2, false); + locContext.arc(points[i].x, -points[i].y, size, 0, Math.PI * 2, false); locContext.closePath(); locContext.fill(); }, @@ -95,7 +93,7 @@ cc.DrawingPrimitiveCanvas = cc.Class.extend(/** @lends cc.DrawingPrimitiveCanvas * @param {cc.Point} destination */ drawLine:function (origin, destination) { - var locContext = this._renderContext.getContext(), locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); + var locContext = this._renderContext.getContext(); locContext.beginPath(); locContext.moveTo(origin.x , -origin.y ); locContext.lineTo(destination.x, -destination.y ); @@ -151,7 +149,6 @@ cc.DrawingPrimitiveCanvas = cc.Class.extend(/** @lends cc.DrawingPrimitiveCanvas throw new Error("Polygon's point must greater than 2"); var firstPoint = vertices[0], locContext = this._renderContext.getContext(); - var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); locContext.beginPath(); locContext.moveTo(firstPoint.x , -firstPoint.y ); for (var i = 1, len = vertices.length; i < len; i++) @@ -189,7 +186,6 @@ cc.DrawingPrimitiveCanvas = cc.Class.extend(/** @lends cc.DrawingPrimitiveCanvas drawCircle: function (center, radius, angle, segments, drawLineToCenter) { drawLineToCenter = drawLineToCenter || false; var locContext = this._renderContext.getContext(); - var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY(); locContext.beginPath(); var endAngle = angle - Math.PI * 2; locContext.arc(0 | (center.x ), 0 | -(center.y ), radius , -angle, -endAngle, false); @@ -379,7 +375,6 @@ cc.DrawingPrimitiveCanvas = cc.Class.extend(/** @lends cc.DrawingPrimitiveCanvas drawColorBall:function (ctx, radius, color) { var wrapper = ctx || this._renderContext; var context = wrapper.getContext(); - radius *= cc.view.getScaleX(); var colorStr = "rgba(" +(0|color.r) + "," + (0|color.g) + "," + (0|color.b); var subRadius = radius / 10; @@ -432,6 +427,6 @@ cc.DrawingPrimitiveCanvas = cc.Class.extend(/** @lends cc.DrawingPrimitiveCanvas * @param {Number} width */ setLineWidth:function (width) { - this._renderContext.getContext().lineWidth = width * cc.view.getScaleX(); + this._renderContext.getContext().lineWidth = width; } }); \ No newline at end of file diff --git a/extensions/spine/CCSkeletonCanvasRenderCmd.js b/extensions/spine/CCSkeletonCanvasRenderCmd.js index 285eb463b7..f31924ec19 100644 --- a/extensions/spine/CCSkeletonCanvasRenderCmd.js +++ b/extensions/spine/CCSkeletonCanvasRenderCmd.js @@ -87,13 +87,12 @@ proto.rendering = function (wrapper, scaleX, scaleY) { } // Bone origins. - // FIXME: point position wrong, might due to scale - drawingUtil.setPointSize(4); + var pointSize = 4; drawingUtil.setDrawColor(0, 0, 255, 255); // Root bone is blue. for (i = 0, n = locSkeleton.bones.length; i < n; i++) { bone = locSkeleton.bones[i]; - drawingUtil.drawPoint({x: bone.worldX, y: bone.worldY}); + drawingUtil.drawPoint({x: bone.worldX, y: bone.worldY}, pointSize); if (i === 0) drawingUtil.setDrawColor(0, 255, 0, 255); } From d26ddb24c068df59972e1c0f11f23f16c97ebc4a Mon Sep 17 00:00:00 2001 From: drelaptop Date: Thu, 12 Apr 2018 14:55:26 +0800 Subject: [PATCH 62/65] remove unused struct --- extensions/spine/CCSkeleton.js | 42 ++++------------------------------ 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/extensions/spine/CCSkeleton.js b/extensions/spine/CCSkeleton.js index 1317a31ffb..97a99f4edb 100644 --- a/extensions/spine/CCSkeleton.js +++ b/extensions/spine/CCSkeleton.js @@ -31,37 +31,6 @@ */ var sp = sp || {}; -/** - * The vertex index of spine. - * @constant - * @type {{X1: number, Y1: number, X2: number, Y2: number, X3: number, Y3: number, X4: number, Y4: number}} - */ -sp.VERTEX_INDEX = { - X1: 0, - Y1: 1, - X2: 2, - Y2: 3, - X3: 4, - Y3: 5, - X4: 6, - Y4: 7 -}; - -/** - * The attachment type of spine. It contains three type: REGION(0), BOUNDING_BOX(1), MESH(2) and SKINNED_MESH. - * @constant - * @type {{REGION: number, BOUNDING_BOX: number, REGION_SEQUENCE: number, MESH: number}} - */ -sp.ATTACHMENT_TYPE = { - REGION: 0, - BOUNDING_BOX: 1, - MESH: 2, - SKINNED_MESH:3, - PATH:4, - POINT:5, - CLIPPING:6 -}; - var spine = sp.spine; /** @@ -231,13 +200,12 @@ sp.Skeleton = cc.Node.extend(/** @lends sp.Skeleton# */{ var attachment = slot.attachment; if (!attachment || !(attachment instanceof spine.RegionAttachment)) continue; - // 3.5 vertices = attachment.updateWorldVertices(slot, false); vertices = spine.Utils.setArraySize(new Array(), 8, 0); - attachment.computeWorldVertices(slot.bone, vertices, 0, 8); - minX = Math.min(minX, vertices[VERTEX.X1] * scaleX, vertices[VERTEX.X4] * scaleX, vertices[VERTEX.X2] * scaleX, vertices[VERTEX.X3] * scaleX); - minY = Math.min(minY, vertices[VERTEX.Y1] * scaleY, vertices[VERTEX.Y4] * scaleY, vertices[VERTEX.Y2] * scaleY, vertices[VERTEX.Y3] * scaleY); - maxX = Math.max(maxX, vertices[VERTEX.X1] * scaleX, vertices[VERTEX.X4] * scaleX, vertices[VERTEX.X2] * scaleX, vertices[VERTEX.X3] * scaleX); - maxY = Math.max(maxY, vertices[VERTEX.Y1] * scaleY, vertices[VERTEX.Y4] * scaleY, vertices[VERTEX.Y2] * scaleY, vertices[VERTEX.Y3] * scaleY); + attachment.computeWorldVertices(slot.bone, vertices, 0, 2); + minX = Math.min(minX, vertices[VERTEX.OX1] * scaleX, vertices[VERTEX.OX4] * scaleX, vertices[VERTEX.OX2] * scaleX, vertices[VERTEX.OX3] * scaleX); + minY = Math.min(minY, vertices[VERTEX.OY1] * scaleY, vertices[VERTEX.OY4] * scaleY, vertices[VERTEX.OY2] * scaleY, vertices[VERTEX.OY3] * scaleY); + maxX = Math.max(maxX, vertices[VERTEX.OX1] * scaleX, vertices[VERTEX.OX4] * scaleX, vertices[VERTEX.OX2] * scaleX, vertices[VERTEX.OX3] * scaleX); + maxY = Math.max(maxY, vertices[VERTEX.OY1] * scaleY, vertices[VERTEX.OY4] * scaleY, vertices[VERTEX.OY2] * scaleY, vertices[VERTEX.OY3] * scaleY); } var position = this.getPosition(); return cc.rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY); From adeefef3a840e0ddb9529cf9038616fcc4fcdde5 Mon Sep 17 00:00:00 2001 From: drelaptop Date: Fri, 13 Apr 2018 14:38:47 +0800 Subject: [PATCH 63/65] avoid vertex data overflow --- extensions/spine/CCSkeletonWebGLRenderCmd.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/spine/CCSkeletonWebGLRenderCmd.js b/extensions/spine/CCSkeletonWebGLRenderCmd.js index 13a6946032..535e4c0ac5 100644 --- a/extensions/spine/CCSkeletonWebGLRenderCmd.js +++ b/extensions/spine/CCSkeletonWebGLRenderCmd.js @@ -91,8 +91,10 @@ proto.uploadData = function (f32buffer, ui32buffer, vertexDataOffset){ this._currTexture = regionTextureAtlas.texture.getRealTexture(); var batchBroken = cc.renderer._updateBatchedInfo(this._currTexture, this._getBlendFunc(slot.data.blendMode, premultiAlpha), this._glProgramState); + // keep the same logic with RendererWebGL.js, avoid vertex data overflow + var uploadAll = vertexDataOffset / 6 + vertCount > (cc.BATCH_VERTEX_COUNT - 200) * 0.5; // Broken for vertex data overflow - if (!batchBroken && vertexDataOffset + vertCount * 6 > f32buffer.length) { + if (!batchBroken && uploadAll) { // render the cached data cc.renderer._batchRendering(); batchBroken = true; From fe148d3b7ba2b35ce8c206feb653ae8d5557301b Mon Sep 17 00:00:00 2001 From: Shun Lin Date: Mon, 25 Feb 2019 18:39:03 +0800 Subject: [PATCH 64/65] Update the latest status of Cocos2d-html5 Now Cocos2d-html5 is the renderer engine of Cocos Creator. --- README.mdown | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/README.mdown b/README.mdown index 57823c8723..843c669833 100644 --- a/README.mdown +++ b/README.mdown @@ -5,36 +5,18 @@ Cocos2d-html5 It incorporates the same high level api as “Cocos2d JS-binding engine” and compatible with Cocos2d-X. It currently supports canvas and WebGL renderer. +#### Cocos2d-html5 has evolved to Cocos Creator, new generation of Cocos game engine with a full featured editor and content creation friendly workflow. The latest repository is maintained in here [Engine of Cocos Creator][9]. + Cross Platform ------------- * Popular browsers: Chrome 14+, Safari 5.0+, IE9+, Firefox 3.5+. - * Mobile platforms: coming soon. + * Mobile platforms: Mobile browsers,Facebook Instant Games and Mini Games. * Native App: Same piece of code can run on "Cocos2d JS-Binding Engine" without or with little modification. Documentation ------------------ * Website: [www.cocos2d-x.org][3] - * API References: [http://www.cocos2d-x.org/wiki/Reference] [4] - - -Installing from [bower][8] (version >=3.4) ------------------- - -```shell -$ bower install cocos2d-html5 -``` - -Running the tests (version <3) ------------------- - -```shell -$ git clone git://github.com/cocos2d/cocos2d-html5.git -$ cd cocos2d-html5 -$ git submodule update --init -$ python -m SimpleHTTPServer -``` -... and then open a browser and go to `http://localhost:8000/tests` - + * Cocos Creator download: [Cocos Creator][10] Contact us ------------------ @@ -50,3 +32,5 @@ Contact us [6]: http://www.twitter.com/cocos2dhtml5 "http://www.twitter.com/cocos2dhtml5" [7]: http://t.sina.com.cn/cocos2dhtml5 "http://t.sina.com.cn/cocos2dhtml5" [8]: http://bower.io "http://bower.io" +[9]: https://github.com/cocos-creator/engine +[10]: http://cocos2d-x.org/download From c0324ad511b7e327a597d9a0d27e5a7d9f4fbc07 Mon Sep 17 00:00:00 2001 From: Jare Guo Date: Fri, 13 Mar 2020 17:27:56 +0800 Subject: [PATCH 65/65] Update README.mdown --- README.mdown | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.mdown b/README.mdown index 843c669833..3b13c27fac 100644 --- a/README.mdown +++ b/README.mdown @@ -5,7 +5,11 @@ Cocos2d-html5 It incorporates the same high level api as “Cocos2d JS-binding engine” and compatible with Cocos2d-X. It currently supports canvas and WebGL renderer. -#### Cocos2d-html5 has evolved to Cocos Creator, new generation of Cocos game engine with a full featured editor and content creation friendly workflow. The latest repository is maintained in here [Engine of Cocos Creator][9]. +------------- + +#### Cocos2d-html5 has evolved to [Cocos Creator][11], new generation of Cocos game engine with a full featured editor and content creation friendly workflow. It supports all major platforms allowing games to be quickly released for the web, iOS, Android, Windows, Mac, and various mini-game platforms. A pure JavaScript-developed engine runtime is available on the web and mini-game platforms for better performance and smaller packages. On other native platforms, C++ is used to implement the underlying framework, providing greater operational efficiency. The latest repository is maintained in here [Engine of Cocos Creator][9]. + +------------- Cross Platform ------------- @@ -34,3 +38,4 @@ Contact us [8]: http://bower.io "http://bower.io" [9]: https://github.com/cocos-creator/engine [10]: http://cocos2d-x.org/download +[11]: https://www.cocos.com/en/products#CocosCreator "https://www.cocos.com"