Эх сурвалжийг харах

cocos2d-x rendering now uses TrianglesCommand for batching across scene graph nodes.

NathanSweet 9 жил өмнө
parent
commit
55851f7699

+ 2 - 0
spine-cocos2dx/3/example/Classes/AppDelegate.cpp

@@ -35,6 +35,7 @@
 #include <string>
 
 #include "RaptorExample.h"
+#include "BatchingExample.h"
 #include "AppMacros.h"
 
 USING_NS_CC;
@@ -98,6 +99,7 @@ bool AppDelegate::applicationDidFinishLaunching () {
 
 	// create a scene. it's an autorelease object
 	auto scene = RaptorExample::scene();
+	//auto scene = BatchingExample::scene();
 
 	// run
 	director->runWithScene(scene);

+ 92 - 0
spine-cocos2dx/3/example/Classes/BatchingExample.cpp

@@ -0,0 +1,92 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) 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.
+ *****************************************************************************/
+
+#include "BatchingExample.h"
+#include "SpineboyExample.h"
+
+USING_NS_CC;
+using namespace spine;
+
+Scene* BatchingExample::scene () {
+	Scene *scene = Scene::create();
+	scene->addChild(BatchingExample::create());
+	return scene;
+}
+
+bool BatchingExample::init () {
+	if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false;
+
+	// Load the texture atlas.
+	spAtlas* atlas = spAtlas_createFromFile("spineboy.atlas", 0);
+	CCASSERT(atlas, "Error reading atlas file.");
+
+	// Load the skeleton data.
+	spSkeletonJson* json = spSkeletonJson_create(atlas);
+	json->scale = 0.6f;
+	spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, "spineboy.json");
+	CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data file.");
+	spSkeletonJson_dispose(json);
+
+	// Setup mix times.
+	spAnimationStateData* stateData = spAnimationStateData_create(skeletonData);
+	spAnimationStateData_setMixByName(stateData, "walk", "jump", 0.2f);
+	spAnimationStateData_setMixByName(stateData, "jump", "run", 0.2f);
+
+	Size windowSize = Director::getInstance()->getWinSize();
+	int xMin = (int)(windowSize.width * 0.10f), xMax = (int)windowSize.width - xMin;
+	int yMin = 20, yMax = windowSize.height - 350;
+	for (int i = 0; i < 50; i++) {
+		// Each skeleton node shares the same atlas, skeleton data, and mix times.
+		SkeletonAnimation* skeletonNode = SkeletonAnimation::createWithData(skeletonData, false);
+		skeletonNode->setAnimationStateData(stateData);
+
+		skeletonNode->setAnimation(0, "walk", true);
+		skeletonNode->addAnimation(0, "jump", false, 3);
+		skeletonNode->addAnimation(0, "run", true);
+
+		skeletonNode->setPosition(Vec2(
+			RandomHelper::random_int(xMin, xMax),
+			RandomHelper::random_int(yMin, yMax)
+		));
+		addChild(skeletonNode);
+	}
+
+	scheduleUpdate();
+
+	EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create();
+	listener->onTouchBegan = [this] (Touch* touch, Event* event) -> bool {
+		Director::getInstance()->replaceScene(SpineboyExample::scene());
+		return true;
+	};
+	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
+
+	return true;
+}

+ 47 - 0
spine-cocos2dx/3/example/Classes/BatchingExample.h

@@ -0,0 +1,47 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) 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.
+ *****************************************************************************/
+
+#ifndef _BATCHINGEXAMPLE_H_
+#define _BATCHINGEXAMPLE_H_
+
+#include "cocos2d.h"
+#include <spine/spine-cocos2dx.h>
+
+class BatchingExample : public cocos2d::LayerColor {
+public:
+	static cocos2d::Scene* scene ();
+
+	CREATE_FUNC(BatchingExample);
+
+	virtual bool init ();
+};
+
+#endif // _BATCHINGEXAMPLE_H_

+ 0 - 4
spine-cocos2dx/3/example/Classes/GoblinsExample.cpp

@@ -31,13 +31,9 @@
 
 #include "GoblinsExample.h"
 #include "RaptorExample.h"
-#include <iostream>
-#include <fstream>
-#include <string.h>
 
 USING_NS_CC;
 using namespace spine;
