Skip to main content

animate_core/
lib.rs

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