Skip to main content

animate_core/tween/
once.rs

1use crate::{Animate, Once, TweenAnim, Tween, FRAME_TIME, IS_ANIMATING};
2use std::sync::atomic::Ordering;
3
4impl<T, E, I> Animate for Tween<T, E, I, Once>
5where
6    T: TweenAnim + PartialEq + Default,
7    E: Fn(f64) -> f64,
8    I: Fn(&T, &T, f64) -> T,
9{
10    type Value = T;
11
12    fn update(&mut self) {
13        if self.state.pending {
14            self.state.start = std::mem::take(&mut self.state.current);
15            self.state.pending = false;
16        }
17
18        if let Some(start_t) = self.state.started_at {
19            let now = FRAME_TIME.load(Ordering::Relaxed);
20            let elapsed = now.saturating_sub(start_t) as f64;
21            let t = (elapsed / self.state.duration).clamp(0.0, 1.0);
22
23            self.state.current =
24                (self.state.interp)(&self.state.start, &self.state.target, (self.state.easing)(t));
25
26            if t >= 1.0 {
27                self.state.started_at = None;
28            } else {
29                IS_ANIMATING.store(true, Ordering::Relaxed);
30            }
31        }
32    }
33
34    fn get(&self) -> &T {
35        &self.state.current
36    }
37
38    fn set(&mut self, target: T) {
39        let now = FRAME_TIME.load(Ordering::Relaxed);
40
41        self.state.target = target;
42        self.state.started_at = Some(now);
43        self.state.pending = true;
44    }
45
46    fn target(&self) -> &T {
47        if self.state.started_at.is_none() {
48            &self.state.current
49        } else {
50            &self.state.target
51        }
52    }
53}