diff --git a/spine-cocos2d-objc/TwoColorTest.atlas b/spine-cocos2d-objc/TwoColorTest.atlas new file mode 100644 index 000000000..3f7ce242c --- /dev/null +++ b/spine-cocos2d-objc/TwoColorTest.atlas @@ -0,0 +1,13 @@ + +TwoColorTest.png +size: 512,512 +format: RGBA8888 +filter: Linear,Linear +repeat: none +squareWithBorder + rotate: false + xy: 2, 2 + size: 300, 300 + orig: 300, 300 + offset: 0, 0 + index: -1 diff --git a/spine-cocos2d-objc/TwoColorTest.json b/spine-cocos2d-objc/TwoColorTest.json new file mode 100644 index 000000000..830de2ea9 --- /dev/null +++ b/spine-cocos2d-objc/TwoColorTest.json @@ -0,0 +1,150 @@ +{ +"skeleton": { "hash": "+PGAjM+dGgrId6XMqdIJm8hlvRE", "spine": "3.6.09-beta", "width": 300, "height": 300, "images": "" }, +"bones": [ + { "name": "root", "x": -178.03, "y": 229.83 }, + { "name": "singleColorTint", "parent": "root", "x": -400 }, + { "name": "singleColorTint2", "parent": "root", "x": -400, "y": -383 }, + { "name": "twoColorTint", "parent": "root", "x": 800 }, + { "name": "twoColorTint2", "parent": "root", "x": 800, "y": -382 }, + { "name": "twoColorTint (blackOnly)", "parent": "root" }, + { "name": "twoColorTint (blackOnly)2", "parent": "root", "y": -391 }, + { "name": "twoColorTint (colorOnly)", "parent": "root", "x": 400 }, + { "name": "twoColorTint (colorOnly)2", "parent": "root", "x": 400, "y": -382 } +], +"slots": [ + { "name": "squareWithBorder", "bone": "singleColorTint", "attachment": "squareWithBorder" }, + { "name": "squareWithBorder7", "bone": "singleColorTint2", "attachment": "squareWithBorder" }, + { "name": "squareWithBorder2", "bone": "twoColorTint (blackOnly)", "dark": "000000", "attachment": "squareWithBorder" }, + { "name": "squareWithBorder8", "bone": "twoColorTint (blackOnly)2", "dark": "000000", "attachment": "squareWithBorder" }, + { "name": "squareWithBorder4", "bone": "twoColorTint (colorOnly)", "dark": "000000", "attachment": "squareWithBorder" }, + { "name": "squareWithBorder5", "bone": "twoColorTint (colorOnly)2", "dark": "000000", "attachment": "squareWithBorder" }, + { "name": "squareWithBorder3", "bone": "twoColorTint", "dark": "000000", "attachment": "squareWithBorder" }, + { "name": "squareWithBorder6", "bone": "twoColorTint2", "dark": "000000", "attachment": "squareWithBorder" } +], +"skins": { + "default": { + "squareWithBorder": { + "squareWithBorder": { "width": 300, "height": 300 } + }, + "squareWithBorder2": { + "squareWithBorder": { "width": 300, "height": 300 } + }, + "squareWithBorder3": { + "squareWithBorder": { "width": 300, "height": 300 } + }, + "squareWithBorder4": { + "squareWithBorder": { "width": 300, "height": 300 } + }, + "squareWithBorder5": { + "squareWithBorder": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 150, -150, -150, -150, -197, 99, 183, 155 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 300, + "height": 300 + } + }, + "squareWithBorder6": { + "squareWithBorder": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 238, -200, -191, -60, -150, 150, 119, 111 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 300, + "height": 300 + } + }, + "squareWithBorder7": { + "squareWithBorder": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 210, -132, -150, -150, -150, 150, 124, 119 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 300, + "height": 300 + } + }, + "squareWithBorder8": { + "squareWithBorder": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 150, -150, -150, -150, -97, 58, 86, 62 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 300, + "height": 300 + } + } + } +}, +"animations": { + "animation": { + "slots": { + "squareWithBorder": { + "color": [ + { "time": 0, "color": "fffffffe" }, + { "time": 1, "color": "9e17b3fe" }, + { "time": 2, "color": "fffffffe" } + ] + }, + "squareWithBorder2": { + "twoColor": [ + { "time": 0, "light": "fffffffe", "dark": "000000" }, + { "time": 1, "light": "fffffffe", "dark": "ff0000" }, + { "time": 2, "light": "fffffffe", "dark": "000000" } + ] + }, + "squareWithBorder3": { + "twoColor": [ + { "time": 0, "light": "fffffffe", "dark": "000000" }, + { "time": 1, "light": "80ff00fe", "dark": "001cff" }, + { "time": 2, "light": "fffffffe", "dark": "000000" } + ] + }, + "squareWithBorder4": { + "twoColor": [ + { "time": 0, "light": "fffffffe", "dark": "000000" }, + { "time": 1, "light": "ffd300fe", "dark": "000000" }, + { "time": 2, "light": "fffffffe", "dark": "000000" } + ] + }, + "squareWithBorder5": { + "twoColor": [ + { "time": 0, "light": "fffffffe", "dark": "000000" }, + { "time": 1, "light": "ffd300fe", "dark": "000000" }, + { "time": 2, "light": "fffffffe", "dark": "000000" } + ] + }, + "squareWithBorder6": { + "twoColor": [ + { "time": 0, "light": "fffffffe", "dark": "000000" }, + { "time": 1, "light": "80ff00fe", "dark": "001cff" }, + { "time": 2, "light": "fffffffe", "dark": "000000" } + ] + }, + "squareWithBorder7": { + "color": [ + { "time": 0, "color": "fffffffe" }, + { "time": 1, "color": "9e17b3fe" }, + { "time": 2, "color": "fffffffe" } + ] + }, + "squareWithBorder8": { + "twoColor": [ + { "time": 0, "light": "fffffffe", "dark": "000000" }, + { "time": 1, "light": "fffffffe", "dark": "ff0000" }, + { "time": 2, "light": "fffffffe", "dark": "000000" } + ] + } + } + } +} +} \ No newline at end of file diff --git a/spine-cocos2d-objc/TwoColorTest.png b/spine-cocos2d-objc/TwoColorTest.png new file mode 100644 index 000000000..f78c2923b Binary files /dev/null and b/spine-cocos2d-objc/TwoColorTest.png differ diff --git a/spine-cocos2d-objc/example/SpineboyExample.m b/spine-cocos2d-objc/example/SpineboyExample.m index e8b108b33..af7f7adeb 100644 --- a/spine-cocos2d-objc/example/SpineboyExample.m +++ b/spine-cocos2d-objc/example/SpineboyExample.m @@ -36,6 +36,7 @@ + (CCScene*) scene { CCScene *scene = [CCScene node]; [scene addChild:[SpineboyExample node]]; + [scene setColorRGBA: [CCColor colorWithRed:1 green:0 blue:0]]; return scene; } @@ -43,11 +44,12 @@ self = [super init]; if (!self) return nil; - skeletonNode = [SkeletonAnimation skeletonWithFile:@"spineboy.json" atlasFile:@"spineboy.atlas" scale:0.6]; + skeletonNode = [SkeletonAnimation skeletonWithFile:@"TwoColorTest.json" atlasFile:@"TwoColorTest.atlas" scale:0.2]; [skeletonNode setMixFrom:@"walk" to:@"jump" duration:0.2f]; [skeletonNode setMixFrom:@"jump" to:@"run" duration:0.2f]; __weak SkeletonAnimation* node = skeletonNode; + skeletonNode.twoColorTint = true; skeletonNode.startListener = ^(spTrackEntry* entry) { const char* animationName = entry->animation->name; NSLog(@"%d start: %s", entry->trackIndex, animationName); @@ -68,18 +70,12 @@ NSLog(@"%d event: %s, %d, %f, %s", entry->trackIndex, event->data->name, event->intValue, event->floatValue, event->stringValue); }; - [skeletonNode setAnimationForTrack:0 name:@"walk" loop:YES]; - spTrackEntry* jumpEntry = [skeletonNode addAnimationForTrack:0 name:@"jump" loop:NO afterDelay:3]; - [skeletonNode addAnimationForTrack:0 name:@"run" loop:YES afterDelay:0]; - - [skeletonNode setListenerForEntry:jumpEntry onStart:^(spTrackEntry* entry) { - CCLOG(@"jumped!"); - }]; + [skeletonNode setAnimationForTrack:0 name:@"animation" loop:YES]; // [skeletonNode setAnimationForTrack:1 name:@"test" loop:YES]; CGSize windowSize = [[CCDirector sharedDirector] viewSize]; - [skeletonNode setPosition:ccp(windowSize.width / 2, 20)]; + [skeletonNode setPosition:ccp(windowSize.width / 2, windowSize.height / 2)]; [self addChild:skeletonNode]; self.userInteractionEnabled = YES; @@ -90,12 +86,7 @@ #if ( TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR ) - (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event { - if (!skeletonNode.debugBones) - skeletonNode.debugBones = true; - else if (skeletonNode.timeScale == 1) - skeletonNode.timeScale = 0.3f; - else - [[CCDirector sharedDirector] replaceScene:[GoblinsExample scene]]; + skeletonNode.twoColorTint = !skeletonNode.twoColorTint; } #endif diff --git a/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj b/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj index 66c7a676e..749a00a7e 100644 --- a/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj +++ b/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj @@ -34,6 +34,9 @@ 765A2EF61D7D7A08003FB779 /* goblins.atlas in Resources */ = {isa = PBXBuildFile; fileRef = 765A2EF41D7D7A08003FB779 /* goblins.atlas */; }; 765A2EF71D7D7A08003FB779 /* goblins.png in Resources */ = {isa = PBXBuildFile; fileRef = 765A2EF51D7D7A08003FB779 /* goblins.png */; }; 76BF7E071E66ED9C00485998 /* GLUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 76BF7E051E66ED9C00485998 /* GLUtils.c */; }; + 76BFBC301E78254F00675E2B /* TwoColorTest.atlas in Resources */ = {isa = PBXBuildFile; fileRef = 76BFBC2D1E78254F00675E2B /* TwoColorTest.atlas */; }; + 76BFBC311E78254F00675E2B /* TwoColorTest.json in Resources */ = {isa = PBXBuildFile; fileRef = 76BFBC2E1E78254F00675E2B /* TwoColorTest.json */; }; + 76BFBC321E78254F00675E2B /* TwoColorTest.png in Resources */ = {isa = PBXBuildFile; fileRef = 76BFBC2F1E78254F00675E2B /* TwoColorTest.png */; }; 76F28D161DEC810300CDE54D /* Animation.c in Sources */ = {isa = PBXBuildFile; fileRef = 76F28CF41DEC810200CDE54D /* Animation.c */; }; 76F28D171DEC810300CDE54D /* AnimationState.c in Sources */ = {isa = PBXBuildFile; fileRef = 76F28CF51DEC810300CDE54D /* AnimationState.c */; }; 76F28D181DEC810300CDE54D /* AnimationStateData.c in Sources */ = {isa = PBXBuildFile; fileRef = 76F28CF61DEC810300CDE54D /* AnimationStateData.c */; }; @@ -162,6 +165,9 @@ 765A2EF51D7D7A08003FB779 /* goblins.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = goblins.png; path = Resources/goblins.png; sourceTree = ""; }; 76BF7E051E66ED9C00485998 /* GLUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GLUtils.c; path = src/spine/GLUtils.c; sourceTree = ""; }; 76BF7E061E66ED9C00485998 /* GLUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GLUtils.h; path = src/spine/GLUtils.h; sourceTree = ""; }; + 76BFBC2D1E78254F00675E2B /* TwoColorTest.atlas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TwoColorTest.atlas; sourceTree = ""; }; + 76BFBC2E1E78254F00675E2B /* TwoColorTest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = TwoColorTest.json; sourceTree = ""; }; + 76BFBC2F1E78254F00675E2B /* TwoColorTest.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TwoColorTest.png; sourceTree = ""; }; 76F28CF41DEC810200CDE54D /* Animation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Animation.c; path = "../spine-c/spine-c/src/spine/Animation.c"; sourceTree = ""; }; 76F28CF51DEC810300CDE54D /* AnimationState.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AnimationState.c; path = "../spine-c/spine-c/src/spine/AnimationState.c"; sourceTree = ""; }; 76F28CF61DEC810300CDE54D /* AnimationStateData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AnimationStateData.c; path = "../spine-c/spine-c/src/spine/AnimationStateData.c"; sourceTree = ""; }; @@ -338,6 +344,9 @@ 43C32867170B0C7F004A9460 /* Resources */ = { isa = PBXGroup; children = ( + 76BFBC2D1E78254F00675E2B /* TwoColorTest.atlas */, + 76BFBC2E1E78254F00675E2B /* TwoColorTest.json */, + 76BFBC2F1E78254F00675E2B /* TwoColorTest.png */, 765A2EF41D7D7A08003FB779 /* goblins.atlas */, 765A2EF51D7D7A08003FB779 /* goblins.png */, 76F5BD9C1D2BDE1C005917E5 /* raptor.atlas */, @@ -517,14 +526,17 @@ 43C3287D170B0DBE004A9460 /* Default-568h@2x.png in Resources */, 43C3287E170B0DBE004A9460 /* Default-Landscape~ipad.png in Resources */, 43C3287F170B0DBE004A9460 /* Default.png in Resources */, + 76BFBC321E78254F00675E2B /* TwoColorTest.png in Resources */, 76F5BDA31D2BDE1C005917E5 /* raptor.json in Resources */, 43C32880170B0DBE004A9460 /* Default@2x.png in Resources */, 765A2EF71D7D7A08003FB779 /* goblins.png in Resources */, 43C32881170B0DBE004A9460 /* Icon-72.png in Resources */, 76F5BDA41D2BDE1C005917E5 /* raptor.png in Resources */, 43C32882170B0DBE004A9460 /* Icon-Small-50.png in Resources */, + 76BFBC301E78254F00675E2B /* TwoColorTest.atlas in Resources */, 76F5BDA21D2BDE1C005917E5 /* raptor.atlas in Resources */, 43C32883170B0DBE004A9460 /* Icon-Small.png in Resources */, + 76BFBC311E78254F00675E2B /* TwoColorTest.json in Resources */, 43C32884170B0DBE004A9460 /* Icon-Small@2x.png in Resources */, 43C32885170B0DBE004A9460 /* Icon.png in Resources */, 76F5BDA71D2BDE1C005917E5 /* tank.png in Resources */, diff --git a/spine-cocos2d-objc/src/spine/GLUtils.c b/spine-cocos2d-objc/src/spine/GLUtils.c index b6ad4abd2..c95cf09bc 100644 --- a/spine-cocos2d-objc/src/spine/GLUtils.c +++ b/spine-cocos2d-objc/src/spine/GLUtils.c @@ -52,8 +52,6 @@ attribute vec4 a_position; attribute vec4 a_color; attribute vec4 a_color2; attribute vec2 a_texCoords; - -uniform mat4 transform; \n#ifdef GL_ES\n varying lowp vec4 v_light; @@ -63,14 +61,13 @@ varying mediump vec2 v_texCoord; varying vec4 v_light; varying vec4 v_dark; varying vec2 v_texCoord; - \n#endif\n void main() { v_light = a_color; v_dark = a_color2; v_texCoord = a_texCoords; - gl_Position = transform * a_position; + gl_Position = a_position; } ); @@ -89,7 +86,7 @@ void main() { vec4 texColor = texture2D(texture, v_texCoord); float alpha = texColor.a * v_light.a; gl_FragColor.a = alpha; - gl_FragColor.rgb = (1.0 - texColor.rgb) * v_dark.rgb * alpha + texColor.rgb * v_light.rgb; + gl_FragColor.rgb = (1.0 - texColor.rgb) * v_dark.rgb * alpha + texColor.rgb * v_light.rgb; } ); @@ -119,6 +116,10 @@ void spMesh_allocatePart(spMesh* mesh, spMeshPart* part, uint32_t numVertices, u part->numIndices = numIndices; part->startIndex = mesh->numAllocatedIndices; part->numVertices = numVertices; + part->textureHandle = textureHandle; + part->srcBlend = srcBlend; + part->dstBlend = dstBlend; + mesh->numAllocatedVertices += numVertices; mesh->numAllocatedIndices += numIndices; } @@ -194,6 +195,7 @@ spTwoColorBatcher* spTwoColorBatcher_create() { batcher->colorAttributeLocation = glGetAttribLocation(batcher->shader->program, "a_color"); batcher->color2AttributeLocation = glGetAttribLocation(batcher->shader->program, "a_color2"); batcher->texCoordsAttributeLocation = glGetAttribLocation(batcher->shader->program, "a_texCoords"); + batcher->textureUniformLocation = glGetUniformLocation(batcher->shader->program, "texture"); glGenBuffers(1, &batcher->vertexBufferHandle); glGenBuffers(1, &batcher->indexBufferHandle); @@ -204,12 +206,72 @@ spTwoColorBatcher* spTwoColorBatcher_create() { return batcher; } -void spTwoColorBatcher_add(spTwoColorBatcher* batcher, spMeshPart* mesh) { +void spTwoColorBatcher_add(spTwoColorBatcher* batcher, spMeshPart mesh) { + if (batcher->numVertices + mesh.numVertices > MAX_VERTICES || batcher->numIndices + mesh.numIndices > MAX_INDICES) { + spTwoColorBatcher_flush(batcher); + } + if (batcher->lastTextureHandle != mesh.textureHandle || batcher->lastSrcBlend != mesh.srcBlend || batcher->lastDstBlend != mesh.dstBlend) { + spTwoColorBatcher_flush(batcher); + } + + spVertex* vertices = &batcher->verticesBuffer[batcher->numVertices]; + unsigned short* indices = &batcher->indicesBuffer[batcher->numIndices]; + + memcpy(vertices, &mesh.mesh->vertices[mesh.startVertex], mesh.numVertices * sizeof(spVertex)); + unsigned short offset = (unsigned short)batcher->numVertices; + for (int i = batcher->numIndices, j = mesh.startIndex, n = batcher->numIndices + mesh.numIndices; i < n; i++, j++) { + indices[i] = mesh.mesh->indices[j] + offset; + } + + batcher->numIndices += mesh.numIndices; + batcher->numVertices += mesh.numVertices; + batcher->lastSrcBlend = mesh.srcBlend; + batcher->lastDstBlend = mesh.dstBlend; + batcher->lastTextureHandle = mesh.textureHandle; } void spTwoColorBatcher_flush(spTwoColorBatcher* batcher) { + if (batcher->numVertices == 0 || batcher->numIndices == 0) + return; + glUseProgram(batcher->shader->program); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, batcher->lastTextureHandle); + glUniform1i(batcher->textureUniformLocation, 0); + + glBlendFunc(batcher->lastSrcBlend, batcher->lastDstBlend); + + glBindBuffer(GL_ARRAY_BUFFER, batcher->vertexBufferHandle); + glBufferData(GL_ARRAY_BUFFER, sizeof(spVertex) * batcher->numVertices , batcher->verticesBuffer, GL_DYNAMIC_DRAW); + + glEnableVertexAttribArray(batcher->positionAttributeLocation); + glEnableVertexAttribArray(batcher->colorAttributeLocation); + glEnableVertexAttribArray(batcher->color2AttributeLocation); + glEnableVertexAttribArray(batcher->texCoordsAttributeLocation); + + glVertexAttribPointer(batcher->positionAttributeLocation, 4, GL_FLOAT, GL_FALSE, sizeof(spVertex), (GLvoid*)0); + glVertexAttribPointer(batcher->colorAttributeLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(spVertex), (GLvoid*)16); + glVertexAttribPointer(batcher->color2AttributeLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(spVertex), (GLvoid*)20); + glVertexAttribPointer(batcher->texCoordsAttributeLocation, 2, GL_FLOAT, GL_FALSE, sizeof(spVertex), (GLvoid*)24); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batcher->indexBufferHandle); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * batcher->numIndices, batcher->indicesBuffer, GL_STATIC_DRAW); + + glDrawElements(GL_TRIANGLES, (GLsizei)batcher->numIndices, GL_UNSIGNED_SHORT, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glUseProgram(0); + glBindTexture(GL_TEXTURE_2D, 0); + + batcher->numIndices = 0; + batcher->numVertices = 0; + batcher->lastSrcBlend = -1; + batcher->lastDstBlend = -1; + batcher->lastTextureHandle = -1; } void spDisposeTwoColorBatcher(spTwoColorBatcher* batcher) { diff --git a/spine-cocos2d-objc/src/spine/GLUtils.h b/spine-cocos2d-objc/src/spine/GLUtils.h index f13ff4595..81881a815 100644 --- a/spine-cocos2d-objc/src/spine/GLUtils.h +++ b/spine-cocos2d-objc/src/spine/GLUtils.h @@ -89,10 +89,15 @@ typedef struct spTwoColorBatcher { int32_t colorAttributeLocation; int32_t color2AttributeLocation; int32_t texCoordsAttributeLocation; + int32_t textureUniformLocation; + + uint32_t lastTextureHandle; + uint32_t lastSrcBlend; + uint32_t lastDstBlend; } spTwoColorBatcher; spTwoColorBatcher* spTwoColorBatcher_create(); -void spTwoColorBatcher_add(spTwoColorBatcher* batcher, spMeshPart* meshPart); +void spTwoColorBatcher_add(spTwoColorBatcher* batcher, spMeshPart meshPart); void spTwoColorBatcher_flush(spTwoColorBatcher* batcher); void spDisposeTwoColorBatcher(spTwoColorBatcher* batcher); diff --git a/spine-cocos2d-objc/src/spine/SkeletonRenderer.m b/spine-cocos2d-objc/src/spine/SkeletonRenderer.m index 2c693566b..03568d1b6 100644 --- a/spine-cocos2d-objc/src/spine/SkeletonRenderer.m +++ b/spine-cocos2d-objc/src/spine/SkeletonRenderer.m @@ -37,6 +37,7 @@ static const unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0}; static spTwoColorBatcher* batcher = 0; static spMesh* mesh = 0; +static bool handlerQueued = false; @interface SkeletonRenderer (Private) - (void) initialize:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData; @@ -66,9 +67,6 @@ static spMesh* mesh = 0; if (!batcher) { batcher = spTwoColorBatcher_create(); mesh = spMesh_create(64000, 32000); - [[CCDirector sharedDirector] addFrameCompletionHandler: ^{ - printf ("frame completed"); - }]; } _ownsSkeletonData = ownsSkeletonData; @@ -159,6 +157,20 @@ static spMesh* mesh = 0; } -(void)draw:(CCRenderer *)renderer transform:(const GLKMatrix4 *)transform { + // FIXME we need to clear the mesh parts at the end of the frame + // there's no general event mechanism to get notified on end frame + // that doesn't need to be re-added every frame. This is a poor man + // notification system that may break if the block is called on a + // separate thread. + if (!handlerQueued) { + [[CCDirector sharedDirector] addFrameCompletionHandler: ^{ + printf("clearing mesh\n"); + spMesh_clearParts(mesh); + handlerQueued = false; + }]; + handlerQueued = true; + } + CCColor* nodeColor = self.color; _skeleton->color.r = nodeColor.red; _skeleton->color.g = nodeColor.green; @@ -265,13 +277,41 @@ static spMesh* mesh = 0; spMeshPart meshPart; spMesh_allocatePart(mesh, &meshPart, verticesCount / 2, trianglesCount, self.texture.name, srcBlend, dstBlend); + spVertex* vertices = &meshPart.mesh->vertices[meshPart.startVertex]; + unsigned short* indices = &meshPart.mesh->indices[meshPart.startIndex]; + + for (int i = 0; i * 2 < verticesCount; i++, vertices++) { + CCVertex vertex; + vertex.position = GLKVector4Make(_worldVertices[i * 2], _worldVertices[i * 2 + 1], 0.0, 1.0); + vertex = CCVertexApplyTransform(vertex, transform); + vertices->x = vertex.position.x; + vertices->y = vertex.position.y; + vertices->z = vertex.position.z; + vertices->w = vertex.position.w; + vertices->color = ((int)(r * 255)) << 24 | ((int)(g * 255)) << 16 | ((int)(b * 255)) << 8 | ((int)(a * 255)); + vertices->color2 = ((int)(r * 255)) << 24 | ((int)(g * 255)) << 16 | ((int)(b * 255)) << 8 | ((int)(a * 255)); + vertices->u = uvs[i * 2]; + vertices->v = 1 - uvs[i * 2 + 1]; + } + + for (int j = 0; j < trianglesCount; j++, indices++) { + *indices = triangles[j]; + } + [renderer enqueueBlock:^{ - + spTwoColorBatcher_add(batcher, meshPart); } globalSortOrder:0 debugLabel: nil threadSafe: false]; } } } } + + if (self.twoColorTint) { + [renderer enqueueBlock:^{ + spTwoColorBatcher_flush(batcher); + } globalSortOrder:0 debugLabel: nil threadSafe: false]; + } + [_drawNode clear]; if (_debugSlots) { // Slots.