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}