Cool, glad it was helpful! It's good to hear that things are mostly easy to follow. I don't blame you for finding AnimationState difficult to follow. It's like Perl, even we forget the entire damn thing minutes after looking at it and have to relearn it every time. It has many edge cases and is difficult to unit test.
To explain AnimationState applyRotateTimeline
, first some background. The most common type of animation mixing in most software mixes the animations additively using weights which sum to 100%. For example, animation A is applied at 23%, B at 37%, and C at 40%. This is straightforward and works well in many cases, but doesn't allow for everything AnimationState does (mainly layering with multiple "tracks", IIRC). You can do this kind of mixing by using MixBlend add
with the Timeline API (it is also possible with AnimationState), but you'll have to manage the weights (alpha
parameter for Timeline apply
) yourself.
The other MixBlend modes do a kind of mixing that is between the setup and current pose and the timeline's pose. AFAIK Spine is the only software to do this. It allows for some really neat features in AnimationState, but requires that we are able to interpolate between any two poses and that comes with the some new problems. This is easy for most values, such as positions, but if you have 2 rotation values there are two possibilities for what is for example 50% between them, depending on whether you rotate clockwise or widdershins.
One solution is to just choose the direction that results in the smaller rotation. Eg, if you have 0 and 90 and need 50%, you'd use clockwise (45) and not counterclockwise (135). This works fine, except that we are not mixing two static rotations. Our rotations come from animations and represent the rotation of arms/legs/etc that are changing over time. It can happen that for part of the mix duration the shortest rotation between the rotation in the two animations is clockwise, but then changes to counterclockwise. When this happens the interpolated rotation flips nearly 180 degrees, which is almost never what you want. That can look like this:
Loading Image
To solve this, what we do is when we start mixing, we choose the rotation direction based on the shortest rotation. We remember that direction and use it for the rest of the mix. There's also some other logic there to handle when the bones cross, but that's the gist of it. During development we made a nutty little tool to visualize and test some extreme use cases:
Loading Image
If you are doing mixing with weights (MixBlend add
), you probably don't have to worry about this. If you are doing mixing between poses, most people use AnimationState and also don't have to worry about this.
I agree it would be nice to have more low level examples. FWIW, one of the few examples we have of the Timeline API is here:
spine-runtimes/MixTest.java at 3.8
Using AnimationState makes this sort of thing so much easier, most people do that. I don't know how Godot works, but I would guess it uses animation weights, so maybe you can go that route.