1use ranim_core::{
2 animation::{AnimationCell, Eval},
3 glam::DVec3,
4 traits::{Aabb, AabbPoint, Locate, RotateTransform, ShiftTransformExt},
5 utils::rate_functions::smooth,
6};
7
8pub trait RotatingRequirement: RotateTransform + ShiftTransformExt + Clone {}
11impl<T: RotateTransform + ShiftTransformExt + Clone> RotatingRequirement for T {}
12
13pub trait RotatingAnim: RotatingRequirement + Sized + 'static {
16 fn rotating(&mut self, angle: f64, axis: DVec3) -> AnimationCell<Self>
18 where
19 Self: Aabb,
20 {
21 self.rotating_at(angle, axis, AabbPoint::CENTER)
22 }
23
24 fn rotating_at<A: Locate<Self>>(
26 &mut self,
27 angle: f64,
28 axis: DVec3,
29 anchor: A,
30 ) -> AnimationCell<Self> {
31 RotatingAnimation::new(self.clone(), angle, axis, anchor.locate(self))
32 .into_animation_cell()
33 .with_rate_func(smooth)
34 .apply_to(self)
35 }
36}
37
38impl<T: RotatingRequirement + 'static> RotatingAnim for T {}
39
40pub struct RotatingAnimation<T: RotatingRequirement> {
48 src: T,
49 angle: f64,
50 axis: DVec3,
51 point: DVec3,
52}
53
54impl<T: RotatingRequirement> RotatingAnimation<T> {
55 pub fn new(src: T, angle: f64, axis: DVec3, point: DVec3) -> Self {
57 Self {
58 src,
59 angle,
60 axis,
61 point,
62 }
63 }
64}
65
66impl<T: RotatingRequirement> Eval<T> for RotatingAnimation<T> {
67 fn eval_alpha(&self, alpha: f64) -> T {
68 let mut result = self.src.clone();
69 result.with_origin(self.point, |x| {
70 x.rotate_on_axis(self.axis, self.angle * alpha);
71 });
72 result
73 }
74}