-using namespace std;
 
 Scene* GoblinsExample::scene () {
 	Scene *scene = Scene::create();

+ 2 - 1
spine-cocos2dx/3/example/Classes/GoblinsExample.h

@@ -39,9 +39,10 @@ class GoblinsExample : public cocos2d::LayerColor {
 public:
 	static cocos2d::Scene* scene ();
 
+	CREATE_FUNC(GoblinsExample);
+
 	virtual bool init ();
 
-	CREATE_FUNC (GoblinsExample);
 private:
 	spine::SkeletonAnimation* skeletonNode;
 };

+ 2 - 6
spine-cocos2dx/3/example/Classes/RaptorExample.cpp

@@ -30,14 +30,10 @@
  *****************************************************************************/
 
 #include "RaptorExample.h"
-#include "SpineboyExample.h"
-#include <iostream>
-#include <fstream>
-#include <string.h>
+#include "BatchingExample.h"
 
 USING_NS_CC;
 using namespace spine;
-using namespace std;
 
 Scene* RaptorExample::scene () {
 	Scene *scene = Scene::create();
@@ -66,7 +62,7 @@ bool RaptorExample::init () {
 		else if (skeletonNode->getTimeScale() == 1)
 			skeletonNode->setTimeScale(0.3f);
 		else
-			Director::getInstance()->replaceScene(SpineboyExample::scene());
+			Director::getInstance()->replaceScene(BatchingExample::scene());
 		return true;
 	};
 	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

+ 2 - 1
spine-cocos2dx/3/example/Classes/RaptorExample.h

@@ -39,9 +39,10 @@ class RaptorExample : public cocos2d::LayerColor {
 public:
 	static cocos2d::Scene* scene ();
 
+	CREATE_FUNC(RaptorExample);
+
 	virtual bool init ();
 
-	CREATE_FUNC (RaptorExample);
 private:
 	spine::SkeletonAnimation* skeletonNode;
 };

+ 103 - 0
spine-cocos2dx/3/example/Classes/SimpleCommand.cpp

@@ -0,0 +1,103 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) 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.
+ *****************************************************************************/
+
+#include "SimpleCommand.h"
+
+USING_NS_CC;
+using namespace std;
+
+Scene* SimpleCommand::scene () {
+	Scene *scene = Scene::create();
+	scene->addChild(SimpleCommand::create());
+	return scene;
+}
+
+bool SimpleCommand::init () {
+	if (!Node::init()) return false;
+
+	setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP));
+
+	_texture = _director->getTextureCache()->addImage("sprite.png");
+	
+	setPosition(100, 100);
+
+	return true;
+}
+
+void SimpleCommand::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) {
+	TrianglesCommand::Triangles* triangles = new TrianglesCommand::Triangles();
+	
+	float x = 0, y = 0;
+	float w = 80, h = 80;
+
+	triangles->vertCount = 4;
+	triangles->verts = new V3F_C4B_T2F[4];
+	triangles->verts[0].colors = Color4B::WHITE;
+	triangles->verts[0].texCoords.u = 0;
+	triangles->verts[0].texCoords.v = 1;
+	triangles->verts[0].vertices.x = 0;
+	triangles->verts[0].vertices.y = 0;
+	triangles->verts[0].vertices.z = 0;
+
+	triangles->verts[1].colors = Color4B::WHITE;
+	triangles->verts[1].texCoords.u = 0;
+	triangles->verts[1].texCoords.v = 0;
+	triangles->verts[1].vertices.x = 0;
+	triangles->verts[1].vertices.y = h;
+	triangles->verts[1].vertices.z = 0;
+
+	triangles->verts[2].colors = Color4B::WHITE;
+	triangles->verts[2].texCoords.u = 1;
+	triangles->verts[2].texCoords.v = 1;
+	triangles->verts[2].vertices.x = w;
+	triangles->verts[2].vertices.y = 0;
+	triangles->verts[2].vertices.z = 0;
+
+	triangles->verts[3].colors = Color4B::WHITE;
+	triangles->verts[3].texCoords.u = 1;
+	triangles->verts[3].texCoords.v = 0;
+	triangles->verts[3].vertices.x = w;
+	triangles->verts[3].vertices.y = h;
+	triangles->verts[3].vertices.z = 0;
+
+	triangles->indexCount = 6;
+	triangles->indices = new GLushort[6];
+	triangles->indices[0] = 0;
+	triangles->indices[1] = 1;
+	triangles->indices[2] = 2;
+	triangles->indices[3] = 3;
+	triangles->indices[4] = 2;
+	triangles->indices[5] = 1;
+
+	TrianglesCommand* trianglesCommand = new TrianglesCommand();
+	trianglesCommand->init(_globalZOrder, _texture->getName(), getGLProgramState(), BlendFunc::ALPHA_PREMULTIPLIED, *triangles, transform, transformFlags);
+   renderer->addCommand(trianglesCommand);
+}

