Jphwth

In previous C runtime versions skeletons always stayed in the exact same state (I mean bones transformations, etc..) they were left after their animation(s) has ended. And that was pretty useful (i.e. I could call setAnimation a few updates later, and not right away upon getting "complete" event, and during that time - picture on the screen stays consistent).

After the recent update though skeletons started to reset themselves right after track ends it's last animation. And I don't even sure if that was an intended change in the logic.

It was also useful in cases where I need to set animation timeline to its end and take the final bones positions or some other info. Now I have to set trackTime to trackEnd * 0.99 (which is not entirely correct) instead of 1.0, otherwise I get wrong values;
Jphwth
  • 記事: 4

puzzler

Yeah, I'm also interested to leave animation at last frame. Is it possible?
puzzler
  • 記事: 107

Pharan

This is working as intended.
If you want to hold the last pose, set trackEnd to positive infinity or a maximum type value.
アバター
Pharan
  • 記事: 5366

puzzler

Hm, but I need complete event + keep last position. If I set trackEnd to infinity, do I get complete event?
puzzler
  • 記事: 107

Pharan

Judging from the code, you should get the Complete event.
spine-runtimes/AnimationState.c at master

AnimationState.c
if (entry->loop ? (trackLastWrapped > FMOD(entry->trackTime, duration))
: (animationTime >= animationEnd && entry->animationLast < animationEnd)) {
_spEventQueue_complete(internal->queue, entry);
}
AnimationState.java
// Queue complete if completed a loop iteration or the animation.
if (entry.loop ? (trackLastWrapped > entry.trackTime % duration)
: (animationTime >= animationEnd && entry.animationLast < animationEnd)) {
queue.complete(entry);
}
アバター
Pharan
  • 記事: 5366

Nate

For looping animations we default trackEnd to essentially forever. For non-looping we default it to the animation duration. Maybe it would make sense to use the same default for both looping and non-looping? That would mean by default animations continue being applied, even if non-looping, and if you want the animation to stop being applied you have to explicitly set trackEnd or play another animation. Thoughts?
アバター
Nate

Nate
  • 記事: 9337

puzzler

Looks good for my side.
puzzler
  • 記事: 107

Nate

We have made the change so trackEnd defaults to forever for both looping and non-looping animations. This will make it to Git master for all runtimes soon.
アバター
Nate

Nate
  • 記事: 9337

RafaSKB

I just tried the latest version from master but for some reason AnimationStateListener's end method isn't being called [libgdx]
RafaSKB
  • 記事: 12

Nate

That's because animations continue being applied until a new animation is set or the track is cleared. See TrackEntry trackEnd.

You could also listener for complete instead of end.

Sorry if AnimationState functionality feels like moving target, but we felt the trackEnd default value change was worth it. The sooner the less overall pain it causes. We don't have plans for any other changes in 3.5 that affect how the API is used.
アバター
Nate

Nate
  • 記事: 9337

RafaSKB

Yes I completely understand and agree that if aggressive API changes need to be made, the sooner the better.

Thanks for the complete vs end tip, that might solve it all :)
RafaSKB
  • 記事: 12

BinaryCats

Nate さんが書きました:We have made the change so trackEnd defaults to forever for both looping and non-looping animations. This will make it to Git master for all runtimes soon.
Does this now mean that attachment stuff over multiple tracks will now work.

i.e.
SetAnimation("attachment on",0,false) //999 frames
AddAnimation("attachment Off",1,0.5/delay/, false)// 1 frame

attachment off will continue to be applied. iirc you suggested that I needed to set the track end time to #inf
アバター
BinaryCats
  • 記事: 1299

badlogic

Yes, that should work now.
アバター
badlogic

Mario
  • 記事: 2168

Brunz

Nate さんが書きました:That's because animations continue being applied until a new animation is set or the track is cleared.
I was updating some legacy code to the 3.6 runtime, and my End Listeners stop working. By comparing with my previous version, I found out that in the AnimationState.c update function I had this
/* End non-looping animation when it reaches its end time and there is no next entry. */
if (!current->loop && current->lastTime >= current->endTime) spAnimationState_clearTrack(self, i);
and now there's this
/* Clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. */
if (current->trackLast >= current->trackEnd && current->mixingFrom == 0) {
I understand the changes made in 3.5 to trackEnd, but not how to get the same I had before. In order to keep the previous pose after the animation, trackEnd should be kept at INT_MAX, but then how should the track be cleared in order to fire the End Event?
Brunz
  • 記事: 5

Nate

If TrackEntry trackEnd is used to keep applying the animation after it is completed (which is the default behavior), then AnimationStateListener end isn't quite what you want. You probably want AnimationStateListener complete.
アバター
Nate

Nate
  • 記事: 9337

Brunz

Thanks for the quick response.

Quickly trying to use AnimationStateListener complete instead of end in some cases, resulted in a better result, but still not the same as before the update. Probably more changes would be needed in other functions, which we probable can't make now.

However, I think I am missing the right usage for the End Listeners then (and how to use them, since trackEnd doesn't let the track being cleared), and how to accomplish the same behaviour as before.
Brunz
  • 記事: 5

Nate

If you want trackEnd to clear the track when the animation duration is reached:
TrackEntry entry = animationState.addAnimation(...);
entry.trackEnd = entry.animation.duration;
This was the old behavior for non-looping animations. The default was changed to match looping animations, which continue being applied. There was discussion and the reasoning was good, though I don't remember it off the top of my head.

If you want the animation to continue being applied past its duration, that is the default behavior but end won't fire, as you found, because end means the track entry is done and won't be applied again.
アバター
Nate

Nate
  • 記事: 9337

Brunz

Ok, last question :p

Is it possible to keep the last pose after the animation duration is reached, other then by having the trackEnd set to infinite?
In other words, can I have both end event and keep last position.
Brunz
  • 記事: 5

Nate

When trackEnd is reached, the track is cleared. When the track is cleared, the animation will no longer be applied, so end occurs. Instead of using trackEnd you could clear the track yourself at the right time.

See exactly when each event occurs here:
AnimationStateListener
If you don't want to use trackEnd to clear the track, then the end event isn't what you want.

Again, you can leave trackEnd so the animation continues being applied, then listen for complete which for a non-looping animation happens once when the animation duration is reached.
アバター
Nate

Nate
  • 記事: 9337


Return to Runtimes