From 9443ecb09ca0c8e3d8cab6ed777e602774fc053a Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Thu, 26 Sep 2013 21:44:22 +0200 Subject: [PATCH] cocos2dx style AnimationState event callback for CCSkeletonAnimation. --- spine-c/include/spine/AnimationState.h | 1 + .../example/Classes/ExampleLayer.cpp | 28 +++++++++++++++++-- spine-cocos2dx/example/Classes/ExampleLayer.h | 7 +++-- .../src/spine/CCSkeletonAnimation.cpp | 20 +++++++++++++ .../src/spine/CCSkeletonAnimation.h | 9 ++++++ 5 files changed, 59 insertions(+), 6 deletions(-) diff --git a/spine-c/include/spine/AnimationState.h b/spine-c/include/spine/AnimationState.h index 8d5b33a3e..2dc163ced 100644 --- a/spine-c/include/spine/AnimationState.h +++ b/spine-c/include/spine/AnimationState.h @@ -67,6 +67,7 @@ struct AnimationState { TrackEntry** tracks; AnimationStateListener listener; + void* context; }; /* @param data May be 0 for no mixing. */ diff --git a/spine-cocos2dx/example/Classes/ExampleLayer.cpp b/spine-cocos2dx/example/Classes/ExampleLayer.cpp index 67c3630af..e0ab4c134 100644 --- a/spine-cocos2dx/example/Classes/ExampleLayer.cpp +++ b/spine-cocos2dx/example/Classes/ExampleLayer.cpp @@ -17,11 +17,12 @@ CCScene* ExampleLayer::scene () { bool ExampleLayer::init () { if (!CCLayer::init()) return false; - + skeletonNode = CCSkeletonAnimation::createWithFile("spineboy.json", "spineboy.atlas"); skeletonNode->setMix("walk", "jump", 0.2f); skeletonNode->setMix("jump", "walk", 0.4f); - + + skeletonNode->setListener(this, animationStateEvent_selector(ExampleLayer::animationStateEvent)); skeletonNode->setAnimation(0, "walk", true); // This shows how to setup animations to play back to back. //skeletonNode->addAnimation(0, "jump", false); @@ -53,4 +54,25 @@ void ExampleLayer::update (float deltaTime) { if (entry->time > 1) skeletonNode->setAnimation(0, "walk", true); } // if (entry->time > 0.1) CCDirector::sharedDirector()->replaceScene(ExampleLayer::scene()); -} \ No newline at end of file +} + +void ExampleLayer::animationStateEvent (CCSkeletonAnimation* node, int trackIndex, EventType type, Event* event, int loopCount) { + TrackEntry* entry = AnimationState_getCurrent(node->state, trackIndex); + const char* animationName = (entry && entry->animation) ? entry->animation->name : 0; + + switch (type) { + case ANIMATION_START: + CCLog("%d start: %s", trackIndex, animationName); + break; + case ANIMATION_END: + CCLog("%d end: %s", trackIndex, animationName); + break; + case ANIMATION_COMPLETE: + CCLog("%d complete: %s, %d", trackIndex, animationName, loopCount); + break; + case ANIMATION_EVENT: + CCLog("%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 6cf2cc974..8f9c708b1 100644 --- a/spine-cocos2dx/example/Classes/ExampleLayer.h +++ b/spine-cocos2dx/example/Classes/ExampleLayer.h @@ -7,9 +7,6 @@ #include class ExampleLayer: public cocos2d::CCLayer { -private: - spine::CCSkeletonAnimation* skeletonNode; - public: static cocos2d::CCScene* scene (); @@ -17,6 +14,10 @@ public: virtual void update (float deltaTime); CREATE_FUNC (ExampleLayer); +private: + spine::CCSkeletonAnimation* skeletonNode; + + void animationStateEvent (spine::CCSkeletonAnimation* node, int trackIndex, EventType type, Event* event, int loopCount); }; #endif // _EXAMPLELAYER_H_ \ No newline at end of file diff --git a/spine-cocos2dx/src/spine/CCSkeletonAnimation.cpp b/spine-cocos2dx/src/spine/CCSkeletonAnimation.cpp index acc678314..9816754a3 100644 --- a/spine-cocos2dx/src/spine/CCSkeletonAnimation.cpp +++ b/spine-cocos2dx/src/spine/CCSkeletonAnimation.cpp @@ -42,6 +42,14 @@ using std::vector; namespace spine { +extern "C" static void callback (AnimationState* state, int trackIndex, EventType type, Event* event, int loopCount) { + ((CCSkeletonAnimation*)state->context)->onAnimationStateEvent(trackIndex, type, event, loopCount); +} + +void CCSkeletonAnimation::onAnimationStateEvent (int trackIndex, EventType type, Event* event, int loopCount) { + if (listenerInstance) (listenerInstance->*listenerMethod)(this, trackIndex, type, event, loopCount); +} + CCSkeletonAnimation* CCSkeletonAnimation::createWithData (SkeletonData* skeletonData) { CCSkeletonAnimation* node = new CCSkeletonAnimation(skeletonData); node->autorelease(); @@ -61,7 +69,12 @@ CCSkeletonAnimation* CCSkeletonAnimation::createWithFile (const char* skeletonDa } void CCSkeletonAnimation::initialize () { + listenerInstance = 0; + listenerMethod = 0; + state = AnimationState_create(AnimationStateData_create(skeleton->data)); + state->context = this; + state->listener = callback; } CCSkeletonAnimation::CCSkeletonAnimation (SkeletonData *skeletonData) @@ -101,12 +114,19 @@ void CCSkeletonAnimation::setAnimationStateData (AnimationStateData* stateData) ownsAnimationStateData = true; state = AnimationState_create(stateData); + state->context = this; + state->listener = callback; } void CCSkeletonAnimation::setMix (const char* fromAnimation, const char* toAnimation, float duration) { AnimationStateData_setMixByName(state->data, fromAnimation, toAnimation, duration); } +void CCSkeletonAnimation::setListener (CCObject* instance, SEL_AnimationStateEvent method) { + listenerInstance = instance; + listenerMethod = method; +} + TrackEntry* CCSkeletonAnimation::setAnimation (int trackIndex, const char* name, bool loop) { return AnimationState_setAnimationByName(state, trackIndex, name, loop); } diff --git a/spine-cocos2dx/src/spine/CCSkeletonAnimation.h b/spine-cocos2dx/src/spine/CCSkeletonAnimation.h index e89ccebdf..75aaf98c5 100644 --- a/spine-cocos2dx/src/spine/CCSkeletonAnimation.h +++ b/spine-cocos2dx/src/spine/CCSkeletonAnimation.h @@ -40,6 +40,10 @@ namespace spine { +class CCSkeletonAnimation; +typedef void (cocos2d::CCObject::*SEL_AnimationStateEvent)(spine::CCSkeletonAnimation* node, int trackIndex, EventType type, Event* event, int loopCount); +#define animationStateEvent_selector(_SELECTOR) (SEL_AnimationStateEvent)(&_SELECTOR) + /** Draws an animated skeleton, providing an AnimationState for applying one or more animations and queuing animations to be * played later. */ class CCSkeletonAnimation: public CCSkeleton { @@ -61,17 +65,22 @@ public: void setAnimationStateData (AnimationStateData* stateData); void setMix (const char* fromAnimation, const char* toAnimation, float duration); + void setListener (CCObject* instance, SEL_AnimationStateEvent method); TrackEntry* setAnimation (int trackIndex, const char* name, bool loop); TrackEntry* addAnimation (int trackIndex, const char* name, bool loop, float delay = 0); TrackEntry* getCurrent (int trackIndex = 0); void clearAnimation (); void clearAnimation (int trackIndex = 0); + void onAnimationStateEvent (int trackIndex, EventType type, Event* event, int loopCount); + protected: CCSkeletonAnimation (); private: typedef CCSkeleton super; + CCObject* listenerInstance; + SEL_AnimationStateEvent listenerMethod; bool ownsAnimationStateData; void initialize ();