diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 901991f87..d0dd79e80 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -58,6 +58,17 @@ namespace spine { class RotateTimeline; typedef void (*AnimationStateListener) (AnimationState* state, EventType type, TrackEntry* entry, Event* event); + + /// Abstract class to inherit from to create a callback object + class SP_API AnimationStateListenerClass + { + public: + AnimationStateListenerClass() = default; + virtual ~AnimationStateListenerClass() = default; + public: + /// The callback function to be called + virtual void callback(AnimationState* state, EventType type, TrackEntry* entry, Event* event) = 0; + }; /// State for the playback of an animation class SP_API TrackEntry : public SpineObject, public HasRendererObject { @@ -241,6 +252,8 @@ namespace spine { void setListener(AnimationStateListener listener); + void setListener(AnimationStateListenerClass* listener); + private: Animation* _animation; @@ -259,6 +272,7 @@ namespace spine { Vector _timelineHoldMix; Vector _timelinesRotation; AnimationStateListener _listener; + AnimationStateListenerClass* _listenerObj; void reset(); }; @@ -396,6 +410,7 @@ namespace spine { void setTimeScale(float inValue); void setListener(AnimationStateListener listener); + void setListener(AnimationStateListenerClass* listener); void disableQueue(); void enableQueue(); @@ -413,6 +428,7 @@ namespace spine { bool _animationsChanged; AnimationStateListener _listener; + AnimationStateListenerClass* _listenerObj; float _timeScale; diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 67d1e717e..4f0731e82 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -59,7 +59,7 @@ TrackEntry::TrackEntry() : _animation(NULL), _next(NULL), _mixingFrom(NULL), _mi _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0), _trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _mixBlend(MixBlend_Replace), - _listener(dummyOnAnimationEventFunc) { + _listener(dummyOnAnimationEventFunc), _listenerObj(NULL) { } TrackEntry::~TrackEntry() { } @@ -164,6 +164,12 @@ void TrackEntry::resetRotationDirections() { void TrackEntry::setListener(AnimationStateListener inValue) { _listener = inValue; + _listenerObj = NULL; +} + +void TrackEntry::setListener(AnimationStateListenerClass* inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObj = inValue; } void TrackEntry::reset() { @@ -179,6 +185,7 @@ void TrackEntry::reset() { _timelinesRotation.clear(); _listener = dummyOnAnimationEventFunc; + _listenerObj = NULL; } EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event) : @@ -248,22 +255,48 @@ void EventQueue::drain() { case EventType_Start: case EventType_Interrupt: case EventType_Complete: - trackEntry->_listener(&state, queueEntry->_type, trackEntry, NULL); - state._listener(&state, queueEntry->_type, trackEntry, NULL); + if (NULL == trackEntry->_listenerObj) + trackEntry->_listener(&state, queueEntry->_type, trackEntry, NULL); + else + trackEntry->_listenerObj->callback(&state, queueEntry->_type, trackEntry, NULL); + if (NULL == state._listenerObj) + state._listener(&state, queueEntry->_type, trackEntry, NULL); + else + state._listenerObj->callback(&state, queueEntry->_type, trackEntry, NULL); break; case EventType_End: - trackEntry->_listener(&state, queueEntry->_type, trackEntry, NULL); - state._listener(&state, queueEntry->_type, trackEntry, NULL); + if (NULL == trackEntry->_listenerObj) + trackEntry->_listener(&state, queueEntry->_type, trackEntry, NULL); + else + trackEntry->_listenerObj->callback(&state, queueEntry->_type, trackEntry, NULL); + if (NULL == state._listenerObj) + state._listener(&state, queueEntry->_type, trackEntry, NULL); + else + state._listenerObj->callback(&state, queueEntry->_type, trackEntry, NULL); /* Yes, we want to fall through here */ case EventType_Dispose: - trackEntry->_listener(&state, EventType_Dispose, trackEntry, NULL); - state._listener(&state, EventType_Dispose, trackEntry, NULL); + + if (NULL == trackEntry->_listenerObj) + trackEntry->_listener(&state, EventType_Dispose, trackEntry, NULL); + else + trackEntry->_listenerObj->callback(&state, EventType_Dispose, trackEntry, NULL); + if (NULL == state._listenerObj) + state._listener(&state, EventType_Dispose, trackEntry, NULL); + else + state._listenerObj->callback(&state, EventType_Dispose, trackEntry, NULL); + trackEntry->reset(); _trackEntryPool.free(trackEntry); break; case EventType_Event: - trackEntry->_listener(&state, queueEntry->_type, trackEntry, queueEntry->_event); - state._listener(&state, queueEntry->_type, trackEntry, queueEntry->_event); + if (NULL == trackEntry->_listenerObj) + trackEntry->_listener(&state, queueEntry->_type, trackEntry, queueEntry->_event); + else + trackEntry->_listenerObj->callback(&state, queueEntry->_type, trackEntry, queueEntry->_event); + if (NULL == state._listenerObj) + state._listener(&state, queueEntry->_type, trackEntry, queueEntry->_event); + else + state._listenerObj->callback(&state, queueEntry->_type, trackEntry, queueEntry->_event); break; } } @@ -283,6 +316,7 @@ AnimationState::AnimationState(AnimationStateData *data) : _queue(EventQueue::newEventQueue(*this, _trackEntryPool)), _animationsChanged(false), _listener(dummyOnAnimationEventFunc), + _listenerObj(NULL), _timeScale(1) { } @@ -618,6 +652,12 @@ void AnimationState::setTimeScale(float inValue) { void AnimationState::setListener(AnimationStateListener inValue) { _listener = inValue; + _listenerObj = NULL; +} + +void AnimationState::setListener(AnimationStateListenerClass* inValue) { + _listener = dummyOnAnimationEventFunc; + _listenerObj = inValue; } void AnimationState::disableQueue() {