+ 10 - 23
spine-cocos2dx/3/src/spine/PolygonBatch.h → spine-cocos2dx/3/example/Classes/SimpleCommand.h

@@ -29,36 +29,23 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
-#ifndef SPINE_POLYGONBATCH_H_
-#define SPINE_POLYGONBATCH_H_
+#ifndef _SIMPLECOMMAND_H_
+#define _SIMPLECOMMAND_H_
 
 #include "cocos2d.h"
 
-namespace spine {
 
-class PolygonBatch : public cocos2d::Ref {
+class SimpleCommand : public cocos2d::Node {
 public:
-	static PolygonBatch* createWithCapacity (ssize_t capacity);
+	static cocos2d::Scene* scene ();
 
-	void add (const cocos2d::Texture2D* texture,
-		const float* vertices, const float* uvs, int verticesCount,
-		const int* triangles, int trianglesCount,
-		cocos2d::Color4B* color);
-	void flush ();
+	virtual bool init ();
+	virtual void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags) override;
 
-protected:
-	PolygonBatch();
-	virtual ~PolygonBatch();
-	bool initWithCapacity (ssize_t capacity);
+	CREATE_FUNC (SimpleCommand);
 
-	ssize_t _capacity;
-	cocos2d::V2F_C4B_T2F* _vertices;
-	int _verticesCount;
-	GLushort* _triangles;
-	int _trianglesCount;
-	const cocos2d::Texture2D* _texture;
+protected:
+	cocos2d::Texture2D* _texture;
 };
 
-}
-
-#endif // SPINE_POLYGONBATCH_H_
+#endif // _SIMPLECOMMAND_H_

+ 0 - 4
spine-cocos2dx/3/example/Classes/SpineboyExample.cpp

@@ -31,13 +31,9 @@
 
 #include "SpineboyExample.h"
 #include "GoblinsExample.h"
-#include <iostream>
-#include <fstream>
-#include <string.h>
 
 USING_NS_CC;
 using namespace spine;
