fix(anim): handle reversed frame range in BuildBlendedFrame

Backward-playback nodes (TurnLeft, SideStepLeft) have LowFrame >
HighFrame after multiply_framerate swaps them. Math.Clamp(x, 19, 0)
throws because min > max.

Fix: compute rangeLo/rangeHi from Min/Max of Low/High, use those
for clamping. Also step nextIdx in the playback direction (forward
+1, backward -1) instead of always +1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-13 12:31:32 +02:00
parent 67b51a3e6f
commit ca7ae45518

View file

@ -487,11 +487,26 @@ public sealed class AnimationSequencer
int numPartFrames = curr.Anim.PartFrames.Count;
int frameIdx = (int)Math.Floor(_frameNum);
frameIdx = Math.Clamp(frameIdx, curr.LowFrame, Math.Min(curr.HighFrame, numPartFrames - 1));
// For backward playback, LowFrame > HighFrame. Use actual min/max
// of the two to get a valid range for clamping.
int rangeLo = Math.Min(curr.LowFrame, curr.HighFrame);
int rangeHi = Math.Min(Math.Max(curr.LowFrame, curr.HighFrame), numPartFrames - 1);
frameIdx = Math.Clamp(frameIdx, rangeLo, rangeHi);
int nextIdx = frameIdx + 1;
if (nextIdx > curr.HighFrame || nextIdx >= numPartFrames)
nextIdx = curr.LowFrame;
// Next frame for interpolation: step in the playback direction.
int nextIdx;
if (curr.Framerate >= 0f)
{
nextIdx = frameIdx + 1;
if (nextIdx > rangeHi || nextIdx >= numPartFrames)
nextIdx = rangeLo; // wrap forward
}
else
{
nextIdx = frameIdx - 1;
if (nextIdx < rangeLo)
nextIdx = rangeHi; // wrap backward
}
float t = _frameNum - (float)Math.Floor(_frameNum);
if (t < 0f) t = 0f;