Skip to main content

ranim_anims/
morph.rs

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