-using namespace std;
 
 Scene* SpineboyExample::scene () {
 	Scene *scene = Scene::create();

+ 3 - 1
spine-cocos2dx/3/example/Classes/SpineboyExample.h

@@ -39,10 +39,12 @@ class SpineboyExample : public cocos2d::LayerColor {
 public:
 	static cocos2d::Scene* scene ();
 
+	CREATE_FUNC (SpineboyExample);
+
 	virtual bool init ();
+
 	virtual void update (float deltaTime);
 
-	CREATE_FUNC (SpineboyExample);
 private:
 	spine::SkeletonAnimation* skeletonNode;
 };

+ 4 - 2
spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj

@@ -129,23 +129,25 @@
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\src\spine\PolygonBatch.h" />
+    <ClInclude Include="..\..\src\spine\SkeletonBatch.h" />
     <ClInclude Include="..\..\src\spine\SkeletonAnimation.h" />
     <ClInclude Include="..\..\src\spine\SkeletonRenderer.h" />
     <ClInclude Include="..\..\src\spine\spine-cocos2dx.h" />
     <ClInclude Include="..\Classes\AppDelegate.h" />
     <ClInclude Include="..\Classes\AppMacros.h" />
+    <ClInclude Include="..\Classes\BatchingExample.h" />
     <ClInclude Include="..\Classes\GoblinsExample.h" />
     <ClInclude Include="..\Classes\RaptorExample.h" />
     <ClInclude Include="..\Classes\SpineboyExample.h" />
     <ClInclude Include="main.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\..\src\spine\PolygonBatch.cpp" />
+    <ClCompile Include="..\..\src\spine\SkeletonBatch.cpp" />
     <ClCompile Include="..\..\src\spine\SkeletonAnimation.cpp" />
     <ClCompile Include="..\..\src\spine\SkeletonRenderer.cpp" />
     <ClCompile Include="..\..\src\spine\spine-cocos2dx.cpp" />
     <ClCompile Include="..\Classes\AppDelegate.cpp" />
+    <ClCompile Include="..\Classes\BatchingExample.cpp" />
     <ClCompile Include="..\Classes\GoblinsExample.cpp" />
     <ClCompile Include="..\Classes\RaptorExample.cpp" />
     <ClCompile Include="..\Classes\SpineboyExample.cpp" />

+ 12 - 6
spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj.filters

@@ -30,9 +30,6 @@
     <ClInclude Include="..\Classes\RaptorExample.h">
       <Filter>Classes</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\src\spine\PolygonBatch.h">
-      <Filter>src</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\src\spine\SkeletonAnimation.h">
       <Filter>src</Filter>
     </ClInclude>
@@ -42,6 +39,12 @@
     <ClInclude Include="..\..\src\spine\spine-cocos2dx.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="..\Classes\BatchingExample.h">
+      <Filter>Classes</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\spine\SkeletonBatch.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="main.cpp">
@@ -59,9 +62,6 @@
     <ClCompile Include="..\Classes\RaptorExample.cpp">
       <Filter>Classes</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\spine\PolygonBatch.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\spine\SkeletonAnimation.cpp">
       <Filter>src</Filter>
     </ClCompile>
@@ -71,5 +71,11 @@
     <ClCompile Include="..\..\src\spine\spine-cocos2dx.cpp">
       <Filter>src</Filter>
     </ClCompile>
+    <ClCompile Include="..\Classes\BatchingExample.cpp">
+      <Filter>Classes</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\spine\SkeletonBatch.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 0 - 116
spine-cocos2dx/3/src/spine/PolygonBatch.cpp

@@ -1,116 +0,0 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
- *****************************************************************************/
-
-#include <spine/PolygonBatch.h>
-#include <spine/extension.h>
-
-USING_NS_CC;
-
-namespace spine {
-
-PolygonBatch* PolygonBatch::createWithCapacity (ssize_t capacity) {
-	PolygonBatch* batch = new PolygonBatch();
-	batch->initWithCapacity(capacity);
-	batch->autorelease();
-	return batch;
-}
-
-PolygonBatch::PolygonBatch () :
-	_capacity(0),
-	_vertices(nullptr), _verticesCount(0),
-	_triangles(nullptr), _trianglesCount(0),
-	_texture(nullptr)
-{}
-
-bool PolygonBatch::initWithCapacity (ssize_t capacity) {
-	// 32767 is max index, so 32767 / 3 - (32767 / 3 % 3) = 10920.
-	CCASSERT(capacity <= 10920, "capacity cannot be > 10920");
-	CCASSERT(capacity >= 0, "capacity cannot be < 0");
-	_capacity = capacity;
-	_vertices = MALLOC(V2F_C4B_T2F, capacity);
-	_triangles = MALLOC(GLushort, capacity * 3);
-	return true;
-}
-
-PolygonBatch::~PolygonBatch () {
-	FREE(_vertices);
-	FREE(_triangles);
-}
-
-void PolygonBatch::add (const Texture2D* addTexture,
-		const float* addVertices, const float* uvs, int addVerticesCount,
-		const int* addTriangles, int addTrianglesCount,
-		Color4B* color) {
-
-	if (
-		addTexture != _texture
-		|| _verticesCount + (addVerticesCount >> 1) > _capacity
-		|| _trianglesCount + addTrianglesCount > _capacity * 3) {
-		this->flush();
-		_texture = addTexture;
-	}
-
-	for (int i = 0; i < addTrianglesCount; ++i, ++_trianglesCount)
-		_triangles[_trianglesCount] = addTriangles[i] + _verticesCount;
-
-	for (int i = 0; i < addVerticesCount; i += 2, ++_verticesCount) {
-		V2F_C4B_T2F* vertex = _vertices + _verticesCount;
-		vertex->vertices.x = addVertices[i];
-		vertex->vertices.y = addVertices[i + 1];
-		vertex->colors = *color;
-		vertex->texCoords.u = uvs[i];
-		vertex->texCoords.v = uvs[i + 1];
-	}
-}
-
-void PolygonBatch::flush () {
-	if (!_verticesCount) return;
-
-	GL::bindTexture2D(_texture->getName());
-	GL::bindVAO(0);
-	glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
-	glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
-	glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORDS);
-	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), &_vertices[0].vertices);
-	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), &_vertices[0].colors);
-	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), &_vertices[0].texCoords);
-
-	glDrawElements(GL_TRIANGLES, _trianglesCount, GL_UNSIGNED_SHORT, _triangles);
-
-	CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _verticesCount);
-
-	_verticesCount = 0;
-	_trianglesCount = 0;
-
-	CHECK_GL_ERROR_DEBUG();
-}
-
-}

+ 1 - 0
spine-cocos2dx/3/src/spine/SkeletonAnimation.h

@@ -47,6 +47,7 @@ typedef std::function<void(int trackIndex, spEvent* event)> EventListener;
   * played later. */
 class SkeletonAnimation: public SkeletonRenderer {
 public:
+	CREATE_FUNC(SkeletonAnimation);
 	static SkeletonAnimation* createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
 	static SkeletonAnimation* createWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale = 1);
 	static SkeletonAnimation* createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);

