Skip to main content

animate_core/spring/
alternate.rs

1use 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}