ranim_anims/
morph.rs

1use ranim_core::{
2    animation::{AnimationCell, Eval},
3    traits::{Alignable, Interpolatable},
4    utils::rate_functions::smooth,
5};
6
7// ANCHOR: MorphRequirement
8/// The requirement of [`Morph`]
9pub trait MorphRequirement: Alignable + Interpolatable + Clone {}
10impl<T: Alignable + Interpolatable + Clone> MorphRequirement for T {}
11// ANCHOR_END: MorphRequirement
12
13// ANCHOR: MorphAnim
14/// The methods to create animations for `T` that satisfies [`MorphRequirement`]
15pub trait MorphAnim: MorphRequirement + Sized + 'static {
16    /// Create a [`Morph`] anim with a func.
17    fn morph<F: Fn(&mut Self)>(&mut self, f: F) -> AnimationCell<Self>;
18    /// Create a [`Morph`] anim from src.
19    fn morph_from(&mut self, src: Self) -> AnimationCell<Self>;
20    /// Create a [`Morph`] anim to dst.
21    fn morph_to(&mut self, dst: Self) -> AnimationCell<Self>;
22}
23// ANCHOR_END: MorphAnim
24
25// ANCHOR: MorphAnim-Impl
26impl<T: MorphRequirement + 'static> MorphAnim for T {
27    fn morph<F: Fn(&mut T)>(&mut self, f: F) -> AnimationCell<T> {
28        let mut dst = self.clone();
29        (f)(&mut dst);
30        Morph::new(self.clone(), dst)
31            .into_animation_cell()
32            .with_rate_func(smooth)
33            .apply_to(self)
34    }
35    fn morph_from(&mut self, s: T) -> AnimationCell<T> {
36        Morph::new(s, self.clone())
37            .into_animation_cell()
38            .with_rate_func(smooth)
39            .apply_to(self)
40    }
41    fn morph_to(&mut self, d: T) -> AnimationCell<T> {
42        Morph::new(self.clone(), d)
43            .into_animation_cell()
44            .with_rate_func(smooth)
45            .apply_to(self)
46    }
47}
48// ANCHOR_END: MorphAnim-Impl
49
50// ANCHOR: Morph
51/// Morph Anim
52pub struct Morph<T: MorphRequirement> {
53    src: T,
54    dst: T,
55    aligned_src: T,
56    aligned_dst: T,
57}
58// ANCHOR_END: Morph
59
60impl<T: MorphRequirement> Morph<T> {
61    /// Constructor
62    pub fn new(src: T, dst: T) -> Self {
63        let mut aligned_src = src.clone();
64        let mut aligned_dst = dst.clone();
65        if !aligned_src.is_aligned(&aligned_dst) {
66            aligned_src.align_with(&mut aligned_dst);
67        }
68        Self {
69            src,
70            dst,
71            aligned_src,
72            aligned_dst,
73        }
74    }
75}
76
77// ANCHOR: Morph-Eval
78impl<T: MorphRequirement> Eval<T> for Morph<T> {
79    fn eval_alpha(&self, alpha: f64) -> T {
80        if alpha == 0.0 {
81            self.src.clone()
82        } else if 0.0 < alpha && alpha < 1.0 {
83            self.aligned_src.lerp(&self.aligned_dst, alpha)
84        } else if alpha == 1.0 {
85            self.dst.clone()
86        } else {
87            unreachable!()
88        }
89    }
90}
91// ANCHOR_END: Morph-Eval