Skip to main content

minifb_ui/
anim.rs

1/// Easing function type
2#[derive(Clone, Copy, Default)]
3pub enum Easing {
4    #[default]
5    Linear,
6    EaseIn,
7    EaseOut,
8    EaseInOut,
9}
10
11impl Easing {
12    fn apply(&self, t: f32) -> f32 {
13        match self {
14            Easing::Linear => t,
15            Easing::EaseIn => t * t,
16            Easing::EaseOut => 1.0 - (1.0 - t) * (1.0 - t),
17            Easing::EaseInOut => {
18                if t < 0.5 {
19                    2.0 * t * t
20                } else {
21                    1.0 - (-2.0 * t + 2.0).powi(2) / 2.0
22                }
23            }
24        }
25    }
26}
27
28/// Smoothly interpolates a value toward a target over time
29pub struct Tween {
30    current: f32,
31    target: f32,
32    /// Linear speed per frame (before easing)
33    speed: f32,
34    easing: Easing,
35    /// Internal progress 0.0–1.0 through current transition
36    progress: f32,
37    start_value: f32,
38}
39
40impl Tween {
41    pub fn new(initial: f32, speed: f32) -> Self {
42        Self {
43            current: initial,
44            target: initial,
45            speed,
46            easing: Easing::Linear,
47            progress: 1.0,
48            start_value: initial,
49        }
50    }
51
52    pub fn with_easing(mut self, easing: Easing) -> Self {
53        self.easing = easing;
54        self
55    }
56
57    /// Sets a new target. Resets internal progress for eased transitions.
58    pub fn set_target(&mut self, target: f32) {
59        if (target - self.target).abs() > f32::EPSILON {
60            self.target = target;
61            self.start_value = self.current;
62            self.progress = 0.0;
63        }
64    }
65
66    /// Advances the animation by one frame. Call once per frame.
67    pub fn update(&mut self) {
68        if self.progress >= 1.0 {
69            self.current = self.target;
70            return;
71        }
72
73        self.progress = (self.progress + self.speed).min(1.0);
74        let eased = self.easing.apply(self.progress);
75        self.current = self.start_value + (self.target - self.start_value) * eased;
76    }
77
78    /// Returns the current interpolated value
79    pub fn value(&self) -> f32 {
80        self.current
81    }
82
83    /// Returns true if the tween has reached its target
84    pub fn done(&self) -> bool {
85        self.progress >= 1.0
86    }
87
88    /// Immediately jumps to the target value
89    pub fn snap(&mut self) {
90        self.current = self.target;
91        self.progress = 1.0;
92    }
93}