pub use instant::Duration;
use crate::{
animation::{AnimationMode, Tween},
spring::Spring,
};
#[derive(Debug, Clone, Copy)]
pub struct Motion {
pub initial: f32,
pub target: f32,
pub duration: Duration,
pub delay: Duration,
pub mode: AnimationMode,
pub on_complete: Option<fn()>,
}
impl Motion {
pub fn new(initial: f32) -> Self {
Self {
initial,
target: initial,
duration: Duration::from_millis(300),
delay: Duration::from_millis(0),
mode: AnimationMode::default(),
on_complete: None,
}
}
pub fn to(mut self, target: f32) -> Self {
self.target = target;
self
}
pub fn animate(self, target: f32) -> Self {
self.to(target)
}
fn validate_duration(duration: Duration) -> Duration {
let millis = duration.as_millis();
if millis == 0 || millis > u64::MAX as u128 {
Duration::from_millis(300) } else {
duration
}
}
pub fn duration(mut self, duration: Duration) -> Self {
let safe_duration = Self::validate_duration(duration);
self.duration = safe_duration;
self.mode = AnimationMode::Tween(Tween::new(safe_duration));
self
}
pub fn spring(mut self, config: Spring) -> Self {
self.mode = AnimationMode::Spring(config);
self
}
pub fn mode(mut self, mode: AnimationMode) -> Self {
self.mode = mode;
self
}
pub fn update_spring(
current: f32,
target: f32,
velocity: &mut f32,
spring: &Spring,
dt: f32,
) -> f32 {
let force = spring.stiffness * (target - current);
let damping = spring.damping * *velocity;
let acceleration = (force - damping) / spring.mass;
*velocity += acceleration * dt;
current + *velocity * dt
}
pub fn easing(mut self, easing: fn(f32, f32, f32, f32) -> f32) -> Self {
self.mode = match self.mode {
AnimationMode::Tween(tween) => AnimationMode::Tween(tween.with_easing(easing)),
_ => self.mode,
};
self
}
pub fn on_complete(mut self, f: fn()) -> Self {
self.on_complete = Some(f);
self
}
pub fn delay(mut self, delay: Duration) -> Self {
self.delay = delay;
self
}
}