use std::sync::{Arc, Mutex};
use crate::animations::{spring::Spring, tween::Tween};
use instant::Duration;
pub trait Animatable:
Copy
+ 'static
+ Default
+ std::ops::Add<Output = Self>
+ std::ops::Sub<Output = Self>
+ std::ops::Mul<f32, Output = Self>
{
fn interpolate(&self, target: &Self, t: f32) -> Self;
fn magnitude(&self) -> f32;
fn epsilon() -> f32 {
0.01 }
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AnimationMode {
Tween(Tween),
Spring(Spring),
}
impl Default for AnimationMode {
fn default() -> Self {
Self::Tween(Tween::default())
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub enum LoopMode {
#[default]
None,
Infinite,
Times(u8),
Alternate,
AlternateTimes(u8),
}
pub type OnComplete = Arc<Mutex<dyn FnMut() + Send + 'static>>;
#[derive(Clone, Default)]
pub struct AnimationConfig {
pub mode: AnimationMode,
pub loop_mode: Option<LoopMode>,
pub delay: Duration,
pub on_complete: Option<Arc<Mutex<dyn FnMut() + Send>>>,
pub epsilon: Option<f32>,
}
impl AnimationConfig {
pub fn new(mode: AnimationMode) -> Self {
Self {
mode,
loop_mode: None,
delay: Duration::default(),
on_complete: None,
epsilon: None,
}
}
pub fn with_loop(mut self, loop_mode: LoopMode) -> Self {
self.loop_mode = Some(loop_mode);
self
}
pub fn with_delay(mut self, delay: Duration) -> Self {
self.delay = delay;
self
}
pub fn with_on_complete<F>(mut self, f: F) -> Self
where
F: FnMut() + Send + 'static,
{
self.on_complete = Some(Arc::new(Mutex::new(f)));
self
}
pub fn with_epsilon(mut self, epsilon: f32) -> Self {
self.epsilon = Some(epsilon);
self
}
pub fn get_duration(&self) -> Duration {
match &self.mode {
AnimationMode::Spring(_) => {
Duration::from_secs_f32(1.0) }
AnimationMode::Tween(tween) => {
let base_duration = tween.duration;
match self.loop_mode {
Some(LoopMode::Infinite) => Duration::from_secs(f32::INFINITY as u64),
Some(LoopMode::Times(count)) => base_duration * count.into(),
Some(LoopMode::Alternate) => Duration::from_secs(f32::INFINITY as u64),
Some(LoopMode::AlternateTimes(count)) => base_duration * (count * 2).into(),
Some(LoopMode::None) | None => base_duration,
}
}
}
}
pub fn execute_completion(&mut self) {
if let Some(on_complete) = &self.on_complete
&& let Ok(mut callback) = on_complete.lock()
{
callback();
}
}
}