oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
2,112 bytes raw
1
const std = @import("std");
2
3
pub const Easing = enum {
4
    linear,
5
    ease_out,
6
    ease_in_out,
7
8
    pub fn apply(self: Easing, t: f64) f64 {
9
        return switch (self) {
10
            .linear => t,
11
            .ease_out => 1.0 - std.math.pow(f64, 1.0 - t, 3),
12
            .ease_in_out => if (t < 0.5)
13
                4.0 * t * t * t
14
            else
15
                1.0 - std.math.pow(f64, -2.0 * t + 2.0, 3) / 2.0,
16
        };
17
    }
18
};
19
20
pub const Animation_Config = struct {
21
    duration_ms: u64 = 150,
22
    easing: Easing = .ease_out,
23
};
24
25
pub const Scroll_Animation = struct {
26
    start_value: i32 = 0,
27
    end_value: i32 = 0,
28
    start_time: i64 = 0,
29
    duration_ms: u64 = 150,
30
    easing: Easing = .ease_out,
31
    active: bool = false,
32
33
    pub fn start(self: *Scroll_Animation, from: i32, to: i32, config: Animation_Config) void {
34
        if (from == to) {
35
            self.active = false;
36
            return;
37
        }
38
        self.start_value = from;
39
        self.end_value = to;
40
        self.start_time = std.time.milliTimestamp();
41
        self.duration_ms = config.duration_ms;
42
        self.easing = config.easing;
43
        self.active = true;
44
    }
45
46
    pub fn update(self: *Scroll_Animation) ?i32 {
47
        if (!self.active) return null;
48
49
        const now = std.time.milliTimestamp();
50
        const elapsed = now - self.start_time;
51
52
        if (elapsed >= @as(i64, @intCast(self.duration_ms))) {
53
            self.active = false;
54
            return self.end_value;
55
        }
56
57
        const t = @as(f64, @floatFromInt(elapsed)) / @as(f64, @floatFromInt(self.duration_ms));
58
        const eased = self.easing.apply(t);
59
        const diff = @as(f64, @floatFromInt(self.end_value - self.start_value));
60
        const current = @as(f64, @floatFromInt(self.start_value)) + (diff * eased);
61
62
        return @intFromFloat(current);
63
    }
64
65
    pub fn is_active(self: *const Scroll_Animation) bool {
66
        return self.active;
67
    }
68
69
    pub fn target(self: *const Scroll_Animation) i32 {
70
        return self.end_value;
71
    }
72
73
    pub fn stop(self: *Scroll_Animation) void {
74
        self.active = false;
75
    }
76
};