Supports cocos2d-x v3.2

- Changes `draw()` with the new v3.2 API: `bool transformUpdated` -> `uint32_t transformFlags`
- cocos2d-ified the API:
  - `const char*` -> `const std::string&`
  - constructors and destructors are `protected` (not `public`)
  - using `_` prefix for ivars
This commit is contained in:
Ricardo Quesada 2014-07-25 10:16:11 -07:00
parent 234e8cf5f2
commit c8bc2bc378
6 changed files with 217 additions and 218 deletions

View File

@ -35,7 +35,7 @@ USING_NS_CC;
namespace spine {
PolygonBatch* PolygonBatch::createWithCapacity (int capacity) {
PolygonBatch* PolygonBatch::createWithCapacity (ssize_t capacity) {
PolygonBatch* batch = new PolygonBatch();
batch->initWithCapacity(capacity);
batch->autorelease();
@ -43,25 +43,25 @@ PolygonBatch* PolygonBatch::createWithCapacity (int capacity) {
}
PolygonBatch::PolygonBatch () :
capacity(0),
vertices(nullptr), verticesCount(0),
triangles(nullptr), trianglesCount(0),
texture(nullptr)
_capacity(0),
_vertices(nullptr), _verticesCount(0),
_triangles(nullptr), _trianglesCount(0),
_texture(nullptr)
{}
bool PolygonBatch::initWithCapacity (int capacity) {
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");
this->capacity = capacity;
vertices = MALLOC(V2F_C4B_T2F, capacity);
triangles = MALLOC(GLushort, capacity * 3);
_capacity = capacity;
_vertices = MALLOC(V2F_C4B_T2F, capacity);
_triangles = MALLOC(GLushort, capacity * 3);
return true;
}
PolygonBatch::~PolygonBatch () {
FREE(vertices);
FREE(triangles);
FREE(_vertices);
FREE(_triangles);
}
void PolygonBatch::add (const Texture2D* addTexture,
@ -70,18 +70,18 @@ void PolygonBatch::add (const Texture2D* addTexture,
Color4B* color) {
if (
addTexture != texture
|| verticesCount + (addVerticesCount >> 1) > capacity
|| trianglesCount + addTrianglesCount > capacity * 3) {
addTexture != _texture
|| _verticesCount + (addVerticesCount >> 1) > _capacity
|| _trianglesCount + addTrianglesCount > _capacity * 3) {
this->flush();
texture = addTexture;
_texture = addTexture;
}
for (int i = 0; i < addTrianglesCount; ++i, ++trianglesCount)
triangles[trianglesCount] = addTriangles[i] + verticesCount;
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;
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;
@ -91,20 +91,22 @@ void PolygonBatch::add (const Texture2D* addTexture,
}
void PolygonBatch::flush () {
if (!verticesCount) return;
if (!_verticesCount) return;
GL::bindTexture2D(texture->getName());
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);
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);
glDrawElements(GL_TRIANGLES, _trianglesCount, GL_UNSIGNED_SHORT, _triangles);
verticesCount = 0;
trianglesCount = 0;
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _verticesCount);
_verticesCount = 0;
_trianglesCount = 0;
CHECK_GL_ERROR_DEBUG();
}

View File

@ -37,29 +37,25 @@ namespace spine {
class PolygonBatch : public cocos2d::Ref {
public:
static PolygonBatch* createWithCapacity (int capacity);
static PolygonBatch* createWithCapacity (ssize_t 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;
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;
};
}

View File

@ -76,13 +76,13 @@ SkeletonAnimation* SkeletonAnimation::createWithData (spSkeletonData* skeletonDa
return node;
}
SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonAnimation* SkeletonAnimation::createWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonDataFile, atlas, scale);
node->autorelease();
return node;
}
SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) {
SkeletonAnimation* SkeletonAnimation::createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale) {
SkeletonAnimation* node = new SkeletonAnimation(skeletonDataFile, atlasFile, scale);
node->autorelease();
return node;
@ -90,11 +90,11 @@ SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFi
void SkeletonAnimation::initialize () {
ownsAnimationStateData = true;
state = spAnimationState_create(spAnimationStateData_create(skeleton->data));
state->rendererObject = this;
state->listener = animationCallback;
_state = spAnimationState_create(spAnimationStateData_create(_skeleton->data));
_state->rendererObject = this;
_state->listener = animationCallback;
_spAnimationState* stateInternal = (_spAnimationState*)state;
_spAnimationState* stateInternal = (_spAnimationState*)_state;
stateInternal->disposeTrackEntry = disposeTrackEntry;
}
@ -103,74 +103,74 @@ SkeletonAnimation::SkeletonAnimation (spSkeletonData *skeletonData)
initialize();
}
SkeletonAnimation::SkeletonAnimation (const char* skeletonDataFile, spAtlas* atlas, float scale)
SkeletonAnimation::SkeletonAnimation (const std::string& skeletonDataFile, spAtlas* atlas, float scale)
: SkeletonRenderer(skeletonDataFile, atlas, scale) {
initialize();
}
SkeletonAnimation::SkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale)
SkeletonAnimation::SkeletonAnimation (const std::string& skeletonDataFile, const std::string& atlasFile, float scale)
: SkeletonRenderer(skeletonDataFile, atlasFile, scale) {
initialize();
}
SkeletonAnimation::~SkeletonAnimation () {
if (ownsAnimationStateData) spAnimationStateData_dispose(state->data);
spAnimationState_dispose(state);
if (ownsAnimationStateData) spAnimationStateData_dispose(_state->data);
spAnimationState_dispose(_state);
}
void SkeletonAnimation::update (float deltaTime) {
super::update(deltaTime);
deltaTime *= timeScale;
spAnimationState_update(state, deltaTime);
spAnimationState_apply(state, skeleton);
spSkeleton_updateWorldTransform(skeleton);
deltaTime *= _timeScale;
spAnimationState_update(_state, deltaTime);
spAnimationState_apply(_state, _skeleton);
spSkeleton_updateWorldTransform(_skeleton);
}
void SkeletonAnimation::setAnimationStateData (spAnimationStateData* stateData) {
CCASSERT(stateData, "stateData cannot be null.");
if (ownsAnimationStateData) spAnimationStateData_dispose(state->data);
spAnimationState_dispose(state);
if (ownsAnimationStateData) spAnimationStateData_dispose(_state->data);
spAnimationState_dispose(_state);
ownsAnimationStateData = false;
state = spAnimationState_create(stateData);
state->rendererObject = this;
state->listener = animationCallback;
_state = spAnimationState_create(stateData);
_state->rendererObject = this;
_state->listener = animationCallback;
}
void SkeletonAnimation::setMix (const char* fromAnimation, const char* toAnimation, float duration) {
spAnimationStateData_setMixByName(state->data, fromAnimation, toAnimation, duration);
void SkeletonAnimation::setMix (const std::string& fromAnimation, const std::string& toAnimation, float duration) {
spAnimationStateData_setMixByName(_state->data, fromAnimation.c_str(), toAnimation.c_str(), duration);
}
spTrackEntry* SkeletonAnimation::setAnimation (int trackIndex, const char* name, bool loop) {
spAnimation* animation = spSkeletonData_findAnimation(skeleton->data, name);
spTrackEntry* SkeletonAnimation::setAnimation (int trackIndex, const std::string& name, bool loop) {
spAnimation* animation = spSkeletonData_findAnimation(_skeleton->data, name.c_str());
if (!animation) {
log("Spine: Animation not found: %s", name);
log("Spine: Animation not found: %s", name.c_str());
return 0;
}
return spAnimationState_setAnimation(state, trackIndex, animation, loop);
return spAnimationState_setAnimation(_state, trackIndex, animation, loop);
}
spTrackEntry* SkeletonAnimation::addAnimation (int trackIndex, const char* name, bool loop, float delay) {
spAnimation* animation = spSkeletonData_findAnimation(skeleton->data, name);
spTrackEntry* SkeletonAnimation::addAnimation (int trackIndex, const std::string& name, bool loop, float delay) {
spAnimation* animation = spSkeletonData_findAnimation(_skeleton->data, name.c_str());
if (!animation) {
log("Spine: Animation not found: %s", name);
log("Spine: Animation not found: %s", name.c_str());
return 0;
}
return spAnimationState_addAnimation(state, trackIndex, animation, loop, delay);
return spAnimationState_addAnimation(_state, trackIndex, animation, loop, delay);
}
spTrackEntry* SkeletonAnimation::getCurrent (int trackIndex) {
return spAnimationState_getCurrent(state, trackIndex);
return spAnimationState_getCurrent(_state, trackIndex);
}
void SkeletonAnimation::clearTracks () {
spAnimationState_clearTracks(state);
spAnimationState_clearTracks(_state);
}
void SkeletonAnimation::clearTrack (int trackIndex) {
spAnimationState_clearTrack(state, trackIndex);
spAnimationState_clearTrack(_state, trackIndex);
}
void SkeletonAnimation::onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) {
@ -191,7 +191,7 @@ void SkeletonAnimation::onAnimationStateEvent (int trackIndex, spEventType type,
}
void SkeletonAnimation::onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) {
spTrackEntry* entry = spAnimationState_getCurrent(state, trackIndex);
spTrackEntry* entry = spAnimationState_getCurrent(_state, trackIndex);
if (!entry->rendererObject) return;
_TrackEntryListeners* listeners = (_TrackEntryListeners*)entry->rendererObject;
switch (type) {
@ -226,4 +226,8 @@ void SkeletonAnimation::setEventListener (spTrackEntry* entry, spine::EventListe
getListeners(entry)->eventListener = listener;
}
spAnimationState* SkeletonAnimation::getState() const {
return _state;
}
}

View File

@ -46,33 +46,21 @@ typedef std::function<void(int trackIndex, spEvent* event)> EventListener;
* played later. */
class SkeletonAnimation: public SkeletonRenderer {
public:
spAnimationState* state;
static SkeletonAnimation* createWithData (spSkeletonData* skeletonData);
static SkeletonAnimation* createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
static SkeletonAnimation* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
SkeletonAnimation (spSkeletonData* skeletonData);
SkeletonAnimation (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
SkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
virtual ~SkeletonAnimation ();
static SkeletonAnimation* createWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale = 0);
static SkeletonAnimation* createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 0);
virtual void update (float deltaTime);
void setAnimationStateData (spAnimationStateData* stateData);
void setMix (const char* fromAnimation, const char* toAnimation, float duration);
void setMix (const std::string& fromAnimation, const std::string& toAnimation, float duration);
spTrackEntry* setAnimation (int trackIndex, const char* name, bool loop);
spTrackEntry* addAnimation (int trackIndex, const char* name, bool loop, float delay = 0);
spTrackEntry* setAnimation (int trackIndex, const std::string& name, bool loop);
spTrackEntry* addAnimation (int trackIndex, const std::string& name, bool loop, float delay = 0);
spTrackEntry* getCurrent (int trackIndex = 0);
void clearTracks ();
void clearTrack (int trackIndex = 0);
StartListener startListener;
EndListener endListener;
CompleteListener completeListener;
EventListener eventListener;
void setStartListener (spTrackEntry* entry, StartListener listener);
void setEndListener (spTrackEntry* entry, EndListener listener);
void setCompleteListener (spTrackEntry* entry, CompleteListener listener);
@ -81,14 +69,27 @@ public:
virtual void onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount);
virtual void onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount);
spAnimationState* getState() const;
StartListener startListener;
EndListener endListener;
CompleteListener completeListener;
EventListener eventListener;
protected:
SkeletonAnimation ();
SkeletonAnimation (spSkeletonData* skeletonData);
SkeletonAnimation (const std::string&skeletonDataFile, spAtlas* atlas, float scale = 0);
SkeletonAnimation (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 0);
virtual ~SkeletonAnimation ();
void initialize ();
spAnimationState* _state;
bool ownsAnimationStateData;
private:
typedef SkeletonRenderer super;
bool ownsAnimationStateData;
void initialize ();
};
}

