////////////////////////////////////////////////////////////////////// // filename: SpineEventMonitor.h // // purpose: Monitor spAnimationState Events ///////////////////////////////////////////////////////////////////// #pragma once #include #include // forward declarations typedef struct spAnimationState spAnimationState; typedef struct spTrackEntry spTrackEntry; typedef struct spEvent spEvent; ////////////////////////////////////////////////////////////////////// // class: SpineEventMonitor // // purpose: Monitor spAnimationState Events and report when there // are no more spTrackEntry(s) waiting to play on track 0; // // Also allows for debug printing of Events to console. ///////////////////////////////////////////////////////////////////// class SpineEventMonitor { public: SpineEventMonitor(spAnimationState *_pAnimationState = 0); virtual ~SpineEventMonitor(); void RegisterListener(spAnimationState *_pAnimationState); void SetDebugLogging(bool val) { bLogging = val; } bool GetDebugLogging() { return bLogging; } virtual bool isAnimationPlaying(); protected: static void spineAnimStateHandler(spAnimationState *state, int type, spTrackEntry *entry, spEvent *event); virtual void OnSpineAnimationStateEvent(spAnimationState *state, int type, spTrackEntry *trackEntry, spEvent *event); protected: spAnimationState *pAnimState; bool bLogging; }; ////////////////////////////////////////////////////////////////////// // class: InterruptMonitor // // purpose: Allows a programmer to interrupt/stop the updating // of an animation based on a specific sequence of // events generated by the animation. ///////////////////////////////////////////////////////////////////// class InterruptMonitor : public SpineEventMonitor { private: struct InterruptEvent { InterruptEvent() { mEventType = -1; // invalid mTrackEntry = 0; } bool matches(spAnimationState *state, int type, spTrackEntry *trackEntry, spEvent *event); std::string mAnimName; int mEventType; spTrackEntry *mTrackEntry; std::string mEventName; }; typedef std::vector InterruptEventStack; public: InterruptMonitor(spAnimationState *_pAnimationState = 0); ~InterruptMonitor() {} virtual bool isAnimationPlaying() override; public: InterruptMonitor &AddInterruptEvent(int theEventType); InterruptMonitor &AddInterruptEvent(int theEventType, const std::string &theAnimationName); InterruptMonitor &AddInterruptEvent(int theEventType, spTrackEntry *theTrackEntry); InterruptMonitor &AddInterruptEventTrigger(const std::string &theEventTriggerName); protected: virtual void OnSpineAnimationStateEvent(spAnimationState *state, int type, spTrackEntry *trackEntry, spEvent *event) override; virtual void OnMatchingComplete() {} protected: bool bForceInterrupt; InterruptEventStack mEventStack; // must match these events in this order size_t mEventStackCursor; }; /* EXAMPLE ======= SpineEventMonitor eventMonitor(state); eventMonitor.SetDebugLogging(true); while(eventMonitor.isAnimationPlaying()){ // update... } EXAMPLE ======= InterruptMonitor eventMonitor(state); eventMonitor.SetDebugLogging(true); // Interrupt the animation on this specific sequence of spEventType(s) eventMonitor .AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump") // First, wait for INTERRUPT signal on the 'jump' animation spTrackEntry .AddInterruptEvent(SP_ANIMATION_START); // Then, stop on any following START signal */