+ 182 - 0
spine-cocos2dx/3/src/spine/SkeletonBatch.cpp

@@ -0,0 +1,182 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) 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.
+ *****************************************************************************/
+
+#include <spine/SkeletonBatch.h>
+#include <spine/extension.h>
+#include <algorithm>
+
+USING_NS_CC;
+using namespace std;
+
+namespace spine {
+
+static SkeletonBatch* instance = nullptr;
+
+void SkeletonBatch::setCommandSize (int maxVertices, int maxTriangles) {
+	// 32767 is max index, so 32767 / 3 - (32767 / 3 % 3) = 10920.
+	CCASSERT(maxTriangles <= 10920, "maxTriangles cannot be > 10920");
+	CCASSERT(maxTriangles >= 0, "maxTriangles cannot be < 0");
+	if (instance) delete instance;
+	instance = new SkeletonBatch(maxVertices, maxTriangles);
+}
+
+SkeletonBatch* SkeletonBatch::getInstance () {
+	if (!instance) instance = new SkeletonBatch(64, 64 * 3);
+	return instance;
+}
+
+SkeletonBatch::SkeletonBatch (int maxVertices, int maxTriangles) :
+	_maxVertices(maxVertices), _maxTriangles(maxTriangles),
+	_renderer(nullptr), _transform(nullptr), _transformFlags(0), _globalZOrder(0), _glProgramState(nullptr),
+	_texture(nullptr), _blendMode(SP_BLEND_MODE_NORMAL)
+{
+	_firstCommand = new Command(maxVertices, maxTriangles);
+	_command = _firstCommand;
+
+	Director::getInstance()->getScheduler()->scheduleUpdate(this, -1, false);
+}
+
+SkeletonBatch::~SkeletonBatch () {
+	Director::getInstance()->getScheduler()->unscheduleUpdate(this);
+
+	Command* command = _firstCommand;
+	while (command) {
+		Command* next = command->_next;
+		delete command;
+		command = next;
+	}
+}
+
+void SkeletonBatch::setRendererState (Renderer* renderer, const Mat4* transform, uint32_t transformFlags,
+		float globalZOrder, GLProgramState* glProgramState, bool premultipliedAlpha) {
+	_renderer = renderer;
+	_transform = transform;
+	_transformFlags = transformFlags;
+	_globalZOrder = globalZOrder;
+	_glProgramState = glProgramState;
+	_premultipliedAlpha = premultipliedAlpha;
+}
+
+void SkeletonBatch::update (float delta) {
+	// Reuse commands at the beginning of each frame.
+	_command = _firstCommand;
+	_command->_triangles->vertCount = 0;
+	_command->_triangles->indexCount = 0;
+}
+
+void SkeletonBatch::add (const Texture2D* addTexture,
+	const float* addVertices, const float* uvs, int addVerticesCount,
+	const int* addTriangles, int addTrianglesCount,
+	const Color4B& color, spBlendMode blendMode
+) {
+	if (addTexture != _texture
+		|| blendMode != _blendMode
+		|| _command->_triangles->vertCount + (addVerticesCount >> 1) > _maxVertices
+		|| _command->_triangles->indexCount + addTrianglesCount > _maxTriangles
+	) {
+		this->flush(max(addVerticesCount >> 1, _maxVertices), max(addTrianglesCount, _maxTriangles));
+		_texture = addTexture;
+		_blendMode = blendMode;
+	}
+
+	TrianglesCommand::Triangles* triangles = _command->_triangles;
+	for (int i = 0; i < addTrianglesCount; ++i, ++triangles->indexCount)
+		triangles->indices[triangles->indexCount] = addTriangles[i] + triangles->vertCount;
+
+	for (int i = 0; i < addVerticesCount; i += 2, ++triangles->vertCount) {
+		V3F_C4B_T2F* vertex = triangles->verts + triangles->vertCount;
+		vertex->vertices.x = addVertices[i];
+		vertex->vertices.y = addVertices[i + 1];
+		vertex->colors = color;
+		vertex->texCoords.u = uvs[i];
+		vertex->texCoords.v = uvs[i + 1];
+	}
+}
+
+void SkeletonBatch::flush (int maxVertices, int maxTriangles) {
+	if (!_command->_triangles->vertCount) return;
+
+	BlendFunc blendFunc;
+	switch (_blendMode) {
+	case SP_BLEND_MODE_ADDITIVE:
+		blendFunc.src = _premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
+		blendFunc.dst = GL_ONE;
+		break;
+	case SP_BLEND_MODE_MULTIPLY:
+		blendFunc.src = GL_DST_COLOR;
+		blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
+		break;
+	case SP_BLEND_MODE_SCREEN:
+		blendFunc.src = GL_ONE;
+		blendFunc.dst = GL_ONE_MINUS_SRC_COLOR;
+		break;
+	default:
+		blendFunc.src = _premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
+		blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
+	}
+
+	_command->_trianglesCommand->init(_globalZOrder, _texture->getName(), _glProgramState, blendFunc, *_command->_triangles,
+		*_transform, _transformFlags);
+   _renderer->addCommand(_command->_trianglesCommand);
+
+	if (!_command->_next) _command->_next = new Command(maxVertices, maxTriangles);
+	_command = _command->_next;
+
+	// If not as large as required, insert new command.
+	if (_command->_maxVertices < maxVertices || _command->_maxTriangles < maxTriangles) {
+		Command* next = _command->_next;
+		_command = new Command(maxVertices, maxTriangles);
+		_command->_next = next;
+	}
+
+	_command->_triangles->vertCount = 0;
+	_command->_triangles->indexCount = 0;
+}
+
+SkeletonBatch::Command::Command (int maxVertices, int maxTriangles) :
+	_maxVertices(maxVertices), _maxTriangles(maxTriangles), _next(nullptr)
+{
+	_trianglesCommand = new TrianglesCommand();
+
+	_triangles = new TrianglesCommand::Triangles();
+	_triangles->verts = new V3F_C4B_T2F[maxVertices];
+	_triangles->indices = new GLushort[maxTriangles];
+}
+
+SkeletonBatch::Command::~Command () {
+	delete [] _triangles->indices;
+	delete [] _triangles->verts;
+	delete _triangles;
+
+	delete _trianglesCommand;
+}
+
+}

