Skip to main content

animate_core/
lib.rs

1pub mod easing;
2mod macros;
3pub mod mode;
4pub mod types;
5
6use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
7
8pub use easing::*;
9pub use mode::*;
10
11pub static FRAME_TIME: AtomicUsize = AtomicUsize::new(0);
12pub static IS_ANIMATING: AtomicBool = AtomicBool::new(false);
13
14pub trait Animate {
15    type Value;
16    fn update(&mut self);
17    fn get(&self) -> &Self::Value;
18    fn set(&mut self, target: Self::Value);
19    fn target(&self) -> &Self::Value;
20}
21
22#[derive(Debug, Default)]
23pub(crate) struct StateInner<T> {
24    pub current: T,
25    pub start: T,
26    pub target: T,
27    pub started_at: Option<usize>,
28    pub pending: bool,
29}
30
31#[derive(Debug)]
32pub(crate) struct AnimateState<T, E, I>
33where
34    E: Fn(f64) -> f64,
35    I: Fn(&T, &T, f64) -> T,
36{
37    pub inner: StateInner<T>,
38    pub duration: f64,
39    pub easing: E,
40    pub interp: I,
41}
42
43impl<T: Default, E, I> AnimateState<T, E, I>
44where
45    E: Fn(f64) -> f64,
46    I: Fn(&T, &T, f64) -> T,
47{
48    pub fn new(initial: T, duration: f64, easing: E, interp: I) -> Self {
49        Self {
50            inner: StateInner {
51                current: initial,
52                start: Default::default(),
53                target: Default::default(),
54                started_at: None,
55                pending: false,
56            },
57            duration: duration.max(f64::MIN_POSITIVE),
58            easing,
59            interp,
60        }
61    }
62}
63
64pub trait Lerp {
65    fn lerp(start: &Self, end: &Self, t: f64) -> Self;
66}
67
68#[inline(always)]
69pub fn tick(delta: usize) {
70    FRAME_TIME.fetch_add(delta, Ordering::Relaxed);
71    IS_ANIMATING.store(false, Ordering::Relaxed);
72}
73
74pub fn is_animating() -> bool {
75    IS_ANIMATING.load(Ordering::Relaxed)
76}