Skip to main content

animate_core/mode/
alternate.rs

1use crate::macros::impl_ops;
2use crate::{AnimateState, FRAME_TIME, IS_ANIMATING, Lerp};
3use std::sync::atomic::Ordering;
4
5#[derive(Debug)]
6pub struct Alternate<T, E, I>(pub(crate) AnimateState<T, E, I>)
7where
8    T: Lerp + PartialEq,
9    E: Fn(f64) -> f64,
10    I: Fn(&T, &T, f64) -> T;
11
12impl<T, E, I> Alternate<T, E, I>
13where
14    T: Lerp + PartialEq + Default,
15    E: Fn(f64) -> f64,
16    I: Fn(&T, &T, f64) -> T,
17{
18    pub fn new(initial: T, duration: f64, easing: E, interp: I) -> Self {
19        Self(AnimateState::new(initial, duration, easing, interp))
20    }
21
22    pub fn set(&mut self, target: T) {
23        let now = FRAME_TIME.load(Ordering::Relaxed);
24        let inner = self.0.inner.get_mut();
25        inner.start = std::mem::take(&mut inner.current);
26        inner.target = target;
27        inner.started_at = Some(now);
28    }
29
30    pub fn get(&self) -> &T {
31        let now = FRAME_TIME.load(Ordering::Relaxed);
32        unsafe {
33            let inner = &mut *self.0.inner.get();
34            if inner.last_update != now {
35                if let Some(start_t) = inner.started_at {
36                    if self.0.duration > 0.0 {
37                        let elapsed = now.saturating_sub(start_t) as f64;
38                        let cycle = (elapsed / self.0.duration) as u64;
39                        let t_raw = (elapsed % self.0.duration) / self.0.duration;
40                        let t = if cycle % 2 == 0 { t_raw } else { 1.0 - t_raw };
41
42                        inner.current =
43                            (self.0.interp)(&inner.start, &inner.target, (self.0.easing)(t));
44                    }
45                    inner.last_update = now;
46                    IS_ANIMATING.store(true, Ordering::Relaxed);
47                }
48            }
49            &inner.current
50        }
51    }
52
53    pub fn target(&self) -> &T {
54        unsafe { &(*self.0.inner.get()).target }
55    }
56}
57
58impl_ops!(Alternate);