+ 101 - 0
spine-cocos2dx/3/src/spine/SkeletonBatch.h

@@ -0,0 +1,101 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) 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.
+ *****************************************************************************/
+
+#ifndef SPINE_SKELETONBATCH_H_
+#define SPINE_SKELETONBATCH_H_
+
+#include <spine/spine.h>
+#include "cocos2d.h"
+
+namespace spine {
+
+/* Batches attachment geometry and issues one or more TrianglesCommands per skeleton. */
+class SkeletonBatch : public cocos2d::Ref {
+public:
+	/* Sets the default size of each TrianglesCommand. Best to call before getInstance is called for the first time. Default is 64, 192.
+	 * TrianglesCommands may be larger than the specified sizes if required to hold the geometry for a single attachment. */
+	static void setCommandSize (int maxVertices, int maxTriangles);
+
+	static SkeletonBatch* getInstance ();
+
+	void update (float delta);
+
+	void setRendererState (cocos2d::Renderer* renderer, const cocos2d::Mat4* transform, uint32_t transformFlags,
+		float globalZOrder, cocos2d::GLProgramState* glProgramState, bool premultipliedAlpha);
+
+	void add (const cocos2d::Texture2D* texture,
+		const float* vertices, const float* uvs, int verticesCount,
+		const int* triangles, int trianglesCount,
+		const cocos2d::Color4B& color, spBlendMode blendMode);
+
+	void flush () {
+		flush(_maxVertices, _maxTriangles);
+	}
+
+protected:
+	SkeletonBatch (int maxVertices, int maxTriangles);
+	virtual ~SkeletonBatch ();
+
+	void flush (int maxVertices, int maxTriangles);
+
+	class Command {
+	public:
+		Command (int maxVertices, int maxTriangles);
+		virtual ~Command ();
+
+		int _maxVertices;
+		int _maxTriangles;
+		cocos2d::TrianglesCommand* _trianglesCommand;
+		cocos2d::TrianglesCommand::Triangles* _triangles;
+		Command* _next;
+	};
+
+	int _maxVertices;
+	int _maxTriangles;
+	Command* _firstCommand;
+	Command* _command;
+
+	// Renderer state.
+	cocos2d::Renderer* _renderer;
+	const cocos2d::Mat4* _transform;
+	uint32_t _transformFlags;
+	float _globalZOrder;
+	cocos2d::GLProgramState* _glProgramState;
+	bool _premultipliedAlpha;
+
+	// Batch state.
+	const cocos2d::Texture2D* _texture;
+	spBlendMode _blendMode;
+};
+
+}
+
+#endif // SPINE_SKELETONBATCH_H_

+ 54 - 72
spine-cocos2dx/3/src/spine/SkeletonRenderer.cpp

