1use std::time::{Duration, Instant};
2
3#[must_use]
6pub fn lerp(start: f32, end: f32, p: f32) -> f32 {
7 (1.0 - p) * start + p * end
8}
9
10#[must_use]
13pub fn slerp(start: f32, end: f32, p: f32) -> f32 {
14 let t = smootherstep(p);
15 (1.0 - t) * start + t * end
16}
17
18pub fn smootherstep(t: f32) -> f32 {
20 (6.0 * t.powi(5) - 15.0 * t.powi(4) + 10.0 * t.powi(3)).clamp(0.0, 1.0)
21}
22
23#[derive(Default, Debug)]
24pub struct State {
25 pub last_change: Option<Instant>,
26}
27
28impl State {
29 pub fn changed(&mut self, dur: Duration) {
30 let t = self.t(dur, false);
31 let diff = dur.mul_f32(t.abs());
32 let now = Instant::now();
33 self.last_change = Some(now.checked_sub(diff).unwrap_or(now));
34 }
35
36 pub fn anim_done(&mut self, dur: Duration) {
37 if self
38 .last_change
39 .is_some_and(|t| Instant::now().duration_since(t) > dur)
40 {
41 self.last_change = None;
42 }
43 }
44
45 pub fn t(&self, dur: Duration, forward: bool) -> f32 {
46 let res = self.last_change.map_or(1., |t| {
47 Instant::now().duration_since(t).as_millis() as f32 / dur.as_millis() as f32
48 });
49 if forward { res } else { 1. - res }
50 }
51}