diff options
Diffstat (limited to 'src/animation.zig')
| -rw-r--r-- | src/animation.zig | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/animation.zig b/src/animation.zig index 9002a2c6..12d352d1 100644 --- a/src/animation.zig +++ b/src/animation.zig @@ -744,6 +744,14 @@ pub const Spring = struct { return spring.at(now_ns).value; } + /// Moves what it shows by `by` at `now_ns`, its speed kept, toward the + /// same target (a scroll's picture falling behind the text it follows), + /// at `motion`'s pace, never past its mark. + pub fn carry(spring: *Spring, by: f32, now_ns: u64, motion: Motion) void { + const state = spring.at(now_ns); + spring.* = .{ .omega = motion.omega, .zeta = 1, .target = spring.target, .from = state.value + by, .velocity = state.velocity, .from_ns = now_ns, .settled = false }; + } + /// Heads for `target` from wherever it is at `now_ns`, moving as it was, /// at the pace and damping `motion` gives: at once when it is `off`. pub fn retarget(spring: *Spring, target: f32, now_ns: u64, motion: Motion) void { @@ -769,6 +777,24 @@ pub const Spring = struct { } }; +test "a carried spring keeps its speed, heads back to its mark and never passes it" { + const ms = std.time.ns_per_ms; + var spring: Spring = .{}; + const smooth = Motion.of(.smooth); + spring.carry(-3, 0, smooth); + try std.testing.expectEqual(@as(f32, -3), spring.value(0)); + const mid = spring.at(40 * ms); + try std.testing.expect(mid.value > -3 and mid.value < 0 and mid.velocity > 0); + // Another notch mid-way: one more row behind, still moving back. + spring.carry(-1, 40 * ms, smooth); + const after = spring.at(40 * ms); + try std.testing.expectApproxEqAbs(mid.value - 1, after.value, 1e-5); + try std.testing.expectApproxEqAbs(mid.velocity, after.velocity, 1e-4); + var t: u64 = 40 * ms; + while (spring.step(t)) : (t += frame_ns) try std.testing.expect(spring.value(t) <= 1e-4); + try std.testing.expect(t < 400 * ms); +} + test "a spring settles without overshoot and keeps its velocity when retargeted" { var spring: Spring = .{}; const ms = std.time.ns_per_ms; |
