animate_core/spring/
once.rs1use 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}