diff --git a/spine-cocos2dx/example/Classes/AppDelegate.cpp b/spine-cocos2dx/example/Classes/AppDelegate.cpp index 28ba80aa1..ed90b2b75 100644 --- a/spine-cocos2dx/example/Classes/AppDelegate.cpp +++ b/spine-cocos2dx/example/Classes/AppDelegate.cpp @@ -3,7 +3,7 @@ #include #include -#include "ExampleLayer.h" +#include "SpineboyExample.h" #include "AppMacros.h" USING_NS_CC; @@ -62,7 +62,7 @@ bool AppDelegate::applicationDidFinishLaunching () { director->setAnimationInterval(1.0 / 60); // create a scene. it's an autorelease object - auto scene = ExampleLayer::scene(); + auto scene = SpineboyExample::scene(); // run director->runWithScene(scene); diff --git a/spine-cocos2dx/example/Classes/GoblinsExample.cpp b/spine-cocos2dx/example/Classes/GoblinsExample.cpp new file mode 100644 index 000000000..9592e0cde --- /dev/null +++ b/spine-cocos2dx/example/Classes/GoblinsExample.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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 "GoblinsExample.h" +#include "SpineboyExample.h" +#include +#include +#include + +USING_NS_CC; +using namespace spine; +using namespace std; + +Scene* GoblinsExample::scene () { + Scene *scene = Scene::create(); + scene->addChild(GoblinsExample::create()); + return scene; +} + +bool GoblinsExample::init () { + if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false; + + skeletonNode = SkeletonAnimation::createWithFile("goblins-ffd.json", "goblins-ffd.atlas", 1.5f); + skeletonNode->setAnimation(0, "walk", true); + skeletonNode->setSkin("goblin"); + + Size windowSize = Director::getInstance()->getWinSize(); + skeletonNode->setPosition(Vector2(windowSize.width / 2, 20)); + addChild(skeletonNode); + + scheduleUpdate(); + + EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create(); + listener->onTouchBegan = [this] (Touch* touch, Event* event) -> bool { + if (!skeletonNode->debugBones) + skeletonNode->debugBones = true; + else if (skeletonNode->timeScale == 1) + skeletonNode->timeScale = 0.3f; + else + Director::getInstance()->replaceScene(SpineboyExample::scene()); + return true; + }; + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); + + return true; +} diff --git a/spine-cocos2dx/example/Classes/GoblinsExample.h b/spine-cocos2dx/example/Classes/GoblinsExample.h new file mode 100644 index 000000000..b74ecaaf8 --- /dev/null +++ b/spine-cocos2dx/example/Classes/GoblinsExample.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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 _GOBLINSEXAMPLE_H_ +#define _GOBLINSEXAMPLE_H_ + +#include "cocos2d.h" +#include + +class GoblinsExample : public cocos2d::LayerColor { +public: + static cocos2d::Scene* scene (); + + virtual bool init (); + + CREATE_FUNC (GoblinsExample); +private: + spine::SkeletonAnimation* skeletonNode; +}; + +#endif // _GOBLINSEXAMPLE_H_ diff --git a/spine-cocos2dx/example/Classes/ExampleLayer.cpp b/spine-cocos2dx/example/Classes/SpineboyExample.cpp similarity index 75% rename from spine-cocos2dx/example/Classes/ExampleLayer.cpp rename to spine-cocos2dx/example/Classes/SpineboyExample.cpp index a676d7f36..9c54fb839 100644 --- a/spine-cocos2dx/example/Classes/ExampleLayer.cpp +++ b/spine-cocos2dx/example/Classes/SpineboyExample.cpp @@ -28,7 +28,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#include "ExampleLayer.h" +#include "SpineboyExample.h" +#include "GoblinsExample.h" #include #include #include @@ -37,31 +38,29 @@ USING_NS_CC; using namespace spine; using namespace std; -Scene* ExampleLayer::scene () { +Scene* SpineboyExample::scene () { Scene *scene = Scene::create(); - scene->addChild(ExampleLayer::create()); + scene->addChild(SpineboyExample::create()); return scene; } -bool ExampleLayer::init () { +bool SpineboyExample::init () { if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false; skeletonNode = SkeletonAnimation::createWithFile("spineboy.json", "spineboy.atlas", 0.6f); - // skeletonNode->timeScale = 0.3f; - skeletonNode->debugBones = true; - - skeletonNode->startListener = [this](int trackIndex) { + + skeletonNode->startListener = [this] (int trackIndex) { spTrackEntry* entry = spAnimationState_getCurrent(skeletonNode->state, trackIndex); const char* animationName = (entry && entry->animation) ? entry->animation->name : 0; log("%d start: %s", trackIndex, animationName); }; - skeletonNode->endListener = [](int trackIndex) { + skeletonNode->endListener = [] (int trackIndex) { log("%d end", trackIndex); }; - skeletonNode->completeListener = [](int trackIndex, int loopCount) { + skeletonNode->completeListener = [] (int trackIndex, int loopCount) { log("%d complete: %d", trackIndex, loopCount); }; - skeletonNode->eventListener = [](int trackIndex, spEvent* event) { + skeletonNode->eventListener = [] (int trackIndex, spEvent* event) { log("%d event: %s, %d, %f, %s", trackIndex, event->data->name, event->intValue, event->floatValue, event->stringValue); }; @@ -71,7 +70,7 @@ bool ExampleLayer::init () { spTrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 3); skeletonNode->addAnimation(0, "run", true); - skeletonNode->setStartListener(jumpEntry, [](int trackIndex) { + skeletonNode->setStartListener(jumpEntry, [] (int trackIndex) { log("jumped!", trackIndex); }); @@ -83,11 +82,24 @@ bool ExampleLayer::init () { addChild(skeletonNode); scheduleUpdate(); + + EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create(); + listener->onTouchBegan = [this] (Touch* touch, Event* event) -> bool { + if (!skeletonNode->debugBones) + skeletonNode->debugBones = true; + else if (skeletonNode->timeScale == 1) + skeletonNode->timeScale = 0.3f; + else + Director::getInstance()->replaceScene(GoblinsExample::scene()); + return true; + }; + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); return true; } -void ExampleLayer::update (float deltaTime) { +void SpineboyExample::update (float deltaTime) { // Test releasing memory. - // Director::getInstance()->replaceScene(ExampleLayer::scene()); + // Director::getInstance()->replaceScene(SpineboyExample::scene()); } + diff --git a/spine-cocos2dx/example/Classes/ExampleLayer.h b/spine-cocos2dx/example/Classes/SpineboyExample.h similarity index 92% rename from spine-cocos2dx/example/Classes/ExampleLayer.h rename to spine-cocos2dx/example/Classes/SpineboyExample.h index 0c1649c11..641834609 100644 --- a/spine-cocos2dx/example/Classes/ExampleLayer.h +++ b/spine-cocos2dx/example/Classes/SpineboyExample.h @@ -28,22 +28,22 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef _EXAMPLELAYER_H_ -#define _EXAMPLELAYER_H_ +#ifndef _SPINEBOYEXAMPLE_H_ +#define _SPINEBOYEXAMPLE_H_ #include "cocos2d.h" #include -class ExampleLayer: public cocos2d::LayerColor { +class SpineboyExample : public cocos2d::LayerColor { public: static cocos2d::Scene* scene (); virtual bool init (); virtual void update (float deltaTime); - CREATE_FUNC (ExampleLayer); + CREATE_FUNC (SpineboyExample); private: spine::SkeletonAnimation* skeletonNode; }; -#endif // _EXAMPLELAYER_H_ \ No newline at end of file +#endif // _SPINEBOYEXAMPLE_H_ diff --git a/spine-cocos2dx/example/proj.win32/spine-cocos2dx.vcxproj b/spine-cocos2dx/example/proj.win32/spine-cocos2dx.vcxproj index 7539fdb53..e0d40382d 100644 --- a/spine-cocos2dx/example/proj.win32/spine-cocos2dx.vcxproj +++ b/spine-cocos2dx/example/proj.win32/spine-cocos2dx.vcxproj @@ -129,20 +129,24 @@ + - + + + - + + diff --git a/spine-cocos2dx/example/proj.win32/spine-cocos2dx.vcxproj.filters b/spine-cocos2dx/example/proj.win32/spine-cocos2dx.vcxproj.filters index 30512300c..ad5c9ffc3 100644 --- a/spine-cocos2dx/example/proj.win32/spine-cocos2dx.vcxproj.filters +++ b/spine-cocos2dx/example/proj.win32/spine-cocos2dx.vcxproj.filters @@ -21,9 +21,6 @@ Classes - - Classes - src @@ -33,6 +30,15 @@ src + + src + + + Classes + + + Classes + @@ -41,9 +47,6 @@ Classes - - Classes - src @@ -53,5 +56,14 @@ src + + src + + + Classes + + + Classes + \ No newline at end of file diff --git a/spine-cocos2dx/src/spine/PolygonBatch.cpp b/spine-cocos2dx/src/spine/PolygonBatch.cpp new file mode 100644 index 000000000..2fd3a22e7 --- /dev/null +++ b/spine-cocos2dx/src/spine/PolygonBatch.cpp @@ -0,0 +1,112 @@ +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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 (int 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 (int 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"); + this->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, + cocos2d::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()); + 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); + + verticesCount = 0; + trianglesCount = 0; + + CHECK_GL_ERROR_DEBUG(); +} + +} diff --git a/spine-cocos2dx/src/spine/PolygonBatch.h b/spine-cocos2dx/src/spine/PolygonBatch.h new file mode 100644 index 000000000..a9e448701 --- /dev/null +++ b/spine-cocos2dx/src/spine/PolygonBatch.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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_POLYGONBATCH_H_ +#define SPINE_POLYGONBATCH_H_ + +#include "cocos2d.h" + +namespace spine { + +class cocos2d::Texture2D; + +class PolygonBatch : public cocos2d::Ref { +public: + static PolygonBatch* createWithCapacity (int capacity); + + /** @js ctor */ + PolygonBatch(); + + /** @js NA + * @lua NA */ + virtual ~PolygonBatch(); + + bool initWithCapacity (int capacity); + void add (const cocos2d::Texture2D* texture, + const float* vertices, const float* uvs, int verticesCount, + const int* triangles, int trianglesCount, + cocos2d::Color4B* color); + void flush (); + +private: + int capacity; + cocos2d::V2F_C4B_T2F* vertices; + int verticesCount; + GLushort* triangles; + int trianglesCount; + const cocos2d::Texture2D* texture; +}; + +} + +#endif // SPINE_POLYGONBATCH_H_ diff --git a/spine-cocos2dx/src/spine/SkeletonAnimation.cpp b/spine-cocos2dx/src/spine/SkeletonAnimation.cpp index 7f20c5c92..baedb69e9 100644 --- a/spine-cocos2dx/src/spine/SkeletonAnimation.cpp +++ b/spine-cocos2dx/src/spine/SkeletonAnimation.cpp @@ -29,8 +29,8 @@ *****************************************************************************/ #include -#include #include +#include #include USING_NS_CC; diff --git a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp index 6b4370383..158b0b7f9 100644 --- a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp +++ b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp @@ -30,6 +30,8 @@ #include #include +#include +#include #include USING_NS_CC; @@ -38,6 +40,8 @@ using std::max; namespace spine { +static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0}; + SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) { SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData); node->autorelease(); @@ -62,6 +66,11 @@ void SkeletonRenderer::initialize () { debugBones = false; timeScale = 1; + 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); @@ -116,6 +125,7 @@ SkeletonRenderer::~SkeletonRenderer () { if (ownsSkeletonData) spSkeletonData_dispose(skeleton->data); if (atlas) spAtlas_dispose(atlas); spSkeleton_dispose(skeleton); + batch->release(); } void SkeletonRenderer::update (float deltaTime) { @@ -132,54 +142,82 @@ void SkeletonRenderer::drawSkeleton (const Matrix &transform, bool transformUpda getShaderProgram()->use(); getShaderProgram()->setUniformsForBuiltins(transform); - GL::blendFunc(blendFunc.src, blendFunc.dst); - Color3B color = getColor(); - skeleton->r = color.r / (float)255; - skeleton->g = color.g / (float)255; - skeleton->b = color.b / (float)255; + Color3B nodeColor = getColor(); + skeleton->r = nodeColor.r / (float)255; + skeleton->g = nodeColor.g / (float)255; + skeleton->b = nodeColor.b / (float)255; skeleton->a = getOpacity() / (float)255; - int additive = 0; - TextureAtlas* textureAtlas = 0; - V3F_C4B_T2F_Quad quad; - quad.tl.vertices.z = 0; - quad.tr.vertices.z = 0; - quad.bl.vertices.z = 0; - quad.br.vertices.z = 0; - + int additive = -1; + Color4B color; + const float* uvs = nullptr; + int verticesCount = 0; + const int* triangles = nullptr; + int trianglesCount = 0; + float r = 0, g = 0, b = 0, a = 0; for (int i = 0, n = skeleton->slotCount; i < n; i++) { spSlot* slot = skeleton->drawOrder[i]; - if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue; - spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment; - TextureAtlas* regionTextureAtlas = getTextureAtlas(attachment); - - if (slot->data->additiveBlending != additive) { - if (textureAtlas) { - textureAtlas->drawQuads(); - textureAtlas->removeAllQuads(); + if (!slot->attachment) continue; + Texture2D *texture = nullptr; + switch (slot->attachment->type) { + case SP_ATTACHMENT_REGION: { + spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment; + spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices); + texture = getTexture(attachment); + uvs = attachment->uvs; + verticesCount = 8; + triangles = quadTriangles; + trianglesCount = 6; + r = attachment->r; + g = attachment->g; + b = attachment->b; + a = attachment->a; + break; + } + case SP_ATTACHMENT_MESH: { + spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment; + spMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices); + texture = getTexture(attachment); + uvs = attachment->uvs; + verticesCount = attachment->verticesCount; + triangles = attachment->triangles; + trianglesCount = attachment->trianglesCount; + r = attachment->r; + g = attachment->g; + b = attachment->b; + a = attachment->a; + break; + } + case SP_ATTACHMENT_SKINNED_MESH: { + spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment; + spSkinnedMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices); + texture = getTexture(attachment); + uvs = attachment->uvs; + verticesCount = attachment->uvsCount; + triangles = attachment->triangles; + trianglesCount = attachment->trianglesCount; + r = attachment->r; + g = attachment->g; + b = attachment->b; + a = attachment->a; + break; + } + } + if (texture) { + if (slot->data->additiveBlending != additive) { + batch->flush(); + GL::blendFunc(blendFunc.src, slot->data->additiveBlending ? GL_ONE : blendFunc.dst); + additive = slot->data->additiveBlending; } - additive = !additive; - GL::blendFunc(blendFunc.src, additive ? GL_ONE : blendFunc.dst); - } else if (regionTextureAtlas != textureAtlas && textureAtlas) { - textureAtlas->drawQuads(); - textureAtlas->removeAllQuads(); + 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); } - textureAtlas = regionTextureAtlas; - - int quadCount = textureAtlas->getTotalQuads(); - if (textureAtlas->getCapacity() == quadCount) { - textureAtlas->drawQuads(); - textureAtlas->removeAllQuads(); - if (!textureAtlas->resizeCapacity(textureAtlas->getCapacity() * 2)) return; - } - - spRegionAttachment_updateQuad(attachment, slot, &quad, premultipliedAlpha); - textureAtlas->updateQuad(&quad, quadCount); - } - if (textureAtlas) { - textureAtlas->drawQuads(); - textureAtlas->removeAllQuads(); } + batch->flush(); if (debugSlots || debugBones) { Director* director = Director::getInstance(); @@ -196,11 +234,11 @@ void SkeletonRenderer::drawSkeleton (const Matrix &transform, bool transformUpda spSlot* slot = skeleton->drawOrder[i]; if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue; spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment; - spRegionAttachment_updateQuad(attachment, slot, &quad); - points[0] = Vector2(quad.bl.vertices.x, quad.bl.vertices.y); - points[1] = Vector2(quad.br.vertices.x, quad.br.vertices.y); - points[2] = Vector2(quad.tr.vertices.x, quad.tr.vertices.y); - points[3] = Vector2(quad.tl.vertices.x, quad.tl.vertices.y); + spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices); + points[0] = Vector2(worldVertices[0], worldVertices[1]); + points[1] = Vector2(worldVertices[2], worldVertices[3]); + points[2] = Vector2(worldVertices[4], worldVertices[5]); + points[3] = Vector2(worldVertices[6], worldVertices[7]); DrawPrimitives::drawPoly(points, 4, true); } } @@ -227,8 +265,16 @@ void SkeletonRenderer::drawSkeleton (const Matrix &transform, bool transformUpda } } -TextureAtlas* SkeletonRenderer::getTextureAtlas (spRegionAttachment* regionAttachment) const { - return (TextureAtlas*)((spAtlasRegion*)regionAttachment->rendererObject)->page->rendererObject; +Texture2D* SkeletonRenderer::getTexture (spRegionAttachment* attachment) const { + return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject; +} + +Texture2D* SkeletonRenderer::getTexture (spMeshAttachment* attachment) const { + return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject; +} + +Texture2D* SkeletonRenderer::getTexture (spSkinnedMeshAttachment* attachment) const { + return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject; } Rect SkeletonRenderer::boundingBox () { @@ -303,7 +349,7 @@ const BlendFunc& SkeletonRenderer::getBlendFunc () const { return blendFunc; } -void SkeletonRenderer::setBlendFunc (const cocos2d::BlendFunc &) { +void SkeletonRenderer::setBlendFunc (const cocos2d::BlendFunc &blendFunc) { this->blendFunc = blendFunc; } diff --git a/spine-cocos2dx/src/spine/SkeletonRenderer.h b/spine-cocos2dx/src/spine/SkeletonRenderer.h index 785abb3b2..31661c260 100644 --- a/spine-cocos2dx/src/spine/SkeletonRenderer.h +++ b/spine-cocos2dx/src/spine/SkeletonRenderer.h @@ -36,6 +36,8 @@ namespace spine { +class PolygonBatch; + /** Draws a skeleton. */ class SkeletonRenderer: public cocos2d::NodeRGBA, public cocos2d::BlendProtocol { public: @@ -58,7 +60,7 @@ public: virtual void update (float deltaTime); virtual void draw (cocos2d::Renderer* renderer, const cocos2d::Matrix& transform, bool transformUpdated) override; - void drawSkeleton (const cocos2d::Matrix& transform, bool transformUpdated); + virtual void drawSkeleton (const cocos2d::Matrix& transform, bool transformUpdated); virtual cocos2d::Rect boundingBox (); // --- Convenience methods for common Skeleton_* functions. @@ -92,13 +94,17 @@ public: protected: SkeletonRenderer (); void setSkeletonData (spSkeletonData* skeletonData, bool ownsSkeletonData); - virtual cocos2d::TextureAtlas* getTextureAtlas (spRegionAttachment* regionAttachment) const; + virtual cocos2d::Texture2D* getTexture (spRegionAttachment* attachment) const; + virtual cocos2d::Texture2D* getTexture (spMeshAttachment* attachment) const; + virtual cocos2d::Texture2D* getTexture (spSkinnedMeshAttachment* attachment) const; private: bool ownsSkeletonData; spAtlas* atlas; - cocos2d::BlendFunc blendFunc; cocos2d::CustomCommand drawCommand; + cocos2d::BlendFunc blendFunc; + PolygonBatch* batch; + float* worldVertices; void initialize (); }; diff --git a/spine-cocos2dx/src/spine/spine-cocos2dx.cpp b/spine-cocos2dx/src/spine/spine-cocos2dx.cpp index ebee422ce..74126aeca 100644 --- a/spine-cocos2dx/src/spine/spine-cocos2dx.cpp +++ b/spine-cocos2dx/src/spine/spine-cocos2dx.cpp @@ -35,15 +35,12 @@ USING_NS_CC; void _spAtlasPage_createTexture (spAtlasPage* self, const char* path) { Texture2D* texture = Director::getInstance()->getTextureCache()->addImage(path); - TextureAtlas* textureAtlas = TextureAtlas::createWithTexture(texture, 128); - textureAtlas->retain(); - self->rendererObject = textureAtlas; + self->rendererObject = texture; self->width = texture->getPixelsWide(); self->height = texture->getPixelsHigh(); } void _spAtlasPage_disposeTexture (spAtlasPage* self) { - ((TextureAtlas*)self->rendererObject)->release(); } char* _spUtil_readFile (const char* path, int* length) { @@ -54,59 +51,3 @@ char* _spUtil_readFile (const char* path, int* length) { memcpy(bytes, data.getBytes(), *length); return bytes; } - -/**/ - -namespace spine { - -void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, V3F_C4B_T2F_Quad* quad, bool premultipliedAlpha) { - float vertices[8]; - spRegionAttachment_computeWorldVertices(self, slot->skeleton->x, slot->skeleton->y, slot->bone, vertices); - - GLubyte r = slot->skeleton->r * slot->r * 255; - GLubyte g = slot->skeleton->g * slot->g * 255; - GLubyte b = slot->skeleton->b * slot->b * 255; - float normalizedAlpha = slot->skeleton->a * slot->a; - if (premultipliedAlpha) { - r *= normalizedAlpha; - g *= normalizedAlpha; - b *= normalizedAlpha; - } - GLubyte a = normalizedAlpha * 255; - quad->bl.colors.r = r; - quad->bl.colors.g = g; - quad->bl.colors.b = b; - quad->bl.colors.a = a; - quad->tl.colors.r = r; - quad->tl.colors.g = g; - quad->tl.colors.b = b; - quad->tl.colors.a = a; - quad->tr.colors.r = r; - quad->tr.colors.g = g; - quad->tr.colors.b = b; - quad->tr.colors.a = a; - quad->br.colors.r = r; - quad->br.colors.g = g; - quad->br.colors.b = b; - quad->br.colors.a = a; - - quad->bl.vertices.x = vertices[SP_VERTEX_X1]; - quad->bl.vertices.y = vertices[SP_VERTEX_Y1]; - quad->tl.vertices.x = vertices[SP_VERTEX_X2]; - quad->tl.vertices.y = vertices[SP_VERTEX_Y2]; - quad->tr.vertices.x = vertices[SP_VERTEX_X3]; - quad->tr.vertices.y = vertices[SP_VERTEX_Y3]; - quad->br.vertices.x = vertices[SP_VERTEX_X4]; - quad->br.vertices.y = vertices[SP_VERTEX_Y4]; - - quad->bl.texCoords.u = self->uvs[SP_VERTEX_X1]; - quad->bl.texCoords.v = self->uvs[SP_VERTEX_Y1]; - quad->tl.texCoords.u = self->uvs[SP_VERTEX_X2]; - quad->tl.texCoords.v = self->uvs[SP_VERTEX_Y2]; - quad->tr.texCoords.u = self->uvs[SP_VERTEX_X3]; - quad->tr.texCoords.v = self->uvs[SP_VERTEX_Y3]; - quad->br.texCoords.u = self->uvs[SP_VERTEX_X4]; - quad->br.texCoords.v = self->uvs[SP_VERTEX_Y4]; -} - -} diff --git a/spine-cocos2dx/src/spine/spine-cocos2dx.h b/spine-cocos2dx/src/spine/spine-cocos2dx.h index 3a2db8731..3409012f3 100644 --- a/spine-cocos2dx/src/spine/spine-cocos2dx.h +++ b/spine-cocos2dx/src/spine/spine-cocos2dx.h @@ -36,10 +36,4 @@ #include #include -namespace spine { - -void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, cocos2d::V3F_C4B_T2F_Quad* quad, bool premultiplied = false); - -} - #endif /* SPINE_COCOS2DX_H_ */