1use crate::{
2 Action, Animation, MeshHandle, MeshLike, MeshPool, MraphicsID, RenderInstance, Scene,
3 anim_curve::{AnimCurve, EaseInOutCubic},
4};
5use nalgebra::{UnitQuaternion, UnitVector3, Vector3};
6use std::{cell::RefCell, marker::PhantomData, rc::Rc};
7
8pub struct MeshAnimation<'res, M, Update, Start, Stop, C>
9where
10 M: MeshLike + 'static,
11 Update: FnMut(&mut M, &mut RenderInstance, f32, f32) + 'res,
12 Start: FnMut() + 'res,
13 Stop: FnMut() + 'res,
14 C: AnimCurve + 'static,
15{
16 pub mesh_id: MraphicsID,
17 pub on_update: Update,
18 pub on_start: Start,
19 pub on_stop: Stop,
20 pub curve: C,
21
22 _marker: PhantomData<&'res M>,
23}
24
25impl<'res, M: MeshLike + 'static>
26 MeshAnimation<'res, M, fn(&mut M, &mut RenderInstance, f32, f32), fn(), fn(), EaseInOutCubic>
27{
28 pub fn new(mesh_handle: &MeshHandle<M>) -> Self {
29 Self {
30 mesh_id: mesh_handle.identifier(),
31 on_update: |_, _, _, _| {},
32 on_start: || {},
33 on_stop: || {},
34 curve: EaseInOutCubic,
35 _marker: PhantomData,
36 }
37 }
38}
39
40impl<'res, M, Update, Start, Stop, C> MeshAnimation<'res, M, Update, Start, Stop, C>
41where
42 M: MeshLike + 'static,
43 Update: FnMut(&mut M, &mut RenderInstance, f32, f32) + 'res,
44 Start: FnMut() + 'res,
45 Stop: FnMut() + 'res,
46 C: AnimCurve + 'static,
47{
48 pub fn with_on_update<F: FnMut(&mut M, &mut RenderInstance, f32, f32) + 'res>(
49 self,
50 closure: F,
51 ) -> MeshAnimation<'res, M, F, Start, Stop, C> {
52 MeshAnimation {
53 mesh_id: self.mesh_id,
54 on_update: closure,
55 on_start: self.on_start,
56 on_stop: self.on_stop,
57 curve: self.curve,
58 _marker: PhantomData,
59 }
60 }
61
62 pub fn with_on_start<F: FnMut() + 'res>(
63 self,
64 closure: F,
65 ) -> MeshAnimation<'res, M, Update, F, Stop, C> {
66 MeshAnimation {
67 mesh_id: self.mesh_id,
68 on_update: self.on_update,
69 on_start: closure,
70 on_stop: self.on_stop,
71 curve: self.curve,
72 _marker: PhantomData,
73 }
74 }
75
76 pub fn with_on_stop<F: FnMut() + 'res>(
77 self,
78 closure: F,
79 ) -> MeshAnimation<'res, M, Update, Start, F, C> {
80 MeshAnimation {
81 mesh_id: self.mesh_id,
82 on_update: self.on_update,
83 on_start: self.on_start,
84 on_stop: closure,
85 curve: self.curve,
86 _marker: PhantomData,
87 }
88 }
89
90 pub fn with_curve<T: AnimCurve + 'static>(
91 self,
92 curve: T,
93 ) -> MeshAnimation<'res, M, Update, Start, Stop, T> {
94 MeshAnimation {
95 mesh_id: self.mesh_id,
96 on_update: self.on_update,
97 on_start: self.on_start,
98 on_stop: self.on_stop,
99 curve,
100 _marker: PhantomData,
101 }
102 }
103}
104
105impl<'res, M, Update, Start, Stop, C> Animation<'res>
106 for MeshAnimation<'res, M, Update, Start, Stop, C>
107where
108 M: MeshLike + 'static,
109 Update: FnMut(&mut M, &mut RenderInstance, f32, f32) + 'res,
110 Start: FnMut() + 'res,
111 Stop: FnMut() + 'res,
112 C: AnimCurve + 'static,
113{
114 fn into_action(
115 mut self,
116 mesh_pool: Rc<RefCell<MeshPool>>,
117 scene: Rc<RefCell<Scene>>,
118 ) -> Action<'res> {
119 let mut out = Action::new();
120
121 out.on_start = Box::new(self.on_start);
122 out.on_stop = Box::new(self.on_stop);
123
124 out.on_update = Box::new(move |progress, elapsed_time| {
125 (self.on_update)(
126 mesh_pool
127 .borrow_mut()
128 .acquire_mesh_mut_unchecked(self.mesh_id),
129 scene
130 .borrow_mut()
131 .acquire_instance_mut_unchecked(self.mesh_id),
132 self.curve.sample(progress),
133 elapsed_time,
134 )
135 });
136
137 out
138 }
139}
140
141pub struct RotateAxisAngle {
143 pub mesh_id: MraphicsID,
145
146 pub axis: UnitVector3<f32>,
148
149 pub angle_rad: f32,
151
152 pub curve: Box<dyn AnimCurve>,
153}
154
155impl RotateAxisAngle {
156 pub fn new<M: MeshLike + 'static>(
157 mesh_handle: &MeshHandle<M>,
158 axis: UnitVector3<f32>,
159 angle_rad: f32,
160 ) -> Self {
161 Self {
162 mesh_id: mesh_handle.identifier(),
163 axis,
164 angle_rad,
165 curve: Box::new(EaseInOutCubic),
166 }
167 }
168
169 pub fn new_normalize<M: MeshLike + 'static>(
170 mesh_handle: &MeshHandle<M>,
171 axis: Vector3<f32>,
172 angle_rad: f32,
173 ) -> Self {
174 Self {
175 mesh_id: mesh_handle.identifier(),
176 axis: UnitVector3::new_normalize(axis),
177 angle_rad,
178 curve: Box::new(EaseInOutCubic),
179 }
180 }
181
182 pub fn with_curve<Curve: AnimCurve + 'static>(mut self, curve: Curve) -> Self {
183 self.curve = Box::new(curve);
184 self
185 }
186}
187
188impl Animation<'static> for RotateAxisAngle {
189 fn into_action(
190 self,
191 _mesh_pool: Rc<RefCell<MeshPool>>,
192 scene: Rc<RefCell<Scene>>,
193 ) -> Action<'static> {
194 let mut out = Action::new();
195 let start_rotation = Rc::new(RefCell::new(UnitQuaternion::identity()));
196
197 let scene_clone = scene.clone();
198 let start_rotation_clone = start_rotation.clone();
199
200 out.on_start = Box::new(move || {
201 start_rotation_clone.borrow_mut().clone_from(
202 scene_clone
203 .borrow()
204 .acquire_instance_unchecked(self.mesh_id)
205 .rotation(),
206 );
207 });
208 out.on_update = Box::new(move |p, _| {
209 scene
210 .borrow_mut()
211 .acquire_instance_mut_unchecked(self.mesh_id)
212 .set_rotation(
213 &(UnitQuaternion::from_axis_angle(
214 &self.axis,
215 self.angle_rad * self.curve.sample(p),
216 ) * &*start_rotation.borrow()),
217 );
218 });
219
220 out
221 }
222}
223
224pub struct MoveTo {
226 pub mesh_id: MraphicsID,
227 pub target_place: Vector3<f32>,
228
229 pub curve: Box<dyn AnimCurve>,
230}
231
232impl MoveTo {
233 pub fn new<M: MeshLike + 'static>(
234 mesh_handle: &MeshHandle<M>,
235 target_place: Vector3<f32>,
236 ) -> Self {
237 Self {
238 mesh_id: mesh_handle.identifier(),
239 target_place,
240 curve: Box::new(EaseInOutCubic),
241 }
242 }
243
244 pub fn with_curve<Curve: AnimCurve + 'static>(mut self, curve: Curve) -> Self {
245 self.curve = Box::new(curve);
246 self
247 }
248}
249
250impl Animation<'static> for MoveTo {
251 fn into_action(
252 self,
253 _mesh_pool: Rc<RefCell<MeshPool>>,
254 scene: Rc<RefCell<Scene>>,
255 ) -> Action<'static> {
256 let mut out = Action::new();
257 let start_place = Rc::new(RefCell::new(Vector3::default()));
258
259 let scene_clone = scene.clone();
260 let start_place_clone = start_place.clone();
261
262 out.on_start = Box::new(move || {
263 start_place_clone.borrow_mut().clone_from(
264 &scene_clone
265 .borrow()
266 .acquire_instance_unchecked(self.mesh_id)
267 .translation()
268 .vector,
269 );
270 });
271 out.on_update = Box::new(move |p, _| {
272 scene
273 .borrow_mut()
274 .acquire_instance_mut_unchecked(self.mesh_id)
275 .move_to(
276 &(*start_place.borrow()
277 + &((self.target_place - *start_place.borrow()) * self.curve.sample(p))),
278 );
279 });
280
281 out
282 }
283}
284
285pub struct ScaleTo {
286 pub mesh_id: MraphicsID,
287 pub target_scale: Vector3<f32>,
288
289 pub curve: Box<dyn AnimCurve>,
290}
291
292impl ScaleTo {
293 pub fn new<M: MeshLike + 'static>(
294 mesh_handle: MeshHandle<M>,
295 target_scale: Vector3<f32>,
296 ) -> Self {
297 Self {
298 mesh_id: mesh_handle.identifier(),
299 target_scale,
300 curve: Box::new(EaseInOutCubic),
301 }
302 }
303
304 pub fn with_curve<Curve: AnimCurve + 'static>(mut self, curve: Curve) -> Self {
305 self.curve = Box::new(curve);
306 self
307 }
308}
309
310impl Animation<'static> for ScaleTo {
311 fn into_action(
312 self,
313 _mesh_pool: Rc<RefCell<MeshPool>>,
314 scene: Rc<RefCell<Scene>>,
315 ) -> Action<'static> {
316 let mut out = Action::new();
317 let start_scale = Rc::new(RefCell::new(Vector3::default()));
318
319 let scene_clone = scene.clone();
320 let start_scale_clone = start_scale.clone();
321
322 out.on_start = Box::new(move || {
323 start_scale_clone.borrow_mut().clone_from(
324 scene_clone
325 .borrow()
326 .acquire_instance_unchecked(self.mesh_id)
327 .scale(),
328 );
329 });
330 out.on_update = Box::new(move |p, _| {
331 scene
332 .borrow_mut()
333 .acquire_instance_mut_unchecked(self.mesh_id)
334 .scale_to(
335 &(*start_scale.borrow()
336 + &((self.target_scale - *start_scale.borrow()) * self.curve.sample(p))),
337 );
338 });
339
340 out
341 }
342}
343
344pub struct ScaleBy {
345 pub mesh_id: MraphicsID,
346 pub scale_factor: Vector3<f32>,
347
348 pub curve: Box<dyn AnimCurve>,
349}
350
351impl ScaleBy {
352 pub fn new<M: MeshLike + 'static>(
353 mesh_handle: MeshHandle<M>,
354 scale_factor: Vector3<f32>,
355 ) -> Self {
356 Self {
357 mesh_id: mesh_handle.identifier(),
358 scale_factor,
359
360 curve: Box::new(EaseInOutCubic),
361 }
362 }
363
364 pub fn with_curve<Curve: AnimCurve + 'static>(mut self, curve: Curve) -> Self {
365 self.curve = Box::new(curve);
366 self
367 }
368}
369
370impl Animation<'static> for ScaleBy {
371 fn into_action(
372 self,
373 _mesh_pool: Rc<RefCell<MeshPool>>,
374 scene: Rc<RefCell<Scene>>,
375 ) -> Action<'static> {
376 let mut out = Action::new();
377 let start_scale = Rc::new(RefCell::new(Vector3::default()));
378
379 let scene_clone = scene.clone();
380 let start_scale_clone = start_scale.clone();
381
382 out.on_start = Box::new(move || {
383 start_scale_clone.borrow_mut().clone_from(
384 scene_clone
385 .borrow()
386 .acquire_instance_unchecked(self.mesh_id)
387 .scale(),
388 );
389 });
390 out.on_update = Box::new(move |p, _| {
391 scene
392 .borrow_mut()
393 .acquire_instance_mut_unchecked(self.mesh_id)
394 .scale_to(&start_scale.borrow().component_mul(
395 &(Vector3::from_element(1.0)
396 + (self.scale_factor - Vector3::from_element(1.0)) * self.curve.sample(p)),
397 ));
398 });
399
400 out
401 }
402}