mraphics_core/animation/predefined/
basic.rs

1use crate::{Action, Animation, RenderInstance, Renderable};
2use nalgebra::{UnitQuaternion, UnitVector3, Vector3};
3use std::{cell::RefCell, rc::Rc};
4
5pub struct MeshAnimation {
6    pub mesh_id: usize,
7    pub on_update: Box<dyn FnMut(&mut RenderInstance, f32, f32)>,
8    pub on_start: Box<dyn FnMut()>,
9    pub on_stop: Box<dyn FnMut()>,
10}
11
12impl MeshAnimation {
13    pub fn new<R: Renderable>(mesh: &R) -> Self {
14        Self {
15            mesh_id: mesh.identifier(),
16            on_update: Box::new(|_, _, _| {}),
17            on_start: Box::new(|| {}),
18            on_stop: Box::new(|| {}),
19        }
20    }
21
22    pub fn with_on_update<F: FnMut(&mut RenderInstance, f32, f32) + 'static>(
23        mut self,
24        closure: F,
25    ) -> Self {
26        self.on_update = Box::new(closure);
27        self
28    }
29
30    pub fn with_on_start<F: FnMut() + 'static>(mut self, closure: F) -> Self {
31        self.on_start = Box::new(closure);
32        self
33    }
34
35    pub fn with_on_stop<F: FnMut() + 'static>(mut self, closure: F) -> Self {
36        self.on_stop = Box::new(closure);
37        self
38    }
39}
40
41impl Animation for MeshAnimation {
42    fn into_action(mut self, scene: std::rc::Rc<std::cell::RefCell<crate::Scene>>) -> Action {
43        let mut out = Action::new();
44
45        out.on_start = self.on_start;
46        out.on_stop = self.on_stop;
47
48        out.on_update = Box::new(move |progress, elapsed_time| {
49            (self.on_update)(
50                scene
51                    .borrow_mut()
52                    .acquire_instance_mut_unchecked(self.mesh_id),
53                progress,
54                elapsed_time,
55            )
56        });
57
58        out
59    }
60}
61
62pub struct RotateAxisAngle {
63    pub mesh_index: usize,
64    pub axis: UnitVector3<f32>,
65    pub angle_rad: f32,
66}
67
68impl RotateAxisAngle {
69    pub fn new<R: Renderable>(mesh: &R, axis: UnitVector3<f32>, angle_rad: f32) -> Self {
70        Self {
71            mesh_index: mesh.identifier(),
72            axis,
73            angle_rad,
74        }
75    }
76
77    pub fn new_normalize<R: Renderable>(mesh: &R, axis: Vector3<f32>, angle_rad: f32) -> Self {
78        Self {
79            mesh_index: mesh.identifier(),
80            axis: UnitVector3::new_normalize(axis),
81            angle_rad,
82        }
83    }
84}
85
86impl Animation for RotateAxisAngle {
87    fn into_action(self, scene: std::rc::Rc<std::cell::RefCell<crate::Scene>>) -> Action {
88        let mut out = Action::new();
89        let start_rotation = Rc::new(RefCell::new(UnitQuaternion::identity()));
90
91        let scene_clone = scene.clone();
92        let start_rotation_clone = start_rotation.clone();
93
94        out.on_start = Box::new(move || {
95            start_rotation_clone.borrow_mut().clone_from(
96                scene_clone
97                    .borrow()
98                    .acquire_instance_unchecked(self.mesh_index)
99                    .rotation(),
100            );
101        });
102        out.on_update = Box::new(move |p, _| {
103            scene
104                .borrow_mut()
105                .acquire_instance_mut_unchecked(self.mesh_index)
106                .set_rotation(
107                    &(UnitQuaternion::from_axis_angle(&self.axis, self.angle_rad * p)
108                        * &*start_rotation.borrow()),
109                );
110        });
111
112        out
113    }
114}