Преглед на файлове

[cocos2d-objc] Added clipping.

badlogic преди 8 години
родител
ревизия
14d3d49ac4

+ 40 - 0
spine-cocos2d-objc/example/CoinExample.h

@@ -0,0 +1,40 @@
+/******************************************************************************
+ * 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.
+ *****************************************************************************/
+
+#import "cocos2d.h"
+#import <spine/spine-cocos2d-objc.h>
+
+@interface CoinExample : CCNode {
+	SkeletonAnimation* skeletonNode;
+}
+
++ (CCScene*) scene;
+
+@end

+ 74 - 0
spine-cocos2d-objc/example/CoinExample.m

@@ -0,0 +1,74 @@
+/******************************************************************************
+ * 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.
+ *****************************************************************************/
+
+#import "CoinExample.h"
+#import "SpineBoyExample.h"
+
+@implementation CoinExample
+
++ (CCScene*) scene {
+	CCScene *scene = [CCScene node];
+	[scene addChild:[CoinExample node]];
+	return scene;
+}
+
+-(id) init {
+	self = [super init];
+	if (!self) return nil;
+
+	skeletonNode = [SkeletonAnimation skeletonWithFile:@"coin.json" atlasFile:@"coin.atlas" scale:0.5];
+
+    __weak SkeletonAnimation* node = skeletonNode;
+	skeletonNode.twoColorTint = false;
+	
+	[skeletonNode setAnimationForTrack:0 name:@"rotate" loop:YES];
+
+	CGSize windowSize = [[CCDirector sharedDirector] viewSize];
+	[skeletonNode setPosition:ccp(windowSize.width / 2, windowSize.height / 2 - 100)];
+	[self addChild:skeletonNode];
+
+	self.userInteractionEnabled = YES;
+    self.contentSize = windowSize;
+
+	return self;
+}
+
+#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:[SpineboyExample scene]];
+}
+#endif
+
+@end

+ 2 - 2
spine-cocos2d-objc/example/TankExample.m

@@ -29,7 +29,7 @@
  *****************************************************************************/
 
 #import "TankExample.h"
-#import "SpineboyExample.h"
+#import "CoinExample.h"
 
 @implementation TankExample
 
@@ -63,7 +63,7 @@
     else if (skeletonNode.timeScale == 1)
         skeletonNode.timeScale = 0.3f;
     else
-        [[CCDirector sharedDirector] replaceScene:[SpineboyExample scene]];
+        [[CCDirector sharedDirector] replaceScene:[CoinExample scene]];
 }
 #endif
 

+ 34 - 0
spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj

@@ -34,6 +34,14 @@
 		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 */; };
+		76EE4E461EB36DE6000254F4 /* Array.c in Sources */ = {isa = PBXBuildFile; fileRef = 76EE4E421EB36DE6000254F4 /* Array.c */; };
+		76EE4E471EB36DE6000254F4 /* ClippingAttachment.c in Sources */ = {isa = PBXBuildFile; fileRef = 76EE4E431EB36DE6000254F4 /* ClippingAttachment.c */; };
+		76EE4E481EB36DE6000254F4 /* SkeletonClipping.c in Sources */ = {isa = PBXBuildFile; fileRef = 76EE4E441EB36DE6000254F4 /* SkeletonClipping.c */; };
+		76EE4E491EB36DE6000254F4 /* Triangulator.c in Sources */ = {isa = PBXBuildFile; fileRef = 76EE4E451EB36DE6000254F4 /* Triangulator.c */; };
+		76EE4E511EB36E53000254F4 /* coin.atlas in Resources */ = {isa = PBXBuildFile; fileRef = 76EE4E4E1EB36E53000254F4 /* coin.atlas */; };
+		76EE4E521EB36E53000254F4 /* coin.json in Resources */ = {isa = PBXBuildFile; fileRef = 76EE4E4F1EB36E53000254F4 /* coin.json */; };
+		76EE4E531EB36E53000254F4 /* coin.png in Resources */ = {isa = PBXBuildFile; fileRef = 76EE4E501EB36E53000254F4 /* coin.png */; };
+		76EE4E561EB36E94000254F4 /* CoinExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EE4E551EB36E94000254F4 /* CoinExample.m */; };
 		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 +170,15 @@
 		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>"; };
