use ranim_core::{
animation::{AnimationCell, Eval},
glam::DVec3,
traits::{Aabb, AabbPoint, Locate, RotateTransform, ShiftTransformExt},
utils::rate_functions::smooth,
};
pub trait RotatingRequirement: RotateTransform + ShiftTransformExt + Clone {}
impl<T: RotateTransform + ShiftTransformExt + Clone> RotatingRequirement for T {}
pub trait RotatingAnim: RotatingRequirement + Sized + 'static {
fn rotating(&mut self, angle: f64, axis: DVec3) -> AnimationCell<Self>
where
Self: Aabb,
{
self.rotating_at(angle, axis, AabbPoint::CENTER)
}
fn rotating_at<A: Locate<Self>>(
&mut self,
angle: f64,
axis: DVec3,
anchor: A,
) -> AnimationCell<Self> {
RotatingAnimation::new(self.clone(), angle, axis, anchor.locate(self))
.into_animation_cell()
.with_rate_func(smooth)
.apply_to(self)
}
}
impl<T: RotatingRequirement + 'static> RotatingAnim for T {}
pub struct RotatingAnimation<T: RotatingRequirement> {
src: T,
angle: f64,
axis: DVec3,
point: DVec3,
}
impl<T: RotatingRequirement> RotatingAnimation<T> {
pub fn new(src: T, angle: f64, axis: DVec3, point: DVec3) -> Self {
Self {
src,
angle,
axis,
point,
}
}
}
impl<T: RotatingRequirement> Eval<T> for RotatingAnimation<T> {
fn eval_alpha(&self, alpha: f64) -> T {
let mut result = self.src.clone();
result.with_origin(self.point, |x| {
x.rotate_on_axis(self.axis, self.angle * alpha);
});
result
}
}