uianimator/
default_animator_f64_quadratic.rs1use std::time::Instant;
2
3use crate::Animator;
4
5pub struct DefaultAnimatorF64Quadratic {
6 target_reach_half_duration: f64,
8 elapsed_duration: f64,
9 decreasing: bool,
10 start: f64,
11 time: Instant,
12 target: f64,
13 speed: f64,
15}
16impl DefaultAnimatorF64Quadratic {
17 pub fn new(value: f64, speed: f64) -> Self {
18 Self {
19 target_reach_half_duration: 0.0,
20 elapsed_duration: 0.0,
21 decreasing: false,
22 start: value,
23 time: Instant::now(),
24 target: value,
25 speed,
26 }
27 }
28 pub fn target(&self) -> f64 {
29 self.target
30 }
31}
32impl Animator for DefaultAnimatorF64Quadratic {
33 type Value = f64;
34 type Time = Instant;
35
36 fn get_value(&self, time: Self::Time) -> Self::Value {
37 let elapsed = self.elapsed_duration
38 + self.speed * time.saturating_duration_since(self.time).as_secs_f64();
39 if elapsed < self.target_reach_half_duration {
40 if self.decreasing {
42 self.start - elapsed * elapsed
43 } else {
44 self.start + elapsed * elapsed
45 }
46 } else {
47 let remaining = (self.target_reach_half_duration * 2.0) - elapsed;
49 if remaining > 0.0 {
50 if self.decreasing {
51 self.target + remaining * remaining
52 } else {
53 self.target - remaining * remaining
54 }
55 } else {
56 self.target
57 }
58 }
59 }
60 fn set_target(&mut self, target: Self::Value, time: Self::Time) {
61 if self.target == target {
62 return;
63 }
64 let elapsed = self.elapsed_duration
65 + self.speed * time.saturating_duration_since(self.time).as_secs_f64();
66 let mut set_time = true;
67 self.start = if elapsed < self.target_reach_half_duration {
69 let slow_down_now_end_value = if self.decreasing {
70 self.start - elapsed * elapsed * 2.0
71 } else {
72 self.start + elapsed * elapsed * 2.0
73 };
74 let new_decreasing = if self.decreasing {
75 target <= slow_down_now_end_value
76 } else {
77 target < slow_down_now_end_value
78 };
79 if new_decreasing == self.decreasing {
81 set_time = false;
83 self.start
84 } else {
85 self.decreasing = new_decreasing;
87 self.elapsed_duration = -elapsed;
89 slow_down_now_end_value
90 }
91 } else {
92 let remaining = (self.target_reach_half_duration * 2.0) - elapsed;
93 if remaining > 0.0 {
94 let new_decreasing = if self.decreasing {
96 target <= self.target
97 } else {
98 target < self.target
99 };
100 if new_decreasing != self.decreasing {
101 self.decreasing = new_decreasing;
103 self.elapsed_duration = -remaining;
105 self.target
106 } else {
107 self.decreasing = new_decreasing;
109 self.elapsed_duration = remaining;
111 if self.decreasing {
112 self.target + remaining * remaining * 2.0
113 } else {
114 self.target - remaining * remaining * 2.0
115 }
116 }
117 } else {
118 self.elapsed_duration = 0.0;
120 self.decreasing = target < self.target;
121 self.target
122 }
123 };
124 self.target = target;
125 self.target_reach_half_duration = (0.5 * (self.start - self.target).abs()).sqrt();
126 if set_time {
127 self.time = time;
128 }
129 }
130}