|
@@ -30,9 +30,10 @@
|
|
*****************************************************************************/
|
|
*****************************************************************************/
|
|
|
|
|
|
#include <spine/SkeletonRenderer.h>
|
|
#include <spine/SkeletonRenderer.h>
|
|
-#include <spine/spine-cocos2dx.h>
|
|
|
|
#include <spine/extension.h>
|
|
#include <spine/extension.h>
|
|
#include <spine/SkeletonBatch.h>
|
|
#include <spine/SkeletonBatch.h>
|
|
|
|
+#include <spine/AttachmentVertices.h>
|
|
|
|
+#include <spine/Cocos2dAttachmentLoader.h>
|
|
#include <algorithm>
|
|
#include <algorithm>
|
|
|
|
|
|
USING_NS_CC;
|
|
USING_NS_CC;
|
|
@@ -41,8 +42,6 @@ using std::max;
|
|
|
|
|
|
namespace spine {
|
|
namespace spine {
|
|
|
|
|
|
-static const int quadTriangles[6] = {0, 1, 2, 2, 3, 0};
|
|
|
|
-
|
|
|
|
SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
|
|
SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
|
|
SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData);
|
|
SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData);
|
|
node->autorelease();
|
|
node->autorelease();
|
|
@@ -62,7 +61,7 @@ SkeletonRenderer* SkeletonRenderer::createWithFile (const std::string& skeletonD
|
|
}
|
|
}
|
|
|
|
|
|
void SkeletonRenderer::initialize () {
|
|
void SkeletonRenderer::initialize () {
|
|
- _worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh.
|
|
|
|
|
|
+ _worldVertices = new float[1000]; // Max number of vertices per mesh.
|
|
|
|
|
|
_blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
|
|
_blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
|
|
setOpacityModifyRGB(true);
|
|
setOpacityModifyRGB(true);
|
|
@@ -76,29 +75,30 @@ void SkeletonRenderer::setSkeletonData (spSkeletonData *skeletonData, bool ownsS
|
|
}
|
|
}
|
|
|
|
|
|
SkeletonRenderer::SkeletonRenderer ()
|
|
SkeletonRenderer::SkeletonRenderer ()
|
|
- : _atlas(0), _debugSlots(false), _debugBones(false), _timeScale(1) {
|
|
|
|
|
|
+ : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _timeScale(1) {
|
|
}
|
|
}
|
|
|
|
|
|
SkeletonRenderer::SkeletonRenderer (spSkeletonData *skeletonData, bool ownsSkeletonData)
|
|
SkeletonRenderer::SkeletonRenderer (spSkeletonData *skeletonData, bool ownsSkeletonData)
|
|
- : _atlas(0), _debugSlots(false), _debugBones(false), _timeScale(1) {
|
|
|
|
|
|
+ : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _timeScale(1) {
|
|
initWithData(skeletonData, ownsSkeletonData);
|
|
initWithData(skeletonData, ownsSkeletonData);
|
|
}
|
|
}
|
|
|
|
|
|
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, spAtlas* atlas, float scale)
|
|
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, spAtlas* atlas, float scale)
|
|
- : _atlas(0), _debugSlots(false), _debugBones(false), _timeScale(1) {
|
|
|
|
|
|
+ : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _timeScale(1) {
|
|
initWithFile(skeletonDataFile, atlas, scale);
|
|
initWithFile(skeletonDataFile, atlas, scale);
|
|
}
|
|
}
|
|
|
|
|
|
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale)
|
|
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale)
|
|
- : _atlas(0), _debugSlots(false), _debugBones(false), _timeScale(1) {
|
|
|
|
|
|
+ : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _timeScale(1) {
|
|
initWithFile(skeletonDataFile, atlasFile, scale);
|
|
initWithFile(skeletonDataFile, atlasFile, scale);
|
|
}
|
|
}
|
|
|
|
|
|
SkeletonRenderer::~SkeletonRenderer () {
|
|
SkeletonRenderer::~SkeletonRenderer () {
|
|
if (_ownsSkeletonData) spSkeletonData_dispose(_skeleton->data);
|
|
if (_ownsSkeletonData) spSkeletonData_dispose(_skeleton->data);
|
|
- if (_atlas) spAtlas_dispose(_atlas);
|
|
|
|
spSkeleton_dispose(_skeleton);
|
|
spSkeleton_dispose(_skeleton);
|
|
- FREE(_worldVertices);
|
|
|
|
|
|
+ if (_atlas) spAtlas_dispose(_atlas);
|
|
|
|
+ if (_attachmentLoader) spAttachmentLoader_dispose(_attachmentLoader);
|
|
|
|
+ delete _worldVertices;
|
|
}
|
|
}
|
|
|
|
|
|
void SkeletonRenderer::initWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
|
|
void SkeletonRenderer::initWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
|
|
@@ -108,7 +108,9 @@ void SkeletonRenderer::initWithData (spSkeletonData* skeletonData, bool ownsSkel
|
|
}
|
|
}
|
|
|
|
|
|
void SkeletonRenderer::initWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale) {
|
|
void SkeletonRenderer::initWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale) {
|
|
- spSkeletonJson* json = spSkeletonJson_create(atlas);
|
|
|
|
|
|
+ _attachmentLoader = SUPER(Cocos2dAttachmentLoader_create(_atlas));
|
|
|
|
+
|
|
|
|
+ spSkeletonJson* json = spSkeletonJson_createWithLoader(_attachmentLoader);
|
|
json->scale = scale;
|
|
json->scale = scale;
|
|
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile.c_str());
|
|
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile.c_str());
|
|
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data.");
|
|
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data.");
|
|
@@ -123,7 +125,9 @@ void SkeletonRenderer::initWithFile (const std::string& skeletonDataFile, const
|
|
_atlas = spAtlas_createFromFile(atlasFile.c_str(), 0);
|
|
_atlas = spAtlas_createFromFile(atlasFile.c_str(), 0);
|
|
CCASSERT(_atlas, "Error reading atlas file.");
|
|
CCASSERT(_atlas, "Error reading atlas file.");
|
|
|
|
|
|
- spSkeletonJson* json = spSkeletonJson_create(_atlas);
|
|
|
|
|
|
+ _attachmentLoader = SUPER(Cocos2dAttachmentLoader_create(_atlas));
|
|
|
|
+
|
|
|
|
+ spSkeletonJson* json = spSkeletonJson_createWithLoader(_attachmentLoader);
|
|
json->scale = scale;
|
|
json->scale = scale;
|
|
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile.c_str());
|
|
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile.c_str());
|
|
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data file.");
|
|
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data file.");
|
|
@@ -141,7 +145,6 @@ void SkeletonRenderer::update (float deltaTime) {
|
|
|
|
|
|
void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) {
|
|
void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) {
|
|
SkeletonBatch* batch = SkeletonBatch::getInstance();
|
|
SkeletonBatch* batch = SkeletonBatch::getInstance();
|
|
- batch->setRendererState(renderer, &transform, transformFlags, _globalZOrder, getGLProgramState(), _premultipliedAlpha);
|
|
|
|
|
|
|
|
Color3B nodeColor = getColor();
|
|
Color3B nodeColor = getColor();
|
|
_skeleton->r = nodeColor.r / (float)255;
|
|
_skeleton->r = nodeColor.r / (float)255;
|
|
@@ -149,72 +152,83 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t
|
|
_skeleton->b = nodeColor.b / (float)255;
|
|
_skeleton->b = nodeColor.b / (float)255;
|
|
_skeleton->a = getDisplayedOpacity() / (float)255;
|
|
_skeleton->a = getDisplayedOpacity() / (float)255;
|
|
|
|
|
|
- int blendMode = -1;
|
|
|
|
Color4B color;
|
|
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->slotsCount; i < n; i++) {
|
|
|
|
|
|
+ int vertexCount = 0;
|
|
|
|
+ AttachmentVertices* attachmentVertices = nullptr;
|
|
|
|
+ for (int i = 0, n = _skeleton->slotsCount; i < n; ++i) {
|
|
spSlot* slot = _skeleton->drawOrder[i];
|
|
spSlot* slot = _skeleton->drawOrder[i];
|
|
if (!slot->attachment) continue;
|
|
if (!slot->attachment) continue;
|
|
- Texture2D *texture = nullptr;
|
|
|
|
|
|
+
|
|
switch (slot->attachment->type) {
|
|
switch (slot->attachment->type) {
|
|
case SP_ATTACHMENT_REGION: {
|
|
case SP_ATTACHMENT_REGION: {
|
|
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
|
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
|
spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices);
|
|
spRegionAttachment_computeWorldVertices(attachment, 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;
|
|
|
|
|
|
+ attachmentVertices = getAttachmentVertices(attachment);
|
|
|
|
+ color.r = attachment->r;
|
|
|
|
+ color.g = attachment->g;
|
|
|
|
+ color.b = attachment->b;
|
|
|
|
+ color.a = attachment->a;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case SP_ATTACHMENT_MESH: {
|
|
case SP_ATTACHMENT_MESH: {
|
|
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
|
|
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
|
|
spMeshAttachment_computeWorldVertices(attachment, slot, _worldVertices);
|
|
spMeshAttachment_computeWorldVertices(attachment, 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;
|
|
|
|
|
|
+ attachmentVertices = getAttachmentVertices(attachment);
|
|
|
|
+ color.r = attachment->r;
|
|
|
|
+ color.g = attachment->g;
|
|
|
|
+ color.b = attachment->b;
|
|
|
|
+ color.a = attachment->a;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case SP_ATTACHMENT_WEIGHTED_MESH: {
|
|
case SP_ATTACHMENT_WEIGHTED_MESH: {
|
|
spWeightedMeshAttachment* attachment = (spWeightedMeshAttachment*)slot->attachment;
|
|
spWeightedMeshAttachment* attachment = (spWeightedMeshAttachment*)slot->attachment;
|
|
spWeightedMeshAttachment_computeWorldVertices(attachment, slot, _worldVertices);
|
|
spWeightedMeshAttachment_computeWorldVertices(attachment, 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;
|
|
|
|
|
|
+ attachmentVertices = getAttachmentVertices(attachment);
|
|
|
|
+ color.r = attachment->r;
|
|
|
|
+ color.g = attachment->g;
|
|
|
|
+ color.b = attachment->b;
|
|
|
|
+ color.a = attachment->a;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- default: ;
|
|
|
|
- }
|
|
|
|
- if (texture) {
|
|
|
|
- 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, slot->data->blendMode);
|
|
|
|
|
|
+ default:
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ color.a *= _skeleton->a * slot->a * 255;
|
|
|
|
+ float multiplier = _premultipliedAlpha ? color.a : 255;
|
|
|
|
+ color.r *= _skeleton->r * slot->r * multiplier;
|
|
|
|
+ color.g *= _skeleton->g * slot->g * multiplier;
|
|
|
|
+ color.b *= _skeleton->b * slot->b * multiplier;
|
|
|
|
+
|
|
|
|
+ for (int v = 0, w = 0, vn = attachmentVertices->_triangles->vertCount; v < vn; ++v, w += 2) {
|
|
|
|
+ V3F_C4B_T2F* vertex = attachmentVertices->_triangles->verts + v;
|
|
|
|
+ vertex->vertices.x = _worldVertices[w];
|
|
|
|
+ vertex->vertices.y = _worldVertices[w + 1];
|
|
|
|
+ vertex->colors = color;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BlendFunc blendFunc;
|
|
|
|
+ switch (slot->data->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;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc,
|
|
|
|
+ *attachmentVertices->_triangles, transform, transformFlags);
|
|
}
|
|
}
|
|
- batch->flush();
|
|
|
|
|
|
|
|
if (_debugSlots || _debugBones) {
|
|
if (_debugSlots || _debugBones) {
|
|
_debugCommand.init(_globalZOrder);
|
|
_debugCommand.init(_globalZOrder);
|
|
@@ -236,7 +250,7 @@ void SkeletonRenderer::drawDebug (const Mat4 &transform, uint32_t transformFlags
|
|
glLineWidth(1);
|
|
glLineWidth(1);
|
|
Vec2 points[4];
|
|
Vec2 points[4];
|
|
V3F_C4B_T2F_Quad quad;
|
|
V3F_C4B_T2F_Quad quad;
|
|
- for (int i = 0, n = _skeleton->slotsCount; i < n; i++) {
|
|
|
|
|
|
+ for (int i = 0, n = _skeleton->slotsCount; i < n; ++i) {
|
|
spSlot* slot = _skeleton->drawOrder[i];
|
|
spSlot* slot = _skeleton->drawOrder[i];
|
|
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
|
|
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
|
|
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
|
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
|
@@ -252,7 +266,7 @@ void SkeletonRenderer::drawDebug (const Mat4 &transform, uint32_t transformFlags
|
|
// Bone lengths.
|
|
// Bone lengths.
|
|
glLineWidth(2);
|
|
glLineWidth(2);
|
|
DrawPrimitives::setDrawColor4B(255, 0, 0, 255);
|
|
DrawPrimitives::setDrawColor4B(255, 0, 0, 255);
|
|
- for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
|
|
|
|
|
|
+ for (int i = 0, n = _skeleton->bonesCount; i < n; ++i) {
|
|
spBone *bone = _skeleton->bones[i];
|
|
spBone *bone = _skeleton->bones[i];
|
|
float x = bone->data->length * bone->a + bone->worldX;
|
|
float x = bone->data->length * bone->a + bone->worldX;
|
|
float y = bone->data->length * bone->c + bone->worldY;
|
|
float y = bone->data->length * bone->c + bone->worldY;
|
|
@@ -261,7 +275,7 @@ void SkeletonRenderer::drawDebug (const Mat4 &transform, uint32_t transformFlags
|
|
// Bone origins.
|
|
// Bone origins.
|
|
DrawPrimitives::setPointSize(4);
|
|
DrawPrimitives::setPointSize(4);
|
|
DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue.
|
|
DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue.
|
|
- for (int i = 0, n = _skeleton->bonesCount; i < n; i++) {
|
|
|
|
|
|
+ for (int i = 0, n = _skeleton->bonesCount; i < n; ++i) {
|
|
spBone *bone = _skeleton->bones[i];
|
|
spBone *bone = _skeleton->bones[i];
|
|
DrawPrimitives::drawPoint(Vec2(bone->worldX, bone->worldY));
|
|
DrawPrimitives::drawPoint(Vec2(bone->worldX, bone->worldY));
|
|
if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255);
|
|
if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255);
|
|
@@ -270,16 +284,16 @@ void SkeletonRenderer::drawDebug (const Mat4 &transform, uint32_t transformFlags
|
|
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
|
}
|
|
}
|
|
|
|
|
|
-Texture2D* SkeletonRenderer::getTexture (spRegionAttachment* attachment) const {
|
|
|
|
- return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
|
|
|
|
|
|
+AttachmentVertices* SkeletonRenderer::getAttachmentVertices (spRegionAttachment* attachment) const {
|
|
|
|
+ return (AttachmentVertices*)attachment->rendererObject;
|
|
}
|
|
}
|
|
|
|
|
|
-Texture2D* SkeletonRenderer::getTexture (spMeshAttachment* attachment) const {
|
|
|
|
- return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
|
|
|
|
|
|
+AttachmentVertices* SkeletonRenderer::getAttachmentVertices (spMeshAttachment* attachment) const {
|
|
|
|
+ return (AttachmentVertices*)attachment->rendererObject;
|
|
}
|
|
}
|
|
|
|
|
|
-Texture2D* SkeletonRenderer::getTexture (spWeightedMeshAttachment* attachment) const {
|
|
|
|
- return (Texture2D*)((spAtlasRegion*)attachment->rendererObject)->page->rendererObject;
|
|
|
|
|
|
+AttachmentVertices* SkeletonRenderer::getAttachmentVertices (spWeightedMeshAttachment* attachment) const {
|
|
|
|
+ return (AttachmentVertices*)attachment->rendererObject;
|
|
}
|
|
}
|
|
|
|
|
|
Rect SkeletonRenderer::getBoundingBox () const {
|
|
Rect SkeletonRenderer::getBoundingBox () const {
|