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}