164 lines
5.0 KiB
C++
Executable File

#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;
}