////////////////////////////////////////////////////////////////////// // filename: SpineEventMonitor.h // // purpose: Monitor spAnimationState Events ///////////////////////////////////////////////////////////////////// #pragma once #include #include #include using namespace Spine; ////////////////////////////////////////////////////////////////////// // class: SpineEventMonitor // // purpose: Monitor spAnimationState Events and report when there // are no more TrackEntry(s) waiting to play on track 0; // // Also allows for debug printing of Events to console. ///////////////////////////////////////////////////////////////////// class SpineEventMonitor { public: SpineEventMonitor(AnimationState* _pAnimationState = 0); virtual ~SpineEventMonitor(); void RegisterListener(AnimationState* _pAnimationState); void SetDebugLogging(bool val) { bLogging = val; } bool GetDebugLogging() { return bLogging; } virtual bool isAnimationPlaying(); protected: static void spineAnimStateHandler(AnimationState* state, EventType type, TrackEntry* entry, Event* event); virtual void OnSpineAnimationStateEvent(AnimationState* state, EventType type, TrackEntry* entry, Event* event); protected: AnimationState *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(AnimationState* state, EventType type, TrackEntry* trackEntry, Event* event); std::string mAnimName; int mEventType; TrackEntry* mTrackEntry; std::string mEventName; }; typedef std::vector InterruptEventStack; public: InterruptMonitor(AnimationState* _pAnimationState = 0); ~InterruptMonitor() {} virtual bool isAnimationPlaying() override; public: InterruptMonitor& AddInterruptEvent(int theEventType); InterruptMonitor& AddInterruptEvent(int theEventType, const std::string& theAnimationName); InterruptMonitor& AddInterruptEvent(int theEventType, TrackEntry* theTrackEntry); InterruptMonitor& AddInterruptEventTrigger(const std::string& theEventTriggerName); protected: virtual void OnSpineAnimationStateEvent(AnimationState* state, EventType type, TrackEntry* trackEntry, Event* 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 TrackEntry .AddInterruptEvent(SP_ANIMATION_START); // Then, stop on any following START signal */