Skip to main content

animate_core/spring/
cycle.rs

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