From 7199d22417aabcfe4507bfdc06cb018ea0784fed Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Sun, 11 May 2014 21:00:50 +0200 Subject: [PATCH] Better AnimationState listeners, including on a TrackEntry. --- spine-c/include/spine/AnimationState.h | 2 + spine-c/include/spine/extension.h | 8 ++ spine-c/src/spine/AnimationState.c | 34 ++++----- .../example/Classes/ExampleLayer.cpp | 47 ++++++------ spine-cocos2dx/example/Classes/ExampleLayer.h | 2 - .../src/spine/SkeletonAnimation.cpp | 75 +++++++++++++++++-- spine-cocos2dx/src/spine/SkeletonAnimation.h | 29 +++++-- spine-cocos2dx/src/spine/spine-cocos2dx.cpp | 13 ++++ spine-cocos2dx/src/spine/spine-cocos2dx.h | 4 + 9 files changed, 155 insertions(+), 59 deletions(-) diff --git a/spine-c/include/spine/AnimationState.h b/spine-c/include/spine/AnimationState.h index aa1b629fb..44093f43a 100644 --- a/spine-c/include/spine/AnimationState.h +++ b/spine-c/include/spine/AnimationState.h @@ -57,6 +57,8 @@ struct spTrackEntry { float delay, time, lastTime, endTime, timeScale; spAnimationStateListener listener; float mixTime, mixDuration, mix; + + void* rendererObject; }; struct spAnimationState { diff --git a/spine-c/include/spine/extension.h b/spine-c/include/spine/extension.h index 09427b862..3820eaa00 100644 --- a/spine-c/include/spine/extension.h +++ b/spine-c/include/spine/extension.h @@ -74,6 +74,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -86,6 +87,8 @@ extern "C" { void _spAtlasPage_createTexture (spAtlasPage* self, const char* path); void _spAtlasPage_disposeTexture (spAtlasPage* self); char* _spUtil_readFile (const char* path, int* length); +spTrackEntry* _spAnimationState_createTrackEntry (spAnimationState* self); +void _spAnimationState_disposeTrackEntry (spAnimationState* self, spTrackEntry* entry); #ifdef SPINE_SHORT_NAMES #define _AtlasPage_createTexture(...) _spAtlasPage_createTexture(__VA_ARGS__) @@ -109,6 +112,11 @@ char* _readFile (const char* path, int* length); /**/ +spTrackEntry* _spTrackEntry_create (); +void _spTrackEntry_dispose (spTrackEntry* entry); + +/**/ + void _spAttachmentLoader_init (spAttachmentLoader* self, /**/ void (*dispose) (spAttachmentLoader* self), /**/ spAttachment* (*newAttachment) (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name, diff --git a/spine-c/src/spine/AnimationState.c b/spine-c/src/spine/AnimationState.c index 344ff4649..77818c411 100644 --- a/spine-c/src/spine/AnimationState.c +++ b/spine-c/src/spine/AnimationState.c @@ -45,14 +45,6 @@ void _spTrackEntry_dispose (spTrackEntry* entry) { FREE(entry); } -void _spTrackEntry_disposeAll (spTrackEntry* entry) { - while (entry) { - spTrackEntry* next = entry->next; - _spTrackEntry_dispose(entry); - entry = next; - } -} - /**/ typedef struct { @@ -71,12 +63,20 @@ spAnimationState* spAnimationState_create (spAnimationStateData* data) { return self; } +void _spAnimationState_disposeAllEntries (spAnimationState* self, spTrackEntry* entry) { + while (entry) { + spTrackEntry* next = entry->next; + _spAnimationState_disposeTrackEntry(self, entry); + entry = next; + } +} + void spAnimationState_dispose (spAnimationState* self) { int i; _spAnimationState* internal = SUB_CAST(_spAnimationState, self); FREE(internal->events); for (i = 0; i < self->trackCount; ++i) - _spTrackEntry_disposeAll(self->tracks[i]); + _spAnimationState_disposeAllEntries(self, self->tracks[i]); FREE(self->tracks); FREE(self); } @@ -140,7 +140,7 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { if (alpha >= 1) { alpha = 1; - _spTrackEntry_dispose(current->previous); + _spAnimationState_disposeTrackEntry(self, current->previous); current->previous = 0; } spAnimation_mix(current->animation, skeleton, current->lastTime, time, @@ -203,8 +203,8 @@ void spAnimationState_clearTrack (spAnimationState* self, int trackIndex) { self->tracks[trackIndex] = 0; - if (current->previous) _spTrackEntry_dispose(current->previous); - _spTrackEntry_disposeAll(current); + if (current->previous) _spAnimationState_disposeTrackEntry(self, current->previous); + _spAnimationState_disposeAllEntries(self, current); } spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index) { @@ -237,9 +237,9 @@ void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEnt } else entry->previous = current; } else - _spTrackEntry_dispose(current); + _spAnimationState_disposeTrackEntry(self, current); - if (previous) _spTrackEntry_dispose(previous); + if (previous) _spAnimationState_disposeTrackEntry(self, previous); } self->tracks[index] = entry; @@ -260,9 +260,9 @@ spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int t spTrackEntry* spAnimationState_setAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop) { spTrackEntry* entry; spTrackEntry* current = _spAnimationState_expandToIndex(self, trackIndex); - if (current) _spTrackEntry_disposeAll(current->next); + if (current) _spAnimationState_disposeAllEntries(self, current->next); - entry = _spTrackEntry_create(); + entry = _spAnimationState_createTrackEntry(self); entry->animation = animation; entry->loop = loop; entry->endTime = animation->duration; @@ -280,7 +280,7 @@ spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIn float delay) { spTrackEntry* last; - spTrackEntry* entry = _spTrackEntry_create(); + spTrackEntry* entry = _spAnimationState_createTrackEntry(self); entry->animation = animation; entry->loop = loop; entry->endTime = animation->duration; diff --git a/spine-cocos2dx/example/Classes/ExampleLayer.cpp b/spine-cocos2dx/example/Classes/ExampleLayer.cpp index 51028c6a4..a676d7f36 100644 --- a/spine-cocos2dx/example/Classes/ExampleLayer.cpp +++ b/spine-cocos2dx/example/Classes/ExampleLayer.cpp @@ -47,16 +47,34 @@ bool ExampleLayer::init () { if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false; skeletonNode = SkeletonAnimation::createWithFile("spineboy.json", "spineboy.atlas", 0.6f); - skeletonNode->setMix("walk", "jump", 0.2f); - skeletonNode->setMix("jump", "run", 0.2f); - skeletonNode->setAnimationListener(&ExampleLayer::animationStateEvent, this); // skeletonNode->timeScale = 0.3f; skeletonNode->debugBones = true; + + 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) { + log("%d end", trackIndex); + }; + skeletonNode->completeListener = [](int trackIndex, int loopCount) { + log("%d complete: %d", trackIndex, loopCount); + }; + skeletonNode->eventListener = [](int trackIndex, spEvent* event) { + log("%d event: %s, %d, %f, %s", trackIndex, event->data->name, event->intValue, event->floatValue, event->stringValue); + }; + skeletonNode->setMix("walk", "jump", 0.2f); + skeletonNode->setMix("jump", "run", 0.2f); skeletonNode->setAnimation(0, "walk", true); - skeletonNode->addAnimation(0, "jump", false, 3); + spTrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 3); skeletonNode->addAnimation(0, "run", true); + skeletonNode->setStartListener(jumpEntry, [](int trackIndex) { + log("jumped!", trackIndex); + }); + // skeletonNode->addAnimation(1, "test", true); // skeletonNode->runAction(RepeatForever::create(Sequence::create(FadeOut::create(1), FadeIn::create(1), DelayTime::create(5), NULL))); @@ -73,24 +91,3 @@ void ExampleLayer::update (float deltaTime) { // Test releasing memory. // Director::getInstance()->replaceScene(ExampleLayer::scene()); } - -void ExampleLayer::animationStateEvent (SkeletonAnimation* node, int trackIndex, spEventType type, spEvent* event, int loopCount) { - spTrackEntry* entry = spAnimationState_getCurrent(node->state, trackIndex); - const char* animationName = (entry && entry->animation) ? entry->animation->name : 0; - - switch (type) { - case SP_ANIMATION_START: - log("%d start: %s", trackIndex, animationName); - break; - case SP_ANIMATION_END: - log("%d end: %s", trackIndex, animationName); - break; - case SP_ANIMATION_COMPLETE: - log("%d complete: %s, %d", trackIndex, animationName, loopCount); - break; - case SP_ANIMATION_EVENT: - log("%d event: %s, %s: %d, %f, %s", trackIndex, animationName, event->data->name, event->intValue, event->floatValue, event->stringValue); - break; - } - fflush(stdout); -} diff --git a/spine-cocos2dx/example/Classes/ExampleLayer.h b/spine-cocos2dx/example/Classes/ExampleLayer.h index 51fb86500..0c1649c11 100644 --- a/spine-cocos2dx/example/Classes/ExampleLayer.h +++ b/spine-cocos2dx/example/Classes/ExampleLayer.h @@ -44,8 +44,6 @@ public: CREATE_FUNC (ExampleLayer); private: spine::SkeletonAnimation* skeletonNode; - - void animationStateEvent (spine::SkeletonAnimation* node, int trackIndex, spEventType type, spEvent* event, int loopCount); }; #endif // _EXAMPLELAYER_H_ \ No newline at end of file diff --git a/spine-cocos2dx/src/spine/SkeletonAnimation.cpp b/spine-cocos2dx/src/spine/SkeletonAnimation.cpp index 719818e72..5d5f7cd59 100644 --- a/spine-cocos2dx/src/spine/SkeletonAnimation.cpp +++ b/spine-cocos2dx/src/spine/SkeletonAnimation.cpp @@ -40,8 +40,12 @@ using std::vector; namespace spine { -static void callback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) { - ((SkeletonAnimation*)state->context)->onAnimationStateEvent(trackIndex, type, event, loopCount); +static void animationCallback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) { + ((SkeletonAnimation*)state->rendererObject)->onAnimationStateEvent(trackIndex, type, event, loopCount); +} + +static void trackEntryCallback (spAnimationState* state, int trackIndex, spEventType type, spEvent* event, int loopCount) { + ((SkeletonAnimation*)state->rendererObject)->onTrackEntryEvent(trackIndex, type, event, loopCount); } SkeletonAnimation* SkeletonAnimation::createWithData (spSkeletonData* skeletonData) { @@ -65,8 +69,8 @@ SkeletonAnimation* SkeletonAnimation::createWithFile (const char* skeletonDataFi void SkeletonAnimation::initialize () { ownsAnimationStateData = true; state = spAnimationState_create(spAnimationStateData_create(skeleton->data)); - state->context = this; - state->listener = callback; + state->rendererObject = this; + state->listener = animationCallback; } SkeletonAnimation::SkeletonAnimation (spSkeletonData *skeletonData) @@ -106,8 +110,8 @@ void SkeletonAnimation::setAnimationStateData (spAnimationStateData* stateData) ownsAnimationStateData = false; state = spAnimationState_create(stateData); - state->context = this; - state->listener = callback; + state->rendererObject = this; + state->listener = animationCallback; } void SkeletonAnimation::setMix (const char* fromAnimation, const char* toAnimation, float duration) { @@ -145,7 +149,64 @@ void SkeletonAnimation::clearTrack (int trackIndex) { } void SkeletonAnimation::onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) { - if (listener) listener(this, trackIndex, type, event, loopCount); + switch (type) { + case SP_ANIMATION_START: + if (startListener) startListener(trackIndex); + break; + case SP_ANIMATION_END: + if (endListener) endListener(trackIndex); + break; + case SP_ANIMATION_COMPLETE: + if (completeListener) completeListener(trackIndex, loopCount); + break; + case SP_ANIMATION_EVENT: + if (eventListener) eventListener(trackIndex, event); + break; + } +} + +void SkeletonAnimation::onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount) { + spTrackEntry* entry = spAnimationState_getCurrent(state, trackIndex); + if (!entry->rendererObject) return; + _TrackEntryListeners* listeners = (_TrackEntryListeners*)entry->rendererObject; + switch (type) { + case SP_ANIMATION_START: + if (listeners->startListener) listeners->startListener(trackIndex); + break; + case SP_ANIMATION_END: + if (listeners->endListener) listeners->endListener(trackIndex); + break; + case SP_ANIMATION_COMPLETE: + if (listeners->completeListener) listeners->completeListener(trackIndex, loopCount); + break; + case SP_ANIMATION_EVENT: + if (listeners->eventListener) listeners->eventListener(trackIndex, event); + break; + } +} + +static _TrackEntryListeners* getListeners (spTrackEntry* entry) { + if (!entry->rendererObject) { + entry->rendererObject = NEW(spine::_TrackEntryListeners); + entry->listener = trackEntryCallback; + } + return (_TrackEntryListeners*)entry->rendererObject; +} + +void SkeletonAnimation::setStartListener (spTrackEntry* entry, StartListener listener) { + getListeners(entry)->startListener = listener; +} + +void SkeletonAnimation::setEndListener (spTrackEntry* entry, EndListener listener) { + getListeners(entry)->endListener = listener; +} + +void SkeletonAnimation::setCompleteListener (spTrackEntry* entry, CompleteListener listener) { + getListeners(entry)->completeListener = listener; +} + +void SkeletonAnimation::setEventListener (spTrackEntry* entry, spine::EventListener listener) { + getListeners(entry)->eventListener = listener; } } diff --git a/spine-cocos2dx/src/spine/SkeletonAnimation.h b/spine-cocos2dx/src/spine/SkeletonAnimation.h index fe7c98eb1..bede0fd3f 100644 --- a/spine-cocos2dx/src/spine/SkeletonAnimation.h +++ b/spine-cocos2dx/src/spine/SkeletonAnimation.h @@ -37,8 +37,17 @@ namespace spine { -class SkeletonAnimation; -typedef std::function AnimationStateListener; +typedef std::function StartListener; +typedef std::function EndListener; +typedef std::function CompleteListener; +typedef std::function EventListener; + +typedef struct _TrackEntryListeners { + StartListener startListener; + EndListener endListener; + CompleteListener completeListener; + EventListener eventListener; +} _TrackEntryListeners; /** Draws an animated skeleton, providing an AnimationState for applying one or more animations and queuing animations to be * played later. */ @@ -61,25 +70,29 @@ public: void setAnimationStateData (spAnimationStateData* stateData); void setMix (const char* fromAnimation, const char* toAnimation, float duration); - template void setAnimationListener (_Rx _Farg0::* const type, _Arg0&& target) { - using namespace std::placeholders; - this->listener = std::bind(type, target, _1, _2, _3, _4, _5); - } - spTrackEntry* setAnimation (int trackIndex, const char* name, bool loop); spTrackEntry* addAnimation (int trackIndex, const char* 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); + void setEventListener (spTrackEntry* entry, EventListener listener); + virtual void onAnimationStateEvent (int trackIndex, spEventType type, spEvent* event, int loopCount); + virtual void onTrackEntryEvent (int trackIndex, spEventType type, spEvent* event, int loopCount); protected: SkeletonAnimation (); private: typedef SkeletonRenderer super; - AnimationStateListener listener; bool ownsAnimationStateData; void initialize (); diff --git a/spine-cocos2dx/src/spine/spine-cocos2dx.cpp b/spine-cocos2dx/src/spine/spine-cocos2dx.cpp index bafeb106d..dea7e4003 100644 --- a/spine-cocos2dx/src/spine/spine-cocos2dx.cpp +++ b/spine-cocos2dx/src/spine/spine-cocos2dx.cpp @@ -55,8 +55,19 @@ char* _spUtil_readFile (const char* path, int* length) { return bytes; } +spTrackEntry* _spAnimationState_createTrackEntry (spAnimationState* self) { + return _spTrackEntry_create(); +} + +void _spAnimationState_disposeTrackEntry (spAnimationState* self, spTrackEntry* entry) { + if (entry->rendererObject) FREE(entry->rendererObject); + _spTrackEntry_dispose(entry); +} + /**/ +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); @@ -106,3 +117,5 @@ void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, V3F_ 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 69677a82f..3a2db8731 100644 --- a/spine-cocos2dx/src/spine/spine-cocos2dx.h +++ b/spine-cocos2dx/src/spine/spine-cocos2dx.h @@ -36,6 +36,10 @@ #include #include +namespace spine { + void spRegionAttachment_updateQuad (spRegionAttachment* self, spSlot* slot, cocos2d::V3F_C4B_T2F_Quad* quad, bool premultiplied = false); +} + #endif /* SPINE_COCOS2DX_H_ */