@@ -32,7 +32,7 @@
 #include <spine/SkeletonRenderer.h>
 #include <spine/spine-cocos2dx.h>
 #include <spine/extension.h>
-#include <spine/PolygonBatch.h>
+#include <spine/SkeletonBatch.h>
 #include <algorithm>
 
 USING_NS_CC;
@@ -64,13 +64,10 @@ SkeletonRenderer* SkeletonRenderer::createWithFile (const std::string& skeletonD
 void SkeletonRenderer::initialize () {
 	_worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh.
 
-	_batch = PolygonBatch::createWithCapacity(2000); // Max number of vertices and triangles per batch.
-	_batch->retain();
-
 	_blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
 	setOpacityModifyRGB(true);
 
-	setGLProgram(ShaderCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
+	setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP));
 }
 
 void SkeletonRenderer::setSkeletonData (spSkeletonData *skeletonData, bool ownsSkeletonData) {
@@ -101,7 +98,6 @@ SkeletonRenderer::~SkeletonRenderer () {
 	if (_ownsSkeletonData) spSkeletonData_dispose(_skeleton->data);
 	if (_atlas) spAtlas_dispose(_atlas);
 	spSkeleton_dispose(_skeleton);
-	_batch->release();
 	FREE(_worldVertices);
 }
 
@@ -144,13 +140,8 @@ void SkeletonRenderer::update (float deltaTime) {
 }
 
 void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) {
-	_drawCommand.init(_globalZOrder);
-	_drawCommand.func = CC_CALLBACK_0(SkeletonRenderer::drawSkeleton, this, transform, transformFlags);
-	renderer->addCommand(&_drawCommand);
-}
-
-void SkeletonRenderer::drawSkeleton (const Mat4 &transform, uint32_t transformFlags) {
-	getGLProgramState()->apply(transform);
+	SkeletonBatch* batch = SkeletonBatch::getInstance();
+	batch->setRendererState(renderer, &transform, transformFlags, _globalZOrder, getGLProgramState(), _premultipliedAlpha);
 
 	Color3B nodeColor = getColor();
 	_skeleton->r = nodeColor.r / (float)255;
@@ -215,77 +206,68 @@ void SkeletonRenderer::drawSkeleton (const Mat4 &transform, uint32_t transformFl
 		default: ;
 		} 
 		if (texture) {
-			if (slot->data->blendMode != blendMode) {
-				_batch->flush();
-				blendMode = slot->data->blendMode;
-				switch (slot->data->blendMode) {
-				case SP_BLEND_MODE_ADDITIVE:
-					GL::blendFunc(_premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE);
-					break;
-				case SP_BLEND_MODE_MULTIPLY:
-					GL::blendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
-					break;
-				case SP_BLEND_MODE_SCREEN:
-					GL::blendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
-					break;
-				default:
-					GL::blendFunc(_blendFunc.src, _blendFunc.dst);
-				}
-			}
 			color.a = _skeleton->a * slot->a * a * 255;
 			float multiplier = _premultipliedAlpha ? color.a : 255;
 			color.r = _skeleton->r * slot->r * r * multiplier;
 			color.g = _skeleton->g * slot->g * g * multiplier;
 			color.b = _skeleton->b * slot->b * b * multiplier;
-			_batch->add(texture, _worldVertices, uvs, verticesCount, triangles, trianglesCount, &color);
+			batch->add(texture, _worldVertices, uvs, verticesCount, triangles, trianglesCount, color, slot->data->blendMode);
 		}
 	}
