As far as I can tell, it's working correctly. You've set a listener on the AnimationState which will be notified every time any animation event happens. With a zero duration animation, your listener gets a complete event every time the animation is applied. That happens when you call apply
every frame, not just when you call apply
from the listener. So, every frame you are getting a complete event and calling setAnimationByName
. This builds up a long linked list of mixingFrom
entries. When you get enough of those, applying the mixing from animations runs out of stack space and crashes.
See TrackEntry listener
. This way you can set a listener that handles the complete on an animation but is not notified for any other animations. Or, deregister your listener using AnimationState removeListener
before setting a new animation.
Eg, to play run
then when complete happens, play empty
:
static void spineAnimStateHandler(spAnimationState* state, int type, spTrackEntry* entry, spEvent* event) {
if (type != SP_ANIMATION_COMPLETE) return;
spAnimationState_setAnimationByName(state, 0, "empty", false);
spAnimationState_update(state, 0);
spAnimationState_apply(state, skeleton);
}
...
TrackEntry* entry = spAnimationState_setAnimationByName(state, 0, "run", true);
entry.listener = (spAnimationStateListener)&spineAnimStateHandler;
Of course for such a simple example you would use AnimationState addAnimation
:
spAnimationState_setAnimationByName(state, 0, "run", true);
spAnimationState_addAnimationByName(state, 0, "empty", true, 0);