1use ranim_core::animation::Eval;
2
3pub trait LaggedAnim<T: Clone>: Sized + 'static {
13 fn lagged<E>(&mut self, lag_ratio: f64, anim_func: impl FnMut(&mut T) -> E) -> Lagged<T, E>
15 where
16 E: Eval<Output = T> + 'static;
17}
18
19impl<T: Clone + 'static, I> LaggedAnim<T> for I
20where
21 for<'a> &'a mut I: IntoIterator<Item = &'a mut T>,
22 I: 'static,
23{
24 fn lagged<E>(&mut self, lag_ratio: f64, anim_func: impl FnMut(&mut T) -> E) -> Lagged<T, E>
25 where
26 E: Eval<Output = T> + 'static,
27 {
28 Lagged::new(lag_ratio, self.into_iter().map(anim_func).collect())
29 }
30}
31
32pub struct Lagged<T: Clone, E: Eval<Output = T>> {
47 anims: Vec<E>,
48 lag_ratio: f64,
49 _output: std::marker::PhantomData<fn() -> T>,
50}
51
52impl<T: Clone, E: Eval<Output = T>> Lagged<T, E> {
53 pub fn new(lag_ratio: f64, anims: Vec<E>) -> Self {
55 Self {
56 anims,
57 lag_ratio,
58 _output: std::marker::PhantomData,
59 }
60 }
61}
62
63impl<T: Clone, E: Eval<Output = T>> Eval for Lagged<T, E> {
64 type Output = Vec<T>;
65
66 fn eval_alpha(&self, alpha: f64) -> Self::Output {
67 let unit_time = 1.0 / (1.0 + (self.anims.len() - 1) as f64 * self.lag_ratio);
73 let unit_lagged_time = unit_time * self.lag_ratio;
74 self.anims
75 .iter()
76 .enumerate()
77 .map(|(i, anim)| {
78 let start = unit_lagged_time * i as f64;
79
80 let alpha = (alpha - start) / unit_time;
81 let alpha = alpha.clamp(0.0, 1.0);
82 anim.eval_alpha(alpha)
83 })
84 .collect()
85 }
86}