feat(speed): switch Playback Speed to 0x–4x forward (drop reverse)
Real-browser eyeball: below-0x reverse jittered because the base loop clips aren't all-intra (the flagged risk). Narrow the slider to 0x–4x forward (still continuous, step=any); 0x still freezes; OS reduced-motion behavior unchanged. Removes the manual rAF reverse loop and the HEFScrub.reverseStep helper + its unit tests. Tests: node unit 10/10; a11y e2e 12/12 (Task 5 now 3 slider tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,31 +59,6 @@ test("integerCrossings: multiple crossings in travel order", () => {
|
||||
assert.deepEqual(S.integerCrossings(3.2, 1.8), [{ index: 3, dir: -1 }, { index: 2, dir: -1 }]);
|
||||
});
|
||||
|
||||
test("reverseStep: decrements within the loop region without wrapping", () => {
|
||||
// region [loopStart=3, duration=8]; step back absSpeed*dt = 0.5
|
||||
assert.deepEqual(S.reverseStep(5, 1, 0.5, 3, 8), { next: 4.5, wrapped: false });
|
||||
// landing exactly on the bottom boundary is the region edge, not a wrap
|
||||
assert.deepEqual(S.reverseStep(3.5, 1, 0.5, 3, 8), { next: 3, wrapped: false });
|
||||
});
|
||||
|
||||
test("reverseStep: wraps past the bottom boundary back to the tail (duration)", () => {
|
||||
// 3.2 - 0.5 = 2.7 < 3 -> overshoot 0.3 -> 8 - 0.3 = 7.7
|
||||
const r = S.reverseStep(3.2, 1, 0.5, 3, 8);
|
||||
assert.equal(r.wrapped, true);
|
||||
assert.ok(Math.abs(r.next - 7.7) < 1e-9, `next=${r.next}`);
|
||||
});
|
||||
|
||||
test("reverseStep: overshoot larger than the region length wraps modulo", () => {
|
||||
// region length L = 5; 3 - 7 = -4 -> overshoot 7 -> 7 % 5 = 2 -> 8 - 2 = 6
|
||||
const r = S.reverseStep(3, 1, 7, 3, 8);
|
||||
assert.equal(r.wrapped, true);
|
||||
assert.ok(Math.abs(r.next - 6) < 1e-9, `next=${r.next}`);
|
||||
});
|
||||
|
||||
test("reverseStep: degenerate region (duration <= loopStart) holds at duration", () => {
|
||||
assert.deepEqual(S.reverseStep(3, 1, 0.5, 3, 3), { next: 3, wrapped: false });
|
||||
});
|
||||
|
||||
test("loopLandFrame: descend lands on the morph's tail frame, ascend on its head", () => {
|
||||
// A morph spans src@0 (frac 0) -> dst@loopTailS (frac 1). Descending (dir>0) lands
|
||||
// on dst at frac 1 -> the base loop must continue from loopTailS. Ascending (dir<0)
|
||||
|
||||
Reference in New Issue
Block a user