#include "SpineEventMonitor.h" #include "spine/spine.h" #include "KString.h" #include "KMemory.h" // Last include SpineEventMonitor::SpineEventMonitor(spAnimationState *_pAnimationState /*= nullptr*/) { bLogging = false; RegisterListener(_pAnimationState); } SpineEventMonitor::~SpineEventMonitor() { pAnimState = 0; } void SpineEventMonitor::RegisterListener(spAnimationState *_pAnimationState) { if (_pAnimationState) { _pAnimationState->rendererObject = this; _pAnimationState->listener = (spAnimationStateListener) &SpineEventMonitor::spineAnimStateHandler; } pAnimState = _pAnimationState; } bool SpineEventMonitor::isAnimationPlaying() { if (pAnimState) return spAnimationState_getCurrent(pAnimState, 0) != 0; return false; } void SpineEventMonitor::spineAnimStateHandler(spAnimationState *state, int type, spTrackEntry *entry, spEvent *event) { if (state && state->rendererObject) { SpineEventMonitor *pEventMonitor = (SpineEventMonitor *) state->rendererObject; pEventMonitor->OnSpineAnimationStateEvent(state, type, entry, event); } } void SpineEventMonitor::OnSpineAnimationStateEvent(spAnimationState *state, int type, spTrackEntry *trackEntry, spEvent *event) { const char *eventName = 0; if (state == pAnimState) { // only monitor ours switch (type) { case SP_ANIMATION_START: eventName = "SP_ANIMATION_START"; break; case SP_ANIMATION_INTERRUPT: eventName = "SP_ANIMATION_INTERRUPT"; break; case SP_ANIMATION_END: eventName = "SP_ANIMATION_END"; break; case SP_ANIMATION_COMPLETE: eventName = "SP_ANIMATION_COMPLETE"; break; case SP_ANIMATION_DISPOSE: eventName = "SP_ANIMATION_DISPOSE"; break; case SP_ANIMATION_EVENT: eventName = "SP_ANIMATION_EVENT"; break; default: break; } if (bLogging && eventName && trackEntry && trackEntry->animation && trackEntry->animation->name) KOutputDebug(DEBUGLVL, "[%s : '%s']\n", eventName, trackEntry->animation->name);//*/ } } InterruptMonitor::InterruptMonitor(spAnimationState *_pAnimationState) : SpineEventMonitor(_pAnimationState) { bForceInterrupt = false; mEventStackCursor = 0; // cursor used to track events } bool InterruptMonitor::isAnimationPlaying() { return !bForceInterrupt && SpineEventMonitor::isAnimationPlaying(); } // Stops the animation on any occurance of the spEventType InterruptMonitor &InterruptMonitor::AddInterruptEvent(int theEventType) { InterruptEvent ev; ev.mEventType = theEventType; mEventStack.push_back(ev); return *this; } // Stops the animation when the [spEventType : 'animationName'] occurs InterruptMonitor &InterruptMonitor::AddInterruptEvent(int theEventType, const std::string &theAnimationName) { InterruptEvent ev; ev.mEventType = theEventType; ev.mAnimName = theAnimationName; mEventStack.push_back(ev); return *this; } // stops the first encounter of spEventType on the specified TrackEntry InterruptMonitor &InterruptMonitor::AddInterruptEvent(int theEventType, spTrackEntry *theTrackEntry) { InterruptEvent ev; ev.mEventType = theEventType; ev.mTrackEntry = theTrackEntry; mEventStack.push_back(ev); return *this; } // Stops on the first SP_ANIMATION_EVENT with the string payload of 'theEventTriggerName' InterruptMonitor &InterruptMonitor::AddInterruptEventTrigger(const std::string &theEventTriggerName) { InterruptEvent ev; ev.mEventType = SP_ANIMATION_EVENT; ev.mEventName = theEventTriggerName; mEventStack.push_back(ev); return *this; } void InterruptMonitor::OnSpineAnimationStateEvent(spAnimationState *state, int type, spTrackEntry *trackEntry, spEvent *event) { SpineEventMonitor::OnSpineAnimationStateEvent(state, type, trackEntry, event); if (mEventStackCursor < mEventStack.size()) { if (mEventStack[mEventStackCursor].matches(state, type, trackEntry, event)) ++mEventStackCursor; if (mEventStackCursor >= mEventStack.size()) { bForceInterrupt = true; OnMatchingComplete(); } } } inline bool InterruptMonitor::InterruptEvent::matches(spAnimationState *state, int type, spTrackEntry *trackEntry, spEvent *event) { // Must match spEventType {SP_ANIMATION_START, SP_ANIMATION_INTERRUPT, SP_ANIMATION_END, SP_ANIMATION_COMPLETE, SP_ANIMATION_DISPOSE, SP_ANIMATION_EVENT } if (mEventType == type) { // Looking for specific TrackEntry by pointer if (mTrackEntry != 0) { return mTrackEntry == trackEntry; } // looking for Animation Track by name if (!mAnimName.empty()) { if (trackEntry && trackEntry->animation && trackEntry->animation->name) { if (CompareNoCase(trackEntry->animation->name, mAnimName) == 0) { return true; } } return false; } // looking for Event String Text if (!mEventName.empty()) { if (event && event->stringValue) { return (CompareNoCase(event->stringValue, mEventName) == 0); } return false; } return true; // waiting for ANY spEventType that matches } return false; }