View File

@ -48,30 +48,30 @@ SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData
return node;
}
SkeletonRenderer* SkeletonRenderer::createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonRenderer* SkeletonRenderer::createWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonRenderer* node = new SkeletonRenderer(skeletonDataFile, atlas, scale);
node->autorelease();
return node;
}
SkeletonRenderer* SkeletonRenderer::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) {
SkeletonRenderer* SkeletonRenderer::createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale) {
SkeletonRenderer* node = new SkeletonRenderer(skeletonDataFile, atlasFile, scale);
node->autorelease();
return node;
}
void SkeletonRenderer::initialize () {
atlas = 0;
debugSlots = false;
debugBones = false;
timeScale = 1;
_atlas = 0;
_debugSlots = false;
_debugBones = false;
_timeScale = 1;
worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh.
_worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh.
batch = PolygonBatch::createWithCapacity(2000); // Max number of vertices and triangles per batch.
batch->retain();
_batch = PolygonBatch::createWithCapacity(2000); // Max number of vertices and triangles per batch.
_batch->retain();
blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
_blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
setOpacityModifyRGB(true);
setGLProgram(ShaderCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
@ -79,9 +79,9 @@ void SkeletonRenderer::initialize () {
}
void SkeletonRenderer::setSkeletonData (spSkeletonData *skeletonData, bool ownsSkeletonData) {
skeleton = spSkeleton_create(skeletonData);
rootBone = skeleton->bones[0];
this->ownsSkeletonData = ownsSkeletonData;
_skeleton = spSkeleton_create(skeletonData);
_rootBone = _skeleton->bones[0];
_ownsSkeletonData = ownsSkeletonData;
}
SkeletonRenderer::SkeletonRenderer () {
@ -94,27 +94,27 @@ SkeletonRenderer::SkeletonRenderer (spSkeletonData *skeletonData, bool ownsSkele
setSkeletonData(skeletonData, ownsSkeletonData);
}
SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, spAtlas* atlas, float scale) {
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, spAtlas* atlas, float scale) {
initialize();
spSkeletonJson* json = spSkeletonJson_create(atlas);
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile);
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile.c_str());
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data.");
spSkeletonJson_dispose(json);
setSkeletonData(skeletonData, true);
}
SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, const char* atlasFile, float scale) {
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale) {
initialize();
atlas = spAtlas_createFromFile(atlasFile, 0);
CCASSERT(atlas, "Error reading atlas file.");
_atlas = spAtlas_createFromFile(atlasFile.c_str(), 0);
CCASSERT(_atlas, "Error reading atlas file.");
spSkeletonJson* json = spSkeletonJson_create(atlas);
spSkeletonJson* json = spSkeletonJson_create(_atlas);
json->scale = scale;
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile);
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, skeletonDataFile.c_str());
CCASSERT(skeletonData, json->error ? json->error : "Error reading skeleton data file.");
spSkeletonJson_dispose(json);
@ -122,33 +122,32 @@ SkeletonRenderer::SkeletonRenderer (const char* skeletonDataFile, const char* at
}
SkeletonRenderer::~SkeletonRenderer () {
if (ownsSkeletonData) spSkeletonData_dispose(skeleton->data);
if (atlas) spAtlas_dispose(atlas);
spSkeleton_dispose(skeleton);
batch->release();
FREE(worldVertices);
if (_ownsSkeletonData) spSkeletonData_dispose(_skeleton->data);
if (_atlas) spAtlas_dispose(_atlas);
spSkeleton_dispose(_skeleton);
_batch->release();
FREE(_worldVertices);
}
void SkeletonRenderer::update (float deltaTime) {
spSkeleton_update(skeleton, deltaTime * timeScale);
spSkeleton_update(_skeleton, deltaTime * _timeScale);
}
void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, bool transformUpdated) {
drawCommand.init(_globalZOrder);
drawCommand.func = CC_CALLBACK_0(SkeletonRenderer::drawSkeleton, this, transform, transformUpdated);
renderer->addCommand(&drawCommand);
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, bool transformUpdated) {
getGLProgram()->use();
getGLProgram()->setUniformsForBuiltins(transform);
GL::bindVAO(0);
void SkeletonRenderer::drawSkeleton (const Mat4 &transform, uint32_t transformFlags) {
getGLProgramState()->apply(transform);
Color3B nodeColor = getColor();
skeleton->r = nodeColor.r / (float)255;
skeleton->g = nodeColor.g / (float)255;
skeleton->b = nodeColor.b / (float)255;
skeleton->a = getDisplayedOpacity() / (float)255;
_skeleton->r = nodeColor.r / (float)255;
_skeleton->g = nodeColor.g / (float)255;
_skeleton->b = nodeColor.b / (float)255;
_skeleton->a = getDisplayedOpacity() / (float)255;
int additive = -1;
Color4B color;
@ -157,14 +156,14 @@ void SkeletonRenderer::drawSkeleton (const Mat4 &transform, bool transformUpdate
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];
for (int i = 0, n = _skeleton->slotCount; i < n; i++) {
spSlot* slot = _skeleton->drawOrder[i];
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);
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, _worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = 8;
@ -178,7 +177,7 @@ void SkeletonRenderer::drawSkeleton (const Mat4 &transform, bool transformUpdate
}
case SP_ATTACHMENT_MESH: {
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, _worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = attachment->verticesCount;
@ -192,7 +191,7 @@ void SkeletonRenderer::drawSkeleton (const Mat4 &transform, bool transformUpdate
}
case SP_ATTACHMENT_SKINNED_MESH: {
spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spSkinnedMeshAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot, _worldVertices);
texture = getTexture(attachment);
uvs = attachment->uvs;
verticesCount = attachment->uvsCount;
@ -208,49 +207,49 @@ void SkeletonRenderer::drawSkeleton (const Mat4 &transform, bool transformUpdate
}
if (texture) {
if (slot->data->additiveBlending != additive) {
batch->flush();
GL::blendFunc(blendFunc.src, slot->data->additiveBlending ? GL_ONE : blendFunc.dst);
_batch->flush();
GL::blendFunc(_blendFunc.src, slot->data->additiveBlending ? GL_ONE : _blendFunc.dst);
additive = slot->data->additiveBlending;
}
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);
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->flush();
_batch->flush();
if (debugSlots || debugBones) {
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) {
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->slotCount; i < n; i++) {
spSlot* slot = skeleton->drawOrder[i];
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;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, 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]);
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, 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) {
if (_debugBones) {
// Bone lengths.
glLineWidth(2);
DrawPrimitives::setDrawColor4B(255, 0, 0, 255);
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
spBone *bone = skeleton->bones[i];
for (int i = 0, n = _skeleton->boneCount; i < n; i++) {
spBone *bone = _skeleton->bones[i];
float x = bone->data->length * bone->m00 + bone->worldX;
float y = bone->data->length * bone->m10 + bone->worldY;
DrawPrimitives::drawLine(Vec2(bone->worldX, bone->worldY), Vec2(x, y));
@ -258,8 +257,8 @@ void SkeletonRenderer::drawSkeleton (const Mat4 &transform, bool transformUpdate
// Bone origins.
DrawPrimitives::setPointSize(4);
DrawPrimitives::setDrawColor4B(0, 0, 255, 255); // Root bone is blue.
for (int i = 0, n = skeleton->boneCount; i < n; i++) {
spBone *bone = skeleton->bones[i];
for (int i = 0, n = _skeleton->boneCount; i < n; i++) {
spBone *bone = _skeleton->bones[i];
DrawPrimitives::drawPoint(Vec2(bone->worldX, bone->worldY));
if (i == 0) DrawPrimitives::setDrawColor4B(0, 255, 0, 255);
}
@ -283,26 +282,26 @@ Texture2D* SkeletonRenderer::getTexture (spSkinnedMeshAttachment* attachment) co
Rect SkeletonRenderer::getBoundingBox () const {
float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
float scaleX = getScaleX(), scaleY = getScaleY();
for (int i = 0; i < skeleton->slotCount; ++i) {
spSlot* slot = skeleton->slots[i];
for (int i = 0; i < _skeleton->slotCount; ++i) {
spSlot* slot = _skeleton->slots[i];
if (!slot->attachment) continue;
int verticesCount;
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, worldVertices);
spRegionAttachment_computeWorldVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, _worldVertices);
verticesCount = 8;
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
spMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, _worldVertices);
verticesCount = mesh->verticesCount;
} else if (slot->attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)slot->attachment;
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, worldVertices);
spSkinnedMeshAttachment_computeWorldVertices(mesh, slot->skeleton->x, slot->skeleton->y, slot, _worldVertices);
verticesCount = mesh->uvsCount;
} else
continue;
for (int ii = 0; ii < verticesCount; ii += 2) {
float x = worldVertices[ii] * scaleX, y = worldVertices[ii + 1] * scaleY;
float x = _worldVertices[ii] * scaleX, y = _worldVertices[ii + 1] * scaleY;
minX = min(minX, x);
minY = min(minY, y);
maxX = max(maxX, x);
@ -316,54 +315,54 @@ Rect SkeletonRenderer::getBoundingBox () const {
// --- Convenience methods for Skeleton_* functions.
void SkeletonRenderer::updateWorldTransform () {
spSkeleton_updateWorldTransform(skeleton);
spSkeleton_updateWorldTransform(_skeleton);
}
void SkeletonRenderer::setToSetupPose () {
spSkeleton_setToSetupPose(skeleton);
spSkeleton_setToSetupPose(_skeleton);
}
void SkeletonRenderer::setBonesToSetupPose () {
spSkeleton_setBonesToSetupPose(skeleton);
spSkeleton_setBonesToSetupPose(_skeleton);
}
void SkeletonRenderer::setSlotsToSetupPose () {
spSkeleton_setSlotsToSetupPose(skeleton);
spSkeleton_setSlotsToSetupPose(_skeleton);
}
spBone* SkeletonRenderer::findBone (const char* boneName) const {
return spSkeleton_findBone(skeleton, boneName);
spBone* SkeletonRenderer::findBone (const std::string& boneName) const {
return spSkeleton_findBone(_skeleton, boneName.c_str());
}
spSlot* SkeletonRenderer::findSlot (const char* slotName) const {
return spSkeleton_findSlot(skeleton, slotName);
spSlot* SkeletonRenderer::findSlot (const std::string& slotName) const {
return spSkeleton_findSlot(_skeleton, slotName.c_str());
}
bool SkeletonRenderer::setSkin (const char* skinName) {
return spSkeleton_setSkinByName(skeleton, skinName) ? true : false;
bool SkeletonRenderer::setSkin (const std::string& skinName) {
return spSkeleton_setSkinByName(_skeleton, skinName.c_str()) ? true : false;
}
spAttachment* SkeletonRenderer::getAttachment (const char* slotName, const char* attachmentName) const {
return spSkeleton_getAttachmentForSlotName(skeleton, slotName, attachmentName);
spAttachment* SkeletonRenderer::getAttachment (const std::string& slotName, const std::string& attachmentName) const {
return spSkeleton_getAttachmentForSlotName(_skeleton, slotName.c_str(), attachmentName.c_str());
}
bool SkeletonRenderer::setAttachment (const char* slotName, const char* attachmentName) {
return spSkeleton_setAttachment(skeleton, slotName, attachmentName) ? true : false;
bool SkeletonRenderer::setAttachment (const std::string& slotName, const std::string& attachmentName) {
return spSkeleton_setAttachment(_skeleton, slotName.c_str(), attachmentName.c_str()) ? true : false;
}
// --- CCBlendProtocol
const BlendFunc& SkeletonRenderer::getBlendFunc () const {
return blendFunc;
return _blendFunc;
}
void SkeletonRenderer::setBlendFunc (const BlendFunc &blendFunc) {
this->blendFunc = blendFunc;
_blendFunc = blendFunc;
}
void SkeletonRenderer::setOpacityModifyRGB (bool value) {
premultipliedAlpha = value;
_premultipliedAlpha = value;
}
bool SkeletonRenderer::isOpacityModifyRGB () {
return premultipliedAlpha;
bool SkeletonRenderer::isOpacityModifyRGB () const {
return _premultipliedAlpha;
}
}

View File

@ -41,26 +41,13 @@ class PolygonBatch;
/** Draws a skeleton. */
class SkeletonRenderer: public cocos2d::Node, public cocos2d::BlendProtocol {
public:
spSkeleton* skeleton;
spBone* rootBone;
float timeScale;
bool debugSlots;
bool debugBones;
bool premultipliedAlpha;
static SkeletonRenderer* createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
static SkeletonRenderer* createWithFile (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
static SkeletonRenderer* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
SkeletonRenderer (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
SkeletonRenderer (const char* skeletonDataFile, spAtlas* atlas, float scale = 0);
SkeletonRenderer (const char* skeletonDataFile, const char* atlasFile, float scale = 0);
virtual ~SkeletonRenderer ();
static SkeletonRenderer* createWithFile (const std::string& skeletonDataFile, spAtlas* atlas, float scale = 0);
static SkeletonRenderer* createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 0);
virtual void update (float deltaTime) override;
virtual void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, bool transformUpdated) override;
virtual void drawSkeleton (const cocos2d::Mat4& transform, bool transformUpdated);
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 cocos2d::Rect getBoundingBox () const override;
// --- Convenience methods for common Skeleton_* functions.
@ -71,41 +58,51 @@ public:
void setSlotsToSetupPose ();
/* Returns 0 if the bone was not found. */
spBone* findBone (const char* boneName) const;
spBone* findBone (const std::string& boneName) const;
/* Returns 0 if the slot was not found. */
spSlot* findSlot (const char* slotName) const;
spSlot* findSlot (const std::string& slotName) const;
/* Sets the skin used to look up attachments not found in the SkeletonData defaultSkin. Attachments from the new skin are
* attached if the corresponding attachment from the old skin was attached. Returns false if the skin was not found.
* @param skin May be 0.*/
bool setSkin (const char* skinName);
bool setSkin (const std::string& skinName);
/* Returns 0 if the slot or attachment was not found. */
spAttachment* getAttachment (const char* slotName, const char* attachmentName) const;
spAttachment* getAttachment (const std::string& slotName, const std::string& attachmentName) const;
/* Returns false if the slot or attachment was not found. */
bool setAttachment (const char* slotName, const char* attachmentName);
bool setAttachment (const std::string& slotName, const std::string& attachmentName);
// --- BlendProtocol
virtual void setBlendFunc (const cocos2d::BlendFunc& blendFunc);
virtual const cocos2d::BlendFunc& getBlendFunc () const;
virtual void setOpacityModifyRGB (bool value);
virtual bool isOpacityModifyRGB ();
virtual bool isOpacityModifyRGB () const;
protected:
SkeletonRenderer ();
SkeletonRenderer (spSkeletonData* skeletonData, bool ownsSkeletonData = false);
SkeletonRenderer (const std::string& skeletonDataFile, spAtlas* atlas, float scale = 0);
SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 0);
virtual ~SkeletonRenderer ();
void initialize ();
void setSkeletonData (spSkeletonData* skeletonData, bool ownsSkeletonData);
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::CustomCommand drawCommand;
cocos2d::BlendFunc blendFunc;
PolygonBatch* batch;
float* worldVertices;
void initialize ();
bool _ownsSkeletonData;
spAtlas* _atlas;
cocos2d::CustomCommand _drawCommand;
cocos2d::BlendFunc _blendFunc;
PolygonBatch* _batch;
float* _worldVertices;
bool _premultipliedAlpha;
spSkeleton* _skeleton;
spBone* _rootBone;
float _timeScale;
bool _debugSlots;
bool _debugBones;
};
}