+		76EE4E421EB36DE6000254F4 /* Array.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Array.c; path = "../spine-c/spine-c/src/spine/Array.c"; sourceTree = "<group>"; };
+		76EE4E431EB36DE6000254F4 /* ClippingAttachment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ClippingAttachment.c; path = "../spine-c/spine-c/src/spine/ClippingAttachment.c"; sourceTree = "<group>"; };
+		76EE4E441EB36DE6000254F4 /* SkeletonClipping.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SkeletonClipping.c; path = "../spine-c/spine-c/src/spine/SkeletonClipping.c"; sourceTree = "<group>"; };
+		76EE4E451EB36DE6000254F4 /* Triangulator.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Triangulator.c; path = "../spine-c/spine-c/src/spine/Triangulator.c"; sourceTree = "<group>"; };
+		76EE4E4E1EB36E53000254F4 /* coin.atlas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = coin.atlas; path = Resources/coin.atlas; sourceTree = "<group>"; };
+		76EE4E4F1EB36E53000254F4 /* coin.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = coin.json; path = Resources/coin.json; sourceTree = "<group>"; };
+		76EE4E501EB36E53000254F4 /* coin.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = coin.png; path = Resources/coin.png; sourceTree = "<group>"; };
+		76EE4E541EB36E94000254F4 /* CoinExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoinExample.h; path = example/CoinExample.h; sourceTree = "<group>"; };
+		76EE4E551EB36E94000254F4 /* CoinExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CoinExample.m; path = example/CoinExample.m; 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>"; };
@@ -269,6 +286,8 @@
 				76F5BDA91D2BDE67005917E5 /* RaptorExample.m */,
 				76F5BDAB1D2BDFA2005917E5 /* TankExample.h */,
 				76F5BDAC1D2BDFA2005917E5 /* TankExample.m */,
+				76EE4E541EB36E94000254F4 /* CoinExample.h */,
+				76EE4E551EB36E94000254F4 /* CoinExample.m */,
 				43C32A07170B10FF004A9460 /* AppDelegate.h */,
 				43C32A08170B10FF004A9460 /* AppDelegate.m */,
 				43C32A05170B0F93004A9460 /* main.m */,
