ranim_anims/
lagged.rs

1use ranim_core::animation::{AnimationCell, Eval};
2
3// MARK: LaggedAnim
4/// The methods to create animations for `Group<T>`
5///
6/// # Example
7/// ```rust,ignore
8/// let item_group: Group::<VItem> = ...;
9/// let anim_lagged = item_group.lagged(0.5, |x| x.fade_in()); # lagged with ratio of 0.5
10/// let anim_not_lagged = item_group.lagged(0.0, |x| x.fade_in()); # not lagged (anim at the same time)
11/// ```
12pub trait LaggedAnim<T>: Sized + 'static {
13    /// Create a [`Lagged`] anim.
14    fn lagged(
15        &mut self,
16        lag_ratio: f64,
17        anim_func: impl FnMut(&mut T) -> AnimationCell<T>,
18    ) -> AnimationCell<Vec<T>>;
19}
20
21impl<T: Clone + 'static, I> LaggedAnim<T> for I
22where
23    for<'a> &'a mut I: IntoIterator<Item = &'a mut T>,
24    I: 'static,
25{
26    fn lagged(
27        &mut self,
28        lag_ratio: f64,
29        anim_func: impl FnMut(&mut T) -> AnimationCell<T>,
30    ) -> AnimationCell<Vec<T>> {
31        Lagged::new(lag_ratio, self.into_iter().map(anim_func).collect()).into_animation_cell()
32    }
33}
34
35// pub fn lagged<T, I>(
36//     lag_ratio: f64,
37//     mut anim_func: impl FnMut(T) -> AnimationCell<T>,
38// ) -> impl FnMut(I) -> Lagged<T>
39// where
40//     I: IntoIterator<Item = T>,
41// {
42//     move |target| Lagged::new(target, lag_ratio, &mut anim_func)
43// }
44
45/// The lagged anim.
46///
47/// This is applyable to `IntoIterator<Item = T>`, and this will apply
48/// the anims in the order of the elements with the lag ratio.
49pub struct Lagged<T> {
50    anims: Vec<AnimationCell<T>>,
51    lag_ratio: f64,
52}
53
54impl<T> Lagged<T> {
55    /// Constructor
56    pub fn new(lag_ratio: f64, anims: Vec<AnimationCell<T>>) -> Self {
57        Self { anims, lag_ratio }
58    }
59}
60
61impl<T: Clone, I: FromIterator<T>> Eval<I> for Lagged<T> {
62    fn eval_alpha(&self, alpha: f64) -> I {
63        // -|--
64        //  -|--
65        //   -|--
66        // total_time - unit_time * (1.0 - lag_ratio)  = unit_time * lag_ratio * n
67        // total_time = unit_time * (1.0 + (n - 1) lag_ratio)
68        let unit_time = 1.0 / (1.0 + (self.anims.len() - 1) as f64 * self.lag_ratio);
69        let unit_lagged_time = unit_time * self.lag_ratio;
70        self.anims
71            .iter()
72            .enumerate()
73            .map(|(i, anim)| {
74                let start = unit_lagged_time * i as f64;
75
76                let alpha = (alpha - start) / unit_time;
77                let alpha = alpha.clamp(0.0, 1.0);
78                anim.eval_alpha(alpha)
79            })
80            .collect()
81    }
82}