animate_core/spring/
cycle.rs1use crate::spring::{Distance, Settled};
2use crate::{Animate, Cycle, IS_ANIMATING, SpringAnim, Spring, SpringParams, delta};
3
4impl<T, I> Animate for Spring<T, I, Cycle>
5where
6 T: SpringAnim + PartialEq + Distance,
7 T::Velocity: Settled,
8 I: Fn(&T, &T, &T::Velocity, SpringParams, f64) -> (T, T::Velocity),
9{
10 type Value = T;
11
12 fn update(&mut self) {
13 if !self.state.active {
14 return;
15 }
16
17 let dt = delta();
18 if dt == 0.0 {
19 IS_ANIMATING.store(true, std::sync::atomic::Ordering::Relaxed);
20 return;
21 }
22
23 if self.state.pending {
24 self.state.origin = std::mem::take(&mut self.state.current);
25 self.state.current = (self.state.interp)(
26 &self.state.origin,
27 &self.state.origin,
28 &T::Velocity::default(),
29 self.state.params,
30 0.0,
31 )
32 .0;
33 self.state.pending = false;
34 }
35
36 let (new_pos, new_vel) = (self.state.interp)(
37 &self.state.current,
38 &self.state.target,
39 &self.state.velocity,
40 self.state.params,
41 dt,
42 );
43
44 let delta = new_pos.distance(&self.state.target);
45
46 if super::has_settled(delta, &new_vel, self.state.params.epsilon) {
47 self.state.current = (self.state.interp)(
48 &self.state.origin,
49 &self.state.origin,
50 &T::Velocity::default(),
51 self.state.params,
52 0.0,
53 )
54 .0;
55 self.state.velocity = T::Velocity::default();
56 } else {
57 self.state.current = new_pos;
58 self.state.velocity = new_vel;
59 }
60
61 IS_ANIMATING.store(true, std::sync::atomic::Ordering::Relaxed);
62 }
63
64 fn get(&self) -> &T {
65 &self.state.current
66 }
67
68 fn set(&mut self, target: T) {
69 self.state.target = target;
70 self.state.active = true;
71 self.state.pending = true;
72 }
73
74 fn target(&self) -> &T {
75 &self.state.target
76 }
77}