Skip to main content

animate_core/spring/
once.rs

1use crate::spring::{Distance, Settled};
2use crate::{Animate, IS_ANIMATING, Once, SpringAnim, Spring, SpringParams, delta};
3
4impl<T, I> Animate for Spring<T, I, Once>
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            return;
20        }
21
22        let (new_pos, new_vel) = (self.state.interp)(
23            &self.state.current,
24            &self.state.target,
25            &self.state.velocity,
26            self.state.params,
27            dt,
28        );
29
30        let delta = new_pos.distance(&self.state.target);
31
32        if super::has_settled(delta, &new_vel, self.state.params.epsilon) {
33            self.state.current = std::mem::take(&mut self.state.target);
34            self.state.velocity = T::Velocity::default();
35            self.state.active = false;
36        } else {
37            self.state.current = new_pos;
38            self.state.velocity = new_vel;
39            IS_ANIMATING.store(true, std::sync::atomic::Ordering::Relaxed);
40        }
41    }
42
43    fn get(&self) -> &T {
44        &self.state.current
45    }
46
47    fn set(&mut self, target: T) {
48        self.state.target = target;
49        self.state.active = true;
50    }
51
52    fn target(&self) -> &T {
53        if self.state.active {
54            &self.state.target
55        } else {
56            &self.state.current
57        }
58    }
59}