use ranim_core::animation::{AnimationCell, Eval};
pub trait LaggedAnim<T>: Sized + 'static {
fn lagged(
&mut self,
lag_ratio: f64,
anim_func: impl FnMut(&mut T) -> AnimationCell<T>,
) -> AnimationCell<Vec<T>>;
}
impl<T: Clone + 'static, I> LaggedAnim<T> for I
where
for<'a> &'a mut I: IntoIterator<Item = &'a mut T>,
I: 'static,
{
fn lagged(
&mut self,
lag_ratio: f64,
anim_func: impl FnMut(&mut T) -> AnimationCell<T>,
) -> AnimationCell<Vec<T>> {
Lagged::new(lag_ratio, self.into_iter().map(anim_func).collect()).into_animation_cell()
}
}
pub struct Lagged<T> {
anims: Vec<AnimationCell<T>>,
lag_ratio: f64,
}
impl<T> Lagged<T> {
pub fn new(lag_ratio: f64, anims: Vec<AnimationCell<T>>) -> Self {
Self { anims, lag_ratio }
}
}
impl<T: Clone, I: FromIterator<T>> Eval<I> for Lagged<T> {
fn eval_alpha(&self, alpha: f64) -> I {
let unit_time = 1.0 / (1.0 + (self.anims.len() - 1) as f64 * self.lag_ratio);
let unit_lagged_time = unit_time * self.lag_ratio;
self.anims
.iter()
.enumerate()
.map(|(i, anim)| {
let start = unit_lagged_time * i as f64;
let alpha = (alpha - start) / unit_time;
let alpha = alpha.clamp(0.0, 1.0);
anim.eval_alpha(alpha)
})
.collect()
}
}