1use ranim_core::{
2 animation::{AnimationCell, Eval},
3 traits::{Alignable, Interpolatable},
4 utils::rate_functions::smooth,
5};
6
7pub trait MorphRequirement: Alignable + Interpolatable + Clone {}
10impl<T: Alignable + Interpolatable + Clone> MorphRequirement for T {}
11pub trait MorphAnim: MorphRequirement + Sized + 'static {
16 fn morph<F: Fn(&mut Self)>(&mut self, f: F) -> AnimationCell<Self>;
18 fn morph_from(&mut self, src: Self) -> AnimationCell<Self>;
20 fn morph_to(&mut self, dst: Self) -> AnimationCell<Self>;
22}
23impl<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}
48pub struct Morph<T: MorphRequirement> {
53 src: T,
54 dst: T,
55 aligned_src: T,
56 aligned_dst: T,
57}
58impl<T: MorphRequirement> Morph<T> {
61 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
77impl<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