diff --git a/src/AcDream.Core/Physics/AnimationSequencer.cs b/src/AcDream.Core/Physics/AnimationSequencer.cs index 4c2226f..12f1abf 100644 --- a/src/AcDream.Core/Physics/AnimationSequencer.cs +++ b/src/AcDream.Core/Physics/AnimationSequencer.cs @@ -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;