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