virtualizer_adapter/
tween.rs1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct Tween {
9 pub from: u64,
10 pub to: u64,
11 pub start_ms: u64,
12 pub duration_ms: u64,
13 pub easing: Easing,
14}
15
16impl Tween {
17 pub fn new(from: u64, to: u64, start_ms: u64, duration_ms: u64, easing: Easing) -> Self {
21 Self {
22 from,
23 to,
24 start_ms,
25 duration_ms: duration_ms.max(1),
26 easing,
27 }
28 }
29
30 pub fn is_done(&self, now_ms: u64) -> bool {
31 now_ms.saturating_sub(self.start_ms) >= self.duration_ms
32 }
33
34 pub fn sample(&self, now_ms: u64) -> u64 {
36 let elapsed = now_ms.saturating_sub(self.start_ms);
37 let t = (elapsed as f32 / self.duration_ms as f32).clamp(0.0, 1.0);
38 let eased = self.easing.sample(t);
39
40 let from = self.from as f32;
41 let to = self.to as f32;
42 let v = from + (to - from) * eased;
43 v.max(0.0) as u64
44 }
45
46 pub fn retarget(&mut self, now_ms: u64, new_to: u64, duration_ms: u64) {
48 let cur = self.sample(now_ms);
49 *self = Self::new(cur, new_to, now_ms, duration_ms, self.easing);
50 }
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
56pub enum Easing {
57 Linear,
58 SmoothStep,
59 EaseInOutCubic,
60}
61
62impl Easing {
63 pub fn sample(self, t: f32) -> f32 {
65 match self {
66 Self::Linear => t,
67 Self::SmoothStep => t * t * (3.0 - 2.0 * t),
68 Self::EaseInOutCubic => {
69 if t < 0.5 {
70 4.0 * t * t * t
71 } else {
72 let u = -2.0 * t + 2.0;
73 1.0 - (u * u * u) / 2.0
74 }
75 }
76 }
77 }
78}