From c746da940f98798e9c05154322d2f1763d87c312 Mon Sep 17 00:00:00 2001 From: badlogic Date: Tue, 14 Mar 2017 15:24:20 +0100 Subject: [PATCH] [cocos2d-objc] More two color tinting work, shader appears broken --- spine-cocos2d-objc/TwoColorTest.atlas | 13 ++ spine-cocos2d-objc/TwoColorTest.json | 150 ++++++++++++++++++ spine-cocos2d-objc/TwoColorTest.png | Bin 0 -> 9826 bytes spine-cocos2d-objc/example/SpineboyExample.m | 21 +-- .../project.pbxproj | 12 ++ spine-cocos2d-objc/src/spine/GLUtils.c | 74 ++++++++- spine-cocos2d-objc/src/spine/GLUtils.h | 7 +- .../src/spine/SkeletonRenderer.m | 48 +++++- 8 files changed, 299 insertions(+), 26 deletions(-) create mode 100644 spine-cocos2d-objc/TwoColorTest.atlas create mode 100644 spine-cocos2d-objc/TwoColorTest.json create mode 100644 spine-cocos2d-objc/TwoColorTest.png 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 0000000000000000000000000000000000000000..f78c2923b5a7548c2e755c86954bcdf579259249 GIT binary patch literal 9826 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 literal 0 HcmV?d00001 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.