From 55851f76993ab166de292ac3e93e35adb5a31ecb Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Fri, 1 Apr 2016 18:37:54 +0200 Subject: [PATCH] cocos2d-x rendering now uses TrianglesCommand for batching across scene graph nodes. --- .../3/example/Classes/AppDelegate.cpp | 2 + .../3/example/Classes/BatchingExample.cpp | 92 +++++++++ .../3/example/Classes/BatchingExample.h | 47 +++++ .../3/example/Classes/GoblinsExample.cpp | 4 - .../3/example/Classes/GoblinsExample.h | 3 +- .../3/example/Classes/RaptorExample.cpp | 8 +- .../3/example/Classes/RaptorExample.h | 3 +- .../3/example/Classes/SimpleCommand.cpp | 103 ++++++++++ .../Classes/SimpleCommand.h} | 33 +--- .../3/example/Classes/SpineboyExample.cpp | 4 - .../3/example/Classes/SpineboyExample.h | 4 +- .../example/proj.win32/spine-cocos2dx.vcxproj | 6 +- .../proj.win32/spine-cocos2dx.vcxproj.filters | 18 +- spine-cocos2dx/3/src/spine/PolygonBatch.cpp | 116 ----------- .../3/src/spine/SkeletonAnimation.h | 1 + spine-cocos2dx/3/src/spine/SkeletonBatch.cpp | 182 ++++++++++++++++++ spine-cocos2dx/3/src/spine/SkeletonBatch.h | 101 ++++++++++ .../3/src/spine/SkeletonRenderer.cpp | 130 ++++++------- spine-cocos2dx/3/src/spine/SkeletonRenderer.h | 9 +- 19 files changed, 624 insertions(+), 242 deletions(-) create mode 100644 spine-cocos2dx/3/example/Classes/BatchingExample.cpp create mode 100644 spine-cocos2dx/3/example/Classes/BatchingExample.h create mode 100644 spine-cocos2dx/3/example/Classes/SimpleCommand.cpp rename spine-cocos2dx/3/{src/spine/PolygonBatch.h => example/Classes/SimpleCommand.h} (74%) delete mode 100644 spine-cocos2dx/3/src/spine/PolygonBatch.cpp create mode 100644 spine-cocos2dx/3/src/spine/SkeletonBatch.cpp create mode 100644 spine-cocos2dx/3/src/spine/SkeletonBatch.h diff --git a/spine-cocos2dx/3/example/Classes/AppDelegate.cpp b/spine-cocos2dx/3/example/Classes/AppDelegate.cpp index afca2c481..a4e47ed64 100644 --- a/spine-cocos2dx/3/example/Classes/AppDelegate.cpp +++ b/spine-cocos2dx/3/example/Classes/AppDelegate.cpp @@ -35,6 +35,7 @@ #include #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); diff --git a/spine-cocos2dx/3/example/Classes/BatchingExample.cpp b/spine-cocos2dx/3/example/Classes/BatchingExample.cpp new file mode 100644 index 000000000..ec569d58e --- /dev/null +++ b/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; +} diff --git a/spine-cocos2dx/3/example/Classes/BatchingExample.h b/spine-cocos2dx/3/example/Classes/BatchingExample.h new file mode 100644 index 000000000..499df60e8 --- /dev/null +++ b/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 + +class BatchingExample : public cocos2d::LayerColor { +public: + static cocos2d::Scene* scene (); + + CREATE_FUNC(BatchingExample); + + virtual bool init (); +}; + +#endif // _BATCHINGEXAMPLE_H_ diff --git a/spine-cocos2dx/3/example/Classes/GoblinsExample.cpp b/spine-cocos2dx/3/example/Classes/GoblinsExample.cpp index 18bc80665..3616b3d55 100644 --- a/spine-cocos2dx/3/example/Classes/GoblinsExample.cpp +++ b/spine-cocos2dx/3/example/Classes/GoblinsExample.cpp @@ -31,13 +31,9 @@ #include "GoblinsExample.h" #include "RaptorExample.h" -#include -#include -#include USING_NS_CC; using namespace spine; -using namespace std; Scene* GoblinsExample::scene () { Scene *scene = Scene::create(); diff --git a/spine-cocos2dx/3/example/Classes/GoblinsExample.h b/spine-cocos2dx/3/example/Classes/GoblinsExample.h index 8361171db..9139a9f96 100644 --- a/spine-cocos2dx/3/example/Classes/GoblinsExample.h +++ b/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; }; diff --git a/spine-cocos2dx/3/example/Classes/RaptorExample.cpp b/spine-cocos2dx/3/example/Classes/RaptorExample.cpp index c8f05ca30..bd15e4669 100644 --- a/spine-cocos2dx/3/example/Classes/RaptorExample.cpp +++ b/spine-cocos2dx/3/example/Classes/RaptorExample.cpp @@ -30,14 +30,10 @@ *****************************************************************************/ #include "RaptorExample.h" -#include "SpineboyExample.h" -#include -#include -#include +#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); diff --git a/spine-cocos2dx/3/example/Classes/RaptorExample.h b/spine-cocos2dx/3/example/Classes/RaptorExample.h index b03442aa6..3a4818165 100644 --- a/spine-cocos2dx/3/example/Classes/RaptorExample.h +++ b/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; }; diff --git a/spine-cocos2dx/3/example/Classes/SimpleCommand.cpp b/spine-cocos2dx/3/example/Classes/SimpleCommand.cpp new file mode 100644 index 000000000..238794b2e --- /dev/null +++ b/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); +} diff --git a/spine-cocos2dx/3/src/spine/PolygonBatch.h b/spine-cocos2dx/3/example/Classes/SimpleCommand.h similarity index 74% rename from spine-cocos2dx/3/src/spine/PolygonBatch.h rename to spine-cocos2dx/3/example/Classes/SimpleCommand.h index 5fa028e30..328eb92ca 100644 --- a/spine-cocos2dx/3/src/spine/PolygonBatch.h +++ b/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; + + CREATE_FUNC (SimpleCommand); protected: - PolygonBatch(); - virtual ~PolygonBatch(); - bool initWithCapacity (ssize_t capacity); - - ssize_t _capacity; - cocos2d::V2F_C4B_T2F* _vertices; - int _verticesCount; - GLushort* _triangles; - int _trianglesCount; - const cocos2d::Texture2D* _texture; + cocos2d::Texture2D* _texture; }; -} - -#endif // SPINE_POLYGONBATCH_H_ +#endif // _SIMPLECOMMAND_H_ diff --git a/spine-cocos2dx/3/example/Classes/SpineboyExample.cpp b/spine-cocos2dx/3/example/Classes/SpineboyExample.cpp index 8e882b9fb..8f0c5c3eb 100644 --- a/spine-cocos2dx/3/example/Classes/SpineboyExample.cpp +++ b/spine-cocos2dx/3/example/Classes/SpineboyExample.cpp @@ -31,13 +31,9 @@ #include "SpineboyExample.h" #include "GoblinsExample.h" -#include -#include -#include USING_NS_CC; using namespace spine; -using namespace std; Scene* SpineboyExample::scene () { Scene *scene = Scene::create(); diff --git a/spine-cocos2dx/3/example/Classes/SpineboyExample.h b/spine-cocos2dx/3/example/Classes/SpineboyExample.h index d32f2e63d..4a5245c32 100644 --- a/spine-cocos2dx/3/example/Classes/SpineboyExample.h +++ b/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; }; diff --git a/spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj b/spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj index 2cea9d4b3..2ff10fdda 100644 --- a/spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj +++ b/spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj @@ -129,23 +129,25 @@ - + + - + + diff --git a/spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj.filters b/spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj.filters index 20aaddefe..4851d364d 100644 --- a/spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj.filters +++ b/spine-cocos2dx/3/example/proj.win32/spine-cocos2dx.vcxproj.filters @@ -30,9 +30,6 @@ Classes - - src - src @@ -42,6 +39,12 @@ src + + Classes + + + src + @@ -59,9 +62,6 @@ Classes - - src - src @@ -71,5 +71,11 @@ src + + Classes + + + src + \ No newline at end of file diff --git a/spine-cocos2dx/3/src/spine/PolygonBatch.cpp b/spine-cocos2dx/3/src/spine/PolygonBatch.cpp deleted file mode 100644 index 63b1bbf1b..000000000 --- a/spine-cocos2dx/3/src/spine/PolygonBatch.cpp +++ /dev/null @@ -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 -#include - -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(); -} - -} diff --git a/spine-cocos2dx/3/src/spine/SkeletonAnimation.h b/spine-cocos2dx/3/src/spine/SkeletonAnimation.h index a140e3a83..ba80c4455 100644 --- a/spine-cocos2dx/3/src/spine/SkeletonAnimation.h +++ b/spine-cocos2dx/3/src/spine/SkeletonAnimation.h @@ -47,6 +47,7 @@ typedef std::function 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); diff --git a/spine-cocos2dx/3/src/spine/SkeletonBatch.cpp b/spine-cocos2dx/3/src/spine/SkeletonBatch.cpp new file mode 100644 index 000000000..504073bdb --- /dev/null +++ b/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 +#include +#include + +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; +} + +} diff --git a/spine-cocos2dx/3/src/spine/SkeletonBatch.h b/spine-cocos2dx/3/src/spine/SkeletonBatch.h new file mode 100644 index 000000000..19904db87 --- /dev/null +++ b/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 +#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_ diff --git a/spine-cocos2dx/3/src/spine/SkeletonRenderer.cpp b/spine-cocos2dx/3/src/spine/SkeletonRenderer.cpp index 904381a42..97a1e0814 100644 --- a/spine-cocos2dx/3/src/spine/SkeletonRenderer.cpp +++ b/spine-cocos2dx/3/src/spine/SkeletonRenderer.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include 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,79 +206,70 @@ 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); - } - } - 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); - } - } - director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); + _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)); + } + // 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); +} + Texture2D* SkeletonRenderer::getTexture (spRegionAttachment* attachment) const { return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject; } diff --git a/spine-cocos2dx/3/src/spine/SkeletonRenderer.h b/spine-cocos2dx/3/src/spine/SkeletonRenderer.h index 480c9d393..e22bbedf2 100644 --- a/spine-cocos2dx/3/src/spine/SkeletonRenderer.h +++ b/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;