@@ -280,6 +299,10 @@
 		43C32822170B0BC2004A9460 /* spine-c */ = {
 			isa = PBXGroup;
 			children = (
+				76EE4E421EB36DE6000254F4 /* Array.c */,
+				76EE4E431EB36DE6000254F4 /* ClippingAttachment.c */,
+				76EE4E441EB36DE6000254F4 /* SkeletonClipping.c */,
+				76EE4E451EB36DE6000254F4 /* Triangulator.c */,
 				76FAC1941E3FA15E001CCC8C /* Color.c */,
 				76FAC1951E3FA15E001CCC8C /* PointAttachment.c */,
 				76F28CF41DEC810200CDE54D /* Animation.c */,
@@ -338,6 +361,9 @@
 		43C32867170B0C7F004A9460 /* Resources */ = {
 			isa = PBXGroup;
 			children = (
+				76EE4E4E1EB36E53000254F4 /* coin.atlas */,
+				76EE4E4F1EB36E53000254F4 /* coin.json */,
+				76EE4E501EB36E53000254F4 /* coin.png */,
 				765A2EF41D7D7A08003FB779 /* goblins.atlas */,
 				765A2EF51D7D7A08003FB779 /* goblins.png */,
 				76F5BD9C1D2BDE1C005917E5 /* raptor.atlas */,
@@ -515,14 +541,17 @@
 				43C3286E170B0DA6004A9460 /* spineboy.atlas in Resources */,
 				43C3286F170B0DA6004A9460 /* spineboy.png in Resources */,
 				43C3287D170B0DBE004A9460 /* [email protected] in Resources */,
+				76EE4E521EB36E53000254F4 /* coin.json in Resources */,
 				43C3287E170B0DBE004A9460 /* Default-Landscape~ipad.png in Resources */,
 				43C3287F170B0DBE004A9460 /* Default.png in Resources */,
 				76F5BDA31D2BDE1C005917E5 /* raptor.json in Resources */,
+				76EE4E531EB36E53000254F4 /* coin.png in Resources */,
 				43C32880170B0DBE004A9460 /* [email protected] 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 */,
+				76EE4E511EB36E53000254F4 /* coin.atlas in Resources */,
 				76F5BDA21D2BDE1C005917E5 /* raptor.atlas in Resources */,
 				43C32883170B0DBE004A9460 /* Icon-Small.png in Resources */,
 				43C32884170B0DBE004A9460 /* [email protected] in Resources */,
@@ -553,16 +582,20 @@
 				76F5BDAA1D2BDE67005917E5 /* RaptorExample.m in Sources */,
 				76F28D301DEC810300CDE54D /* Skin.c in Sources */,
 				76F28D251DEC810300CDE54D /* Json.c in Sources */,
+				76EE4E491EB36DE6000254F4 /* Triangulator.c in Sources */,
 				76F28D1C1DEC810300CDE54D /* AttachmentLoader.c in Sources */,
+				76EE4E461EB36DE6000254F4 /* Array.c in Sources */,
 				76F28D241DEC810300CDE54D /* IkConstraintData.c in Sources */,
 				76F28D1E1DEC810300CDE54D /* BoneData.c in Sources */,
 				76F28D2A1DEC810300CDE54D /* RegionAttachment.c in Sources */,
+				76EE4E471EB36DE6000254F4 /* ClippingAttachment.c in Sources */,
 				76F28D2C1DEC810300CDE54D /* SkeletonBinary.c in Sources */,
 				76F5BDAD1D2BDFA2005917E5 /* TankExample.m in Sources */,
 				76F28D171DEC810300CDE54D /* AnimationState.c in Sources */,
 				76F28D221DEC810300CDE54D /* extension.c in Sources */,
 				76F28D231DEC810300CDE54D /* IkConstraint.c in Sources */,
 				76BF7E071E66ED9C00485998 /* GLUtils.c in Sources */,
+				76EE4E481EB36DE6000254F4 /* SkeletonClipping.c in Sources */,
 				43C3282F170B0C19004A9460 /* spine-cocos2d-objc.m in Sources */,
 				76F28D1F1DEC810300CDE54D /* BoundingBoxAttachment.c in Sources */,
 				76F28D281DEC810300CDE54D /* PathConstraint.c in Sources */,
@@ -580,6 +613,7 @@
 				76F28D1B1DEC810300CDE54D /* Attachment.c in Sources */,
 				76F28D261DEC810300CDE54D /* MeshAttachment.c in Sources */,
 				76F28D1A1DEC810300CDE54D /* AtlasAttachmentLoader.c in Sources */,
+				76EE4E561EB36E94000254F4 /* CoinExample.m in Sources */,
 				76F28D211DEC810300CDE54D /* EventData.c in Sources */,
 				76F28D181DEC810300CDE54D /* AnimationStateData.c in Sources */,
 				43F7FF891927F94800CA4038 /* SkeletonRenderer.m in Sources */,

+ 1 - 0
spine-cocos2d-objc/src/spine/SkeletonRenderer.h

@@ -46,6 +46,7 @@
 	spAtlas* _atlas;
 	float* _worldVertices;
 	CCBlendMode* screenMode;
+	spSkeletonClipping* _clipper;
 }
 
 + (id) skeletonWithData:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData;

+ 74 - 51
spine-cocos2d-objc/src/spine/SkeletonRenderer.m

@@ -34,7 +34,7 @@
 #import <spine/GLUtils.h>
 #import "CCDrawNode.h"
 
-static const unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0};
+static unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0};
 static spTwoColorBatcher* batcher = 0;
 static spMesh* mesh = 0;
 static bool handlerQueued = false;
@@ -89,6 +89,8 @@ static bool handlerQueued = false;
 		CCBlendFuncSrcColor: @(GL_ONE),
 		CCBlendFuncDstColor: @(GL_ONE_MINUS_SRC_COLOR)}
 	];
