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}