use keyframe::EasingFunction; use crate::Color; pub trait AnimationLerp { fn lerp(&self, x: f32) -> T; } #[derive(Clone)] pub struct Animation { time: f32, duration: f32, in_delay: f32, out_delay: f32, from: T, to: T, function: F, direction: bool, } impl Animation { pub fn new(function: F, duration: f32, from: T, to: T) -> Self { Self { time: duration, duration, from, to, in_delay: 0.0, out_delay: 0.0, function, direction: false, } } pub fn update(&mut self, dt: f32) { self.time += dt; } pub fn is_active(&self) -> bool { self.time < self.duration } pub fn ease_in(&mut self) { if !self.direction { self.ease_toggle(); } } pub fn ease_out(&mut self) { if self.direction { self.ease_toggle(); } } pub fn ease_toggle(&mut self) { if self.is_active() { self.time = self.duration - self.time; } else if self.direction { self.time = -self.out_delay; } else { self.time = -self.in_delay; } self.direction = !self.direction; } pub fn set_in_delay(&mut self, delay: f32) { self.in_delay = delay; } pub fn set_out_delay(&mut self, delay: f32) { self.out_delay = delay; } pub fn clamped(&self) -> Option { if self.is_active() { if self.time <= 0.0 { if self.direction { Some(self.from) } else { Some(self.to) } } else { None } } else if self.direction { Some(self.to) } else { Some(self.from) } } } impl AnimationLerp for Animation { fn lerp(&self, x: f32) -> f32 { (1.0 - x) * self.from + x * self.to } } impl AnimationLerp for Animation { fn lerp(&self, x: f32) -> Color { let from: glam::Vec4 = self.from.into(); let to: glam::Vec4 = self.to.into(); let lerp = (1.0 - x) * from + x * to; lerp.into() } } impl Animation where F: EasingFunction, T: Copy, Animation: AnimationLerp, { pub fn get(&self) -> T { if let Some(clamped) = self.clamped() { clamped } else { let x = self.time / self.duration; let x = if self.direction { x } else { 1.0 - x }; let lerp = self.function.y(x as f64) as f32; self.lerp(lerp) } } pub fn ease_to(&mut self, to: T) { self.from = self.get(); self.to = to; self.time = 0.0; self.direction = true; } }