diff --git a/CHANGELOG.md b/CHANGELOG.md index 55dd3dd5f..335e2a4f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ * Added support for vertex effects. See `RaptorExample.cpp`. * Added ETC1 alpha support, thanks @halx99! Does not work when two color tint is enabled. * Added `spAtlasPage_setCustomTextureLoader()` which let's you do texture loading manually. Thanks @jareguo. + * Added `SkeletonRenderer:setSlotsRange()` and `SkeletonRenderer::createWithSkeleton()`. This allows you to split rendering of a skeleton up into multiple parts, and render other nodes in between. See `SkeletonRendererSeparatorExample.cpp` for an example. ### Cocos2d-Objc * Fixed renderer to work with 3.6 changes diff --git a/spine-cocos2dx/example/Classes/AppDelegate.cpp b/spine-cocos2dx/example/Classes/AppDelegate.cpp index 26023f9d6..3cad127b2 100644 --- a/spine-cocos2dx/example/Classes/AppDelegate.cpp +++ b/spine-cocos2dx/example/Classes/AppDelegate.cpp @@ -35,7 +35,8 @@ #include "RaptorExample.h" #include "BatchingExample.h" -#include "CoinExample.h" +#include "CoinExample.h" +#include "SkeletonRendererSeparatorExample.h" #include "AppMacros.h" USING_NS_CC; @@ -99,7 +100,7 @@ bool AppDelegate::applicationDidFinishLaunching () { // create a scene. it's an autorelease object //auto scene = RaptorExample::scene(); - auto scene = BatchingExample::scene(); + auto scene = SkeletonRendererSeparatorExample::scene(); // run director->runWithScene(scene); diff --git a/spine-cocos2dx/example/Classes/SimpleCommand.cpp b/spine-cocos2dx/example/Classes/SimpleCommand.cpp deleted file mode 100644 index 1f0c6ed08..000000000 --- a/spine-cocos2dx/example/Classes/SimpleCommand.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/****************************************************************************** - * 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. - *****************************************************************************/ - -#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/example/Classes/SkeletonRendererSeparatorExample.cpp b/spine-cocos2dx/example/Classes/SkeletonRendererSeparatorExample.cpp new file mode 100644 index 000000000..5ebdfc4eb --- /dev/null +++ b/spine-cocos2dx/example/Classes/SkeletonRendererSeparatorExample.cpp @@ -0,0 +1,96 @@ +/****************************************************************************** + * 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. + *****************************************************************************/ + +#include "SkeletonRendererSeparatorExample.h" +#include "GoblinsExample.h" + +USING_NS_CC; +using namespace spine; + +Scene* SkeletonRendererSeparatorExample::scene () { + Scene *scene = Scene::create(); + scene->addChild(SkeletonRendererSeparatorExample::create()); + return scene; +} + +bool SkeletonRendererSeparatorExample::init () { + if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false; + + // Spineboy's back, which will manage the animation and GPU resources + // will render only the front slots of Spineboy + backNode = SkeletonAnimation::createWithJsonFile("spineboy-ess.json", "spineboy.atlas", 0.6f); + backNode->setMix("walk", "jump", 0.4); + backNode->setAnimation(0, "walk", true); + backNode->setSlotsRange(backNode->findSlot("rear-upper-arm")->data->index, backNode->findSlot("rear-shin")->data->index); + backNode->setPosition(Vec2(_contentSize.width / 2, 20)); + + // A simple rectangle to go between the front and back slots of Spineboy + betweenNode = DrawNode::create(); + Vec2 rect[4]; + rect[0] = Vec2(0, 0); + rect[1] = Vec2(40, 0); + rect[2] = Vec2(40, 200); + rect[3] = Vec2(0, 200); + betweenNode->drawPolygon(rect, 4, Color4F(1, 0, 0, 1), 1, Color4F(1, 0, 0, 1)); + betweenNode->setPosition(Vec2(_contentSize.width / 2 + 30, 20)); + + // Spineboy's front, doesn't manage any skeleton, animation or GPU resources, but simply + // renders the back slots of Spineboy. The skeleton, animatio state and GPU resources + // are shared with the front node! + frontNode = SkeletonRenderer::createWithSkeleton(backNode->getSkeleton()); + frontNode->setSlotsRange(frontNode->findSlot("neck")->data->index, -1); + frontNode->setPosition(Vec2(_contentSize.width / 2, 20)); + + // Add the front, between and back node in the correct order to this scene + addChild(backNode); + addChild(betweenNode); + addChild(frontNode); + + scheduleUpdate(); + + EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create(); + listener->onTouchBegan = [this] (Touch* touch, Event* event) -> bool { + if (!backNode->getDebugBonesEnabled()) + backNode->setDebugBonesEnabled(true); + else if (backNode->getTimeScale() == 1) + backNode->setTimeScale(0.3f); + else + Director::getInstance()->replaceScene(GoblinsExample::scene()); + return true; + }; + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); + + return true; +} + +void SkeletonRendererSeparatorExample::update (float deltaTime) { + // Test releasing memory. + // Director::getInstance()->replaceScene(SpineboyExample::scene()); +} diff --git a/spine-cocos2dx/example/Classes/SimpleCommand.h b/spine-cocos2dx/example/Classes/SkeletonRendererSeparatorExample.h similarity index 79% rename from spine-cocos2dx/example/Classes/SimpleCommand.h rename to spine-cocos2dx/example/Classes/SkeletonRendererSeparatorExample.h index 7d6ac09fb..328c1d0ff 100644 --- a/spine-cocos2dx/example/Classes/SimpleCommand.h +++ b/spine-cocos2dx/example/Classes/SkeletonRendererSeparatorExample.h @@ -28,23 +28,27 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef _SIMPLECOMMAND_H_ -#define _SIMPLECOMMAND_H_ +#ifndef _SKELETONRENDERERSEPARATOREXAMPLE_H_ +#define _SKELETONRENDERERSEPARATOREXAMPLE_H_ #include "cocos2d.h" +#include - -class SimpleCommand : public cocos2d::Node { +class SkeletonRendererSeparatorExample : public cocos2d::LayerColor { public: static cocos2d::Scene* scene (); + CREATE_FUNC (SkeletonRendererSeparatorExample); + virtual bool init (); - virtual void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags) override; - CREATE_FUNC (SimpleCommand); + virtual void update (float deltaTime); -protected: - cocos2d::Texture2D* _texture; +private: + spine::SkeletonAnimation* backNode; + spine::SkeletonRenderer* frontNode; + cocos2d::DrawNode* betweenNode; + }; -#endif // _SIMPLECOMMAND_H_ +#endif // _SKELETONRENDERERSEPARATOREXAMPLE_H_ diff --git a/spine-cocos2dx/example/proj.ios_mac/spine-cocos2d-x.xcodeproj/project.pbxproj b/spine-cocos2dx/example/proj.ios_mac/spine-cocos2d-x.xcodeproj/project.pbxproj index 8b6a40892..e4bb73140 100644 --- a/spine-cocos2dx/example/proj.ios_mac/spine-cocos2d-x.xcodeproj/project.pbxproj +++ b/spine-cocos2dx/example/proj.ios_mac/spine-cocos2d-x.xcodeproj/project.pbxproj @@ -52,7 +52,6 @@ 76AAA3C11D180F7C00C54FCB /* BatchingExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3B61D180F7C00C54FCB /* BatchingExample.cpp */; }; 76AAA3C21D180F7C00C54FCB /* GoblinsExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3B81D180F7C00C54FCB /* GoblinsExample.cpp */; }; 76AAA3C31D180F7C00C54FCB /* RaptorExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BA1D180F7C00C54FCB /* RaptorExample.cpp */; }; - 76AAA3C41D180F7C00C54FCB /* SimpleCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BC1D180F7C00C54FCB /* SimpleCommand.cpp */; }; 76AAA3C51D180F7C00C54FCB /* SpineboyExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BE1D180F7C00C54FCB /* SpineboyExample.cpp */; }; 76AAA40C1D18106000C54FCB /* AttachmentVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA4001D18106000C54FCB /* AttachmentVertices.cpp */; }; 76AAA40D1D18106000C54FCB /* Cocos2dAttachmentLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA4021D18106000C54FCB /* Cocos2dAttachmentLoader.cpp */; }; @@ -81,12 +80,12 @@ 76AAA4411D1811B000C54FCB /* GoblinsExample.h in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3B91D180F7C00C54FCB /* GoblinsExample.h */; }; 76AAA4421D1811B000C54FCB /* RaptorExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BA1D180F7C00C54FCB /* RaptorExample.cpp */; }; 76AAA4431D1811B000C54FCB /* RaptorExample.h in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BB1D180F7C00C54FCB /* RaptorExample.h */; }; - 76AAA4441D1811B000C54FCB /* SimpleCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BC1D180F7C00C54FCB /* SimpleCommand.cpp */; }; - 76AAA4451D1811B000C54FCB /* SimpleCommand.h in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BD1D180F7C00C54FCB /* SimpleCommand.h */; }; 76AAA4461D1811B000C54FCB /* SpineboyExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BE1D180F7C00C54FCB /* SpineboyExample.cpp */; }; 76AAA4471D1811B000C54FCB /* SpineboyExample.h in Sources */ = {isa = PBXBuildFile; fileRef = 76AAA3BF1D180F7C00C54FCB /* SpineboyExample.h */; }; 76AAA4571D18132D00C54FCB /* common in Resources */ = {isa = PBXBuildFile; fileRef = 76AAA4521D18132D00C54FCB /* common */; }; 76AAA4581D18132D00C54FCB /* common in Resources */ = {isa = PBXBuildFile; fileRef = 76AAA4521D18132D00C54FCB /* common */; }; + 76D1BFE02029E35200A0272D /* SkeletonRendererSeparatorExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76D1BFDF2029E35200A0272D /* SkeletonRendererSeparatorExample.cpp */; }; + 76D1BFE12029E37700A0272D /* SkeletonRendererSeparatorExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76D1BFDF2029E35200A0272D /* SkeletonRendererSeparatorExample.cpp */; }; 76D520DA1EB3611300572471 /* ClippingAttachment.c in Sources */ = {isa = PBXBuildFile; fileRef = 76D520D71EB3611300572471 /* ClippingAttachment.c */; }; 76D520DB1EB3611300572471 /* SkeletonClipping.c in Sources */ = {isa = PBXBuildFile; fileRef = 76D520D81EB3611300572471 /* SkeletonClipping.c */; }; 76D520DC1EB3611300572471 /* Triangulator.c in Sources */ = {isa = PBXBuildFile; fileRef = 76D520D91EB3611300572471 /* Triangulator.c */; }; @@ -276,8 +275,6 @@ 76AAA3B91D180F7C00C54FCB /* GoblinsExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GoblinsExample.h; sourceTree = ""; }; 76AAA3BA1D180F7C00C54FCB /* RaptorExample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RaptorExample.cpp; sourceTree = ""; }; 76AAA3BB1D180F7C00C54FCB /* RaptorExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RaptorExample.h; sourceTree = ""; }; - 76AAA3BC1D180F7C00C54FCB /* SimpleCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleCommand.cpp; sourceTree = ""; }; - 76AAA3BD1D180F7C00C54FCB /* SimpleCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleCommand.h; sourceTree = ""; }; 76AAA3BE1D180F7C00C54FCB /* SpineboyExample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpineboyExample.cpp; sourceTree = ""; }; 76AAA3BF1D180F7C00C54FCB /* SpineboyExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpineboyExample.h; sourceTree = ""; }; 76AAA4001D18106000C54FCB /* AttachmentVertices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AttachmentVertices.cpp; path = ../../src/spine/AttachmentVertices.cpp; sourceTree = ""; }; @@ -293,6 +290,8 @@ 76AAA40A1D18106000C54FCB /* spine-cocos2dx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "spine-cocos2dx.cpp"; path = "../../src/spine/spine-cocos2dx.cpp"; sourceTree = ""; }; 76AAA40B1D18106000C54FCB /* spine-cocos2dx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "spine-cocos2dx.h"; path = "../../src/spine/spine-cocos2dx.h"; sourceTree = ""; }; 76AAA4521D18132D00C54FCB /* common */ = {isa = PBXFileReference; lastKnownFileType = folder; path = common; sourceTree = ""; }; + 76D1BFDE2029E35100A0272D /* SkeletonRendererSeparatorExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkeletonRendererSeparatorExample.h; sourceTree = ""; }; + 76D1BFDF2029E35200A0272D /* SkeletonRendererSeparatorExample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SkeletonRendererSeparatorExample.cpp; sourceTree = ""; }; 76D520D71EB3611300572471 /* ClippingAttachment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ClippingAttachment.c; path = "../../../spine-c/spine-c/src/spine/ClippingAttachment.c"; sourceTree = ""; }; 76D520D81EB3611300572471 /* SkeletonClipping.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SkeletonClipping.c; path = "../../../spine-c/spine-c/src/spine/SkeletonClipping.c"; sourceTree = ""; }; 76D520D91EB3611300572471 /* Triangulator.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Triangulator.c; path = "../../../spine-c/spine-c/src/spine/Triangulator.c"; sourceTree = ""; }; @@ -483,6 +482,8 @@ 46880B8319C43A87006E1F66 /* Classes */ = { isa = PBXGroup; children = ( + 76D1BFDF2029E35200A0272D /* SkeletonRendererSeparatorExample.cpp */, + 76D1BFDE2029E35100A0272D /* SkeletonRendererSeparatorExample.h */, 76D520E41EB362DD00572471 /* CoinExample.cpp */, 76D520E51EB362DD00572471 /* CoinExample.h */, 76F5BD531D2BD7D3005917E5 /* TankExample.cpp */, @@ -496,8 +497,6 @@ 76AAA3B91D180F7C00C54FCB /* GoblinsExample.h */, 76AAA3BA1D180F7C00C54FCB /* RaptorExample.cpp */, 76AAA3BB1D180F7C00C54FCB /* RaptorExample.h */, - 76AAA3BC1D180F7C00C54FCB /* SimpleCommand.cpp */, - 76AAA3BD1D180F7C00C54FCB /* SimpleCommand.h */, 76AAA3BE1D180F7C00C54FCB /* SpineboyExample.cpp */, 76AAA3BF1D180F7C00C54FCB /* SpineboyExample.h */, ); @@ -763,6 +762,7 @@ files = ( 76F28CCA1DEC7EBB00CDE54D /* SkeletonJson.c in Sources */, 76AAA40C1D18106000C54FCB /* AttachmentVertices.cpp in Sources */, + 76D1BFE02029E35200A0272D /* SkeletonRendererSeparatorExample.cpp in Sources */, 76F28CC81DEC7EBB00CDE54D /* SkeletonBounds.c in Sources */, 76F28CB71DEC7EBB00CDE54D /* AttachmentLoader.c in Sources */, 76F5BD551D2BD7D3005917E5 /* TankExample.cpp in Sources */, @@ -785,7 +785,6 @@ 76AAA3C01D180F7C00C54FCB /* AppDelegate.cpp in Sources */, 76FAC18D1E3F97D2001CCC8C /* PointAttachment.c in Sources */, 76F28CC31DEC7EBB00CDE54D /* PathConstraint.c in Sources */, - 76AAA3C41D180F7C00C54FCB /* SimpleCommand.cpp in Sources */, 503AE10017EB989F00D1A890 /* AppController.mm in Sources */, 76F28CC11DEC7EBB00CDE54D /* MeshAttachment.c in Sources */, 76F28CC01DEC7EBB00CDE54D /* Json.c in Sources */, @@ -825,6 +824,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 76D1BFE12029E37700A0272D /* SkeletonRendererSeparatorExample.cpp in Sources */, 76FB15111F0139B400C5377F /* VertexEffect.c in Sources */, 76D520E71EB3634600572471 /* CoinExample.cpp in Sources */, 76D520E31EB3625B00572471 /* Array.c in Sources */, @@ -878,8 +878,6 @@ 76AAA4411D1811B000C54FCB /* GoblinsExample.h in Sources */, 76AAA4421D1811B000C54FCB /* RaptorExample.cpp in Sources */, 76AAA4431D1811B000C54FCB /* RaptorExample.h in Sources */, - 76AAA4441D1811B000C54FCB /* SimpleCommand.cpp in Sources */, - 76AAA4451D1811B000C54FCB /* SimpleCommand.h in Sources */, 76AAA4461D1811B000C54FCB /* SpineboyExample.cpp in Sources */, 76AAA4471D1811B000C54FCB /* SpineboyExample.h in Sources */, 76AAA4121D18119F00C54FCB /* AttachmentVertices.cpp in Sources */, diff --git a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp index df80160a1..b56fbf030 100644 --- a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp +++ b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp @@ -64,6 +64,12 @@ void SkeletonRenderer::destroyScratchBuffers() { worldVerticesLength = 0; } } + +SkeletonRenderer* SkeletonRenderer::createWithSkeleton(spSkeleton* skeleton, bool ownsSkeleton, bool ownsSkeletonData) { + SkeletonRenderer* node = new SkeletonRenderer(skeleton, ownsSkeleton, ownsSkeletonData); + node->autorelease(); + return node; +} SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) { SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData); @@ -135,35 +141,48 @@ void SkeletonRenderer::setSkeletonData (spSkeletonData *skeletonData, bool ownsS } SkeletonRenderer::SkeletonRenderer () - : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr) { + : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr), _startSlotIndex(-1), _endSlotIndex(-1) { +} + +SkeletonRenderer::SkeletonRenderer(spSkeleton* skeleton, bool ownsSkeleton, bool ownsSkeletonData) + : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr), _startSlotIndex(-1), _endSlotIndex(-1) { + initWithSkeleton(skeleton, ownsSkeleton, ownsSkeletonData); } SkeletonRenderer::SkeletonRenderer (spSkeletonData *skeletonData, bool ownsSkeletonData) - : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr) { + : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr), _startSlotIndex(-1), _endSlotIndex(-1) { initWithData(skeletonData, ownsSkeletonData); } SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, spAtlas* atlas, float scale) - : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr) { + : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr), _startSlotIndex(-1), _endSlotIndex(-1) { initWithJsonFile(skeletonDataFile, atlas, scale); } SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale) - : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr) { + : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr), _startSlotIndex(-1), _endSlotIndex(-1) { initWithJsonFile(skeletonDataFile, atlasFile, scale); } SkeletonRenderer::~SkeletonRenderer () { if (_ownsSkeletonData) spSkeletonData_dispose(_skeleton->data); - spSkeleton_dispose(_skeleton); + if (_ownsSkeleton) spSkeleton_dispose(_skeleton); if (_atlas) spAtlas_dispose(_atlas); if (_attachmentLoader) spAttachmentLoader_dispose(_attachmentLoader); spSkeletonClipping_dispose(_clipper); } +void SkeletonRenderer::initWithSkeleton(spSkeleton* skeleton, bool ownsSkeleton, bool ownsSkeletonData) { + _skeleton = skeleton; + _ownsSkeleton = ownsSkeleton; + _ownsSkeletonData = ownsSkeletonData; + + initialize(); +} + void SkeletonRenderer::initWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) { + _ownsSkeleton = true; setSkeletonData(skeletonData, ownsSkeletonData); - initialize(); } @@ -177,6 +196,7 @@ void SkeletonRenderer::initWithJsonFile (const std::string& skeletonDataFile, sp CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data."); spSkeletonJson_dispose(json); + _ownsSkeleton = true; setSkeletonData(skeletonData, true); initialize(); @@ -194,6 +214,7 @@ void SkeletonRenderer::initWithJsonFile (const std::string& skeletonDataFile, co CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data file."); spSkeletonJson_dispose(json); + _ownsSkeleton = true; setSkeletonData(skeletonData, true); initialize(); @@ -208,7 +229,7 @@ void SkeletonRenderer::initWithBinaryFile (const std::string& skeletonDataFile, spSkeletonData* skeletonData = spSkeletonBinary_readSkeletonDataFile(binary, skeletonDataFile.c_str()); CCASSERT(skeletonData, binary->error ? binary->error : "Error reading skeleton data file."); spSkeletonBinary_dispose(binary); - + _ownsSkeleton = true; setSkeletonData(skeletonData, true); initialize(); @@ -225,7 +246,7 @@ void SkeletonRenderer::initWithBinaryFile (const std::string& skeletonDataFile, spSkeletonData* skeletonData = spSkeletonBinary_readSkeletonDataFile(binary, skeletonDataFile.c_str()); CCASSERT(skeletonData, binary->error ? binary->error : "Error reading skeleton data file."); spSkeletonBinary_dispose(binary); - + _ownsSkeleton = true; setSkeletonData(skeletonData, true); initialize(); @@ -234,7 +255,7 @@ void SkeletonRenderer::initWithBinaryFile (const std::string& skeletonDataFile, void SkeletonRenderer::update (float deltaTime) { Node::update(deltaTime); - spSkeleton_update(_skeleton, deltaTime * _timeScale); + if (_ownsSkeleton) spSkeleton_update(_skeleton, deltaTime * _timeScale); } void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) { @@ -255,8 +276,23 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t float darkPremultipliedAlpha = _premultipliedAlpha ? 255 : 0; AttachmentVertices* attachmentVertices = nullptr; TwoColorTrianglesCommand* lastTwoColorTrianglesCommand = nullptr; - for (int i = 0, n = _skeleton->slotsCount; i < n; ++i) { + bool inRange = _startSlotIndex != -1 || _endSlotIndex != -1 ? false : true; + for (int i = 0, n = _skeleton->slotsCount; i < n; ++i) { spSlot* slot = _skeleton->drawOrder[i]; + + if (_startSlotIndex >= 0 && _startSlotIndex == slot->data->index) { + inRange = true; + } + + if (!inRange) { + spSkeletonClipping_clipEnd(_clipper, slot); + continue; + } + + if (_endSlotIndex >= 0 && _endSlotIndex == slot->data->index) { + inRange = false; + } + if (!slot->attachment) { spSkeletonClipping_clipEnd(_clipper, slot); continue; @@ -780,6 +816,11 @@ bool SkeletonRenderer::isTwoColorTint() { void SkeletonRenderer::setVertexEffect(spVertexEffect *effect) { this->_effect = effect; } + +void SkeletonRenderer::setSlotsRange(int startSlotIndex, int endSlotIndex) { + this->_startSlotIndex = startSlotIndex; + this->_endSlotIndex = endSlotIndex; +} spSkeleton* SkeletonRenderer::getSkeleton () { return _skeleton; diff --git a/spine-cocos2dx/src/spine/SkeletonRenderer.h b/spine-cocos2dx/src/spine/SkeletonRenderer.h index 426cba1aa..3f41e4a5d 100644 --- a/spine-cocos2dx/src/spine/SkeletonRenderer.h +++ b/spine-cocos2dx/src/spine/SkeletonRenderer.h @@ -42,6 +42,7 @@ class AttachmentVertices; class SkeletonRenderer: public cocos2d::Node, public cocos2d::BlendProtocol { public: CREATE_FUNC(SkeletonRenderer); + static SkeletonRenderer* createWithSkeleton(spSkeleton* skeleton, bool ownsSkeleton = false, bool ownsSkeletonData = false); 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); @@ -102,6 +103,9 @@ public: /* Sets the vertex effect to be used, set to 0 to disable vertex effects */ void setVertexEffect(spVertexEffect* effect); + + /* Sets the range of slots that should be rendered. Use -1, -1 to clear the range */ + void setSlotsRange(int startSlotIndex, int endSlotIndex); // --- BlendProtocol virtual void setBlendFunc (const cocos2d::BlendFunc& blendFunc)override; @@ -114,12 +118,14 @@ public: CC_CONSTRUCTOR_ACCESS: SkeletonRenderer (); + SkeletonRenderer(spSkeleton* skeleton, bool ownsSkeleton = false, bool ownsSkeletonData = false); SkeletonRenderer (spSkeletonData* skeletonData, bool ownsSkeletonData = false); SkeletonRenderer (const std::string& skeletonDataFile, spAtlas* atlas, float scale = 1); SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1); virtual ~SkeletonRenderer (); + void initWithSkeleton(spSkeleton* skeleton, bool ownsSkeleton = false, bool ownsSkeletonData = false); void initWithData (spSkeletonData* skeletonData, bool ownsSkeletonData = false); void initWithJsonFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale = 1); void initWithJsonFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1); @@ -135,6 +141,7 @@ protected: void setupGLProgramState(bool twoColorTintEnabled); bool _ownsSkeletonData; + bool _ownsSkeleton; spAtlas* _atlas; spAttachmentLoader* _attachmentLoader; cocos2d::CustomCommand _debugCommand; @@ -147,6 +154,9 @@ protected: bool _debugMeshes; spSkeletonClipping* _clipper; spVertexEffect* _effect; + + int _startSlotIndex; + int _endSlotIndex; }; }