[cocos2d-objc] More two color tinting work, shader appears broken

This commit is contained in:
badlogic 2017-03-14 15:24:20 +01:00
parent 3ed9290c6f
commit c746da940f
8 changed files with 299 additions and 26 deletions

View File

@ -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

View File

@ -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" }
]
}
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -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

View File

@ -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 = "<group>"; };
76BF7E051E66ED9C00485998 /* GLUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GLUtils.c; path = src/spine/GLUtils.c; sourceTree = "<group>"; };
76BF7E061E66ED9C00485998 /* GLUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GLUtils.h; path = src/spine/GLUtils.h; sourceTree = "<group>"; };
76BFBC2D1E78254F00675E2B /* TwoColorTest.atlas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TwoColorTest.atlas; sourceTree = "<group>"; };
76BFBC2E1E78254F00675E2B /* TwoColorTest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = TwoColorTest.json; sourceTree = "<group>"; };
76BFBC2F1E78254F00675E2B /* TwoColorTest.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TwoColorTest.png; sourceTree = "<group>"; };
76F28CF41DEC810200CDE54D /* Animation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Animation.c; path = "../spine-c/spine-c/src/spine/Animation.c"; sourceTree = "<group>"; };
76F28CF51DEC810300CDE54D /* AnimationState.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AnimationState.c; path = "../spine-c/spine-c/src/spine/AnimationState.c"; sourceTree = "<group>"; };
76F28CF61DEC810300CDE54D /* AnimationStateData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AnimationStateData.c; path = "../spine-c/spine-c/src/spine/AnimationStateData.c"; sourceTree = "<group>"; };
@ -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 */,

View File

@ -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) {

View File

@ -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);

View File

@ -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.