animate_core/spring/
alternate.rs1use crate::spring::{Distance, Settled};
2use crate::{Alternate, Animate, IS_ANIMATING, SpringAnim, Spring, SpringParams, delta};
3
4impl<T, I> Animate for Spring<T, I, Alternate>
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.target,
49 &self.state.target,
50 &T::Velocity::default(),
51 self.state.params,
52 0.0,
53 )
54 .0;
55 self.state.velocity = T::Velocity::default();
56
57 std::mem::swap(&mut self.state.origin, &mut self.state.target);
58 self.advancing = !self.advancing;
59 } else {
60 self.state.current = new_pos;
61 self.state.velocity = new_vel;
62 }
63
64 IS_ANIMATING.store(true, std::sync::atomic::Ordering::Relaxed);
65 }
66
67 fn get(&self) -> &T {
68 &self.state.current
69 }
70
71 fn set(&mut self, target: T) {
72 self.state.target = target;
73 self.state.active = true;
74 self.state.pending = true;
75 self.advancing = true;
76 }
77
78 fn target(&self) -> &T {
79 &self.state.target
80 }
81}