summaryrefslogtreecommitdiff
path: root/src/animation.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/animation.zig')
-rw-r--r--src/animation.zig11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/animation.zig b/src/animation.zig
index 855fef03..713a8a30 100644
--- a/src/animation.zig
+++ b/src/animation.zig
@@ -1132,6 +1132,9 @@ pub fn Fade(comptime Value: type) type {
to: Value,
displayed: Value,
step: u16 = transition_steps,
+ /// Set off from partway through another fade: it eases out (moving
+ /// at once) instead of in and out, so it never stalls (§7.2).
+ retargeted: bool = false,
pub fn init(value: Value) Self {
return .{ .from = value, .to = value, .displayed = value };
@@ -1142,19 +1145,25 @@ pub fn Fade(comptime Value: type) type {
}
pub fn retarget(a: *Self, target: Value) void {
+ a.retargeted = a.isActive();
a.from = a.displayed;
a.to = target;
a.step = if (std.meta.eql(a.from, target)) transition_steps else 0;
if (a.step == transition_steps) a.displayed = target;
}
+ /// A state change eases in and out (§8.1); a retargeted one out.
+ const resolution: u16 = 1000;
+
pub fn advance(a: *Self) void {
if (!a.isActive()) return;
a.step += 1;
+ const t = @as(f32, @floatFromInt(a.step)) / @as(f32, @floatFromInt(transition_steps));
+ const eased = sample(if (a.retargeted) .out_cubic else .smooth, t);
a.displayed = if (a.step == transition_steps)
a.to
else
- Value.interpolate(a.from, a.to, a.step, transition_steps);
+ Value.interpolate(a.from, a.to, @intFromFloat(@round(eased * resolution)), resolution);
}
pub fn snap(a: *Self, value: Value) void {