-	_batch->flush();
+	batch->flush();
 
 	if (_debugSlots || _debugBones) {
-		Director* director = Director::getInstance();
-		director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
-		director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
-
-		if (_debugSlots) {
-			// Slots.
-			DrawPrimitives::setDrawColor4B(0, 0, 255, 255);
-			glLineWidth(1);
-			Vec2 points[4];
-			V3F_C4B_T2F_Quad quad;
-			for (int i = 0, n = _skeleton->slotsCount; i < n; i++) {
-				spSlot* slot = _skeleton->drawOrder[i];
-				if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
-				spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
-				spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices);
-				points[0] = Vec2(_worldVertices[0], _worldVertices[1]);
-				points[1] = Vec2(_worldVertices[2], _worldVertices[3]);
-				points[2] = Vec2(_worldVertices[4], _worldVertices[5]);
-				points[3] = Vec2(_worldVertices[6], _worldVertices[7]);
-				DrawPrimitives::drawPoly(points, 4, true);
-			}
+		_debugCommand.init(_globalZOrder);
+		_debugCommand.func = CC_CALLBACK_0(SkeletonRenderer::drawDebug, this, transform, transformFlags);
+		renderer->addCommand(&_debugCommand);
+	}
+}
+
+void SkeletonRenderer::drawDebug (const Mat4 &transform, uint32_t transformFlags) {
+	getGLProgramState()->apply(transform);
+
+	Director* director = Director::getInstance();
+	director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
+	director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
+
+	if (_debugSlots) {
+		// Slots.
+		DrawPrimitives::setDrawColor4B(0, 0, 255, 255);
+		glLineWidth(1);
+		Vec2 points[4];
+		V3F_C4B_T2F_Quad quad;
+		for (int i = 0, n = _skeleton->slotsCount; i < n; i++) {
+			spSlot* slot = _skeleton->drawOrder[i];
+			if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
+			spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
+			spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices);
+			points[0] = Vec2(_worldVertices[0], _worldVertices[1]);
+			points[1] = Vec2(_worldVertices[2], _worldVertices[3]);
+			points[2] = Vec2(_worldVertices[4], _worldVertices[5]);
+			points[3] = Vec2(_worldVertices[6], _worldVertices[7]);
+			DrawPrimitives::drawPoly(points, 4, true);
+		}
+	}
+	if (_debugBones) {
+		// Bone lengths.
+		glLineWidth(2);
+		DrawPrimitives::setDrawColor4B(255, 0, 0, 255);
+		for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
+			spBone *bone = _skeleton->bones[i];
+			float x = bone->data->length * bone->a + bone->worldX;
+			float y = bone->data->length * bone->c + bone->worldY;
+			DrawPrimitives::drawLine(Vec2(bone->worldX, bone->worldY), Vec2(x, y));
 		}
-		if (_debugBones) {
-			// Bone lengths.
-			glLineWidth(2);
-			DrawPrimitives::setDrawColor4B(255, 0, 0, 255);
-			for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
-				spBone *bone = _skeleton->bones[i];
-				float x = bone->data->length * bone->a + bone->worldX;
-				float y = bone->data->length * bone->c + bone->worldY;
-				DrawPrimitives::drawLine(Vec2(bone->worldX, bone->worldY), Vec2(x, y));
-			}
-			// Bone origins.
-			DrawPrimitives::setPointSize(4);
-			DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue.
-			for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
-				spBone *bone = _skeleton->bones[i];
-				DrawPrimitives::drawPoint(Vec2(bone->worldX, bone->worldY));
-				if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255);
-			}
+		// Bone origins.
+		DrawPrimitives::setPointSize(4);
+		DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue.
+		for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
+			spBone *bone = _skeleton->bones[i];
+			DrawPrimitives::drawPoint(Vec2(bone->worldX, bone->worldY));
+			if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255);
 		}
-		director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
 	}
+	director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
 }
 
 Texture2D* SkeletonRenderer::getTexture (spRegionAttachment* attachment) const {

+ 5 - 4
spine-cocos2dx/3/src/spine/SkeletonRenderer.h

@@ -39,16 +39,17 @@ namespace spine {
 
 class PolygonBatch;
 
-/** Draws a skeleton. */
+/* Draws a skeleton. */
 class SkeletonRenderer: public cocos2d::Node, public cocos2d::BlendProtocol {
 public:
+	CREATE_FUNC(SkeletonRenderer);
 	static SkeletonRenderer* createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
 	static SkeletonRenderer* createWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale = 1);
 	static SkeletonRenderer* createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
 
 	virtual void update (float deltaTime) override;
 	virtual void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags) override;
-	virtual void drawSkeleton (const cocos2d::Mat4& transform, uint32_t transformFlags);
+	virtual void drawDebug (const cocos2d::Mat4& transform, uint32_t transformFlags);
 	virtual cocos2d::Rect getBoundingBox () const override;
 	virtual void onEnter () override;
 	virtual void onExit () override;
@@ -58,6 +59,7 @@ public:
 	void setTimeScale(float scale);
 	float getTimeScale() const;
 
+	/*  */
 	void setDebugSlotsEnabled(bool enabled);
 	bool getDebugSlotsEnabled() const;
 
@@ -119,9 +121,8 @@ protected:
 
 	bool _ownsSkeletonData;
 	spAtlas* _atlas;
-	cocos2d::CustomCommand _drawCommand;
+	cocos2d::CustomCommand _debugCommand;
 	cocos2d::BlendFunc _blendFunc;
-	PolygonBatch* _batch;
 	float* _worldVertices;
 	bool _premultipliedAlpha;
 	spSkeleton* _skeleton;