+	
+	_clipper = spSkeletonClipping_create();
 }
 
 - (id) initWithData:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData {
@@ -153,6 +155,7 @@ static bool handlerQueued = false;
 	if (_atlas) spAtlas_dispose(_atlas);
 	spSkeleton_dispose(_skeleton);
 	FREE(_worldVertices);
+	spSkeletonClipping_dispose(_clipper);
 	[super dealloc];
 }
 
@@ -179,9 +182,10 @@ static bool handlerQueued = false;
 	int blendMode = -1;
 	uint32_t srcBlend = GL_SRC_ALPHA;
 	uint32_t dstBlend = GL_ONE_MINUS_SRC_ALPHA;
-	const float* uvs = 0;
+	float* uvs = 0;
+	float* vertices = _worldVertices;
 	int verticesCount = 0;
-	const unsigned short* triangles = 0;
+	unsigned short* triangles = 0;
 	int trianglesCount = 0;
 	float r = 0, g = 0, b = 0, a = 0;
 	float dr = 0, dg = 0, db = 0;
@@ -192,7 +196,7 @@ static bool handlerQueued = false;
 		switch (slot->attachment->type) {
 		case SP_ATTACHMENT_REGION: {
 			spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
-			spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices, 0, 2);
+			spRegionAttachment_computeWorldVertices(attachment, slot->bone, vertices, 0, 2);
 			texture = [self getTextureForRegion:attachment];
 			uvs = attachment->uvs;
 			verticesCount = 8;
@@ -206,7 +210,7 @@ static bool handlerQueued = false;
 		}
 		case SP_ATTACHMENT_MESH: {
 			spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
-			spVertexAttachment_computeWorldVertices(SUPER(attachment), slot, 0, attachment->super.worldVerticesLength, _worldVertices, 0, 2);
+			spVertexAttachment_computeWorldVertices(SUPER(attachment), slot, 0, attachment->super.worldVerticesLength, vertices, 0, 2);
 			texture = [self getTextureForMesh:attachment];
 			uvs = attachment->uvs;
 			verticesCount = attachment->super.worldVerticesLength;
@@ -218,8 +222,13 @@ static bool handlerQueued = false;
 			a = attachment->color.a;
 			break;
 		}
+		case SP_ATTACHMENT_CLIPPING: {
+			spClippingAttachment* clip = (spClippingAttachment*)slot->attachment;
+			spSkeletonClipping_clipStart(_clipper, slot, clip);
+		}
 		default: ;
 		}
+		
 		if (texture) {
 			if (slot->data->blendMode != blendMode) {
 				blendMode = slot->data->blendMode;
@@ -261,58 +270,72 @@ static bool handlerQueued = false;
 			GLKVector2 center = GLKVector2Make(size.width / 2.0, size.height / 2.0);
 			GLKVector2 extents = GLKVector2Make(size.width / 2.0, size.height / 2.0);
 			if (_skipVisibilityCheck || CCRenderCheckVisbility(transform, center, extents)) {
-				if (!self.twoColorTint) {
-					CCRenderBuffer buffer = [renderer enqueueTriangles:(trianglesCount / 3) andVertexes:verticesCount withState:self.renderState globalSortOrder:0];
-					for (int i = 0; i * 2 < verticesCount; ++i) {
-						CCVertex vertex;
-						vertex.position = GLKVector4Make(_worldVertices[i * 2], _worldVertices[i * 2 + 1], 0.0, 1.0);
-						vertex.color = GLKVector4Make(r, g, b, a);
-						vertex.texCoord1 = GLKVector2Make(uvs[i * 2], 1 - uvs[i * 2 + 1]);
-						CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform(vertex, transform));
-					}
-					for (int j = 0; j * 3 < trianglesCount; ++j) {
-						CCRenderBufferSetTriangle(buffer, j, triangles[j * 3], triangles[j * 3 + 1], triangles[j * 3 + 2]);
-					}
-				} else {
-					if (slot->darkColor) {
-						dr = slot->darkColor->r;
-						dg = slot->darkColor->g;
-						db = slot->darkColor->b;
+				
+				if (spSkeletonClipping_isClipping(_clipper)) {
+					spSkeletonClipping_clipTriangles(_clipper, vertices, verticesCount, triangles, trianglesCount, uvs);
+					vertices = _clipper->clippedVertices->items;
+					verticesCount = _clipper->clippedVertices->size;
+					uvs = _clipper->clippedUVs->items;
+					triangles = _clipper->clippedTriangles->items;
+					trianglesCount = _clipper->clippedTriangles->size;
+				}
+				
+				if (trianglesCount > 0) {
+					if (!self.twoColorTint) {
+						CCRenderBuffer buffer = [renderer enqueueTriangles:(trianglesCount / 3) andVertexes:verticesCount withState:self.renderState globalSortOrder:0];
+						for (int i = 0; i * 2 < verticesCount; ++i) {
+							CCVertex vertex;
+							vertex.position = GLKVector4Make(vertices[i * 2], vertices[i * 2 + 1], 0.0, 1.0);
+							vertex.color = GLKVector4Make(r, g, b, a);
+							vertex.texCoord1 = GLKVector2Make(uvs[i * 2], 1 - uvs[i * 2 + 1]);
+							CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform(vertex, transform));
+						}
+						for (int j = 0; j * 3 < trianglesCount; ++j) {
+							CCRenderBufferSetTriangle(buffer, j, triangles[j * 3], triangles[j * 3 + 1], triangles[j * 3 + 2]);
+						}
 					} else {
-						dr = dg = db = 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 = ((unsigned short)(r * 255))| ((unsigned short)(g * 255)) << 8 | ((unsigned short)(b * 255)) <<16 | ((unsigned short)(a * 255)) << 24;
-						vertices->color2 = ((unsigned short)(dr * 255)) | ((unsigned short)(dg * 255)) << 8 | ((unsigned short)(db * 255)) << 16 | ((unsigned short)(255)) << 24;
-						vertices->u = uvs[i * 2];
-						vertices->v = 1 - uvs[i * 2 + 1];
-					}
-					
-					for (int j = 0; j < trianglesCount; j++, indices++) {
-						*indices = triangles[j];
+						if (slot->darkColor) {
+							dr = slot->darkColor->r;
+							dg = slot->darkColor->g;
+							db = slot->darkColor->b;
+						} else {
+							dr = dg = db = 0;
+						}
+						
+						spMeshPart meshPart;
+						spMesh_allocatePart(mesh, &meshPart, verticesCount / 2, trianglesCount, self.texture.name, srcBlend, dstBlend);
+						
+						spVertex* verts = &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(vertices[i * 2], vertices[i * 2 + 1], 0.0, 1.0);
+							vertex = CCVertexApplyTransform(vertex, transform);
+							verts->x = vertex.position.x;
+							verts->y = vertex.position.y;
+							verts->z = vertex.position.z;
+							verts->w = vertex.position.w;
+							verts->color = ((unsigned short)(r * 255))| ((unsigned short)(g * 255)) << 8 | ((unsigned short)(b * 255)) <<16 | ((unsigned short)(a * 255)) << 24;
+							verts->color2 = ((unsigned short)(dr * 255)) | ((unsigned short)(dg * 255)) << 8 | ((unsigned short)(db * 255)) << 16 | ((unsigned short)(255)) << 24;
+							verts->u = uvs[i * 2];
+							verts->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];
 					}
-					
-					[renderer enqueueBlock:^{
-						spTwoColorBatcher_add(batcher, meshPart);
-					} globalSortOrder:0 debugLabel: nil threadSafe: false];
 				}
 			}
 		}
+		spSkeletonClipping_clipEnd(_clipper, slot);
 	}
+	spSkeletonClipping_clipEnd2(_clipper);
 	
 	if (self.twoColorTint) {
 		[renderer enqueueBlock:^{