1use crate::layer::RALayer;
2use keyframe::{ease, functions::*};
3use std::time::Instant;
4
5#[derive(Copy, Clone, Debug)]
6pub enum EasingFunction {
7 EaseIn,
8 EaseInCubic,
9 EaseInOut,
10 EaseInOutCubic,
11 EaseInOutQuad,
12 EaseInOutQuart,
13 EaseInOutQuint,
14 EaseInQuad,
15 EaseInQuart,
16 EaseInQuint,
17 EaseOut,
18 EaseOutCubic,
19 EaseOutQuad,
20 EaseOutQuart,
21 EaseOutQuint,
22 Linear,
23 Step,
24}
25
26pub type CAMediaTimingFunction = EasingFunction;
28
29pub struct Animation {
30 animation_time_instance: Instant,
31 translation_x_running: bool,
32 translation_x_starting_time: u128,
33 translation_x_time_duration: f32,
34 translation_x_from_value: i32,
35 translation_x_to_value: i32,
36 translation_x_ease: EasingFunction,
37
38 translation_y_running: bool,
39 translation_y_starting_time: u128,
40 translation_y_time_duration: f32,
41 translation_y_from_value: i32,
42 translation_y_to_value: i32,
43 translation_y_ease: EasingFunction,
44
45 scale_running: bool,
46 scale_starting_time: u128,
47 scale_time_duration: f32,
48 scale_from_value: f32,
49 scale_to_value: f32,
50 scale_ease: EasingFunction,
51
52 rotation_running: bool,
53 rotation_starting_time: u128,
54 rotation_time_duration: f32,
55 rotation_from_value: i32,
56 rotation_to_value: i32,
57 rotation_ease: EasingFunction,
58
59 opacity_running: bool,
60 opacity_starting_time: u128,
61 opacity_time_duration: f32,
62 opacity_from_value: f32,
63 opacity_to_value: f32,
64 opacity_ease: EasingFunction,
65
66 pub duration: f32,
68 pub timing_function: Option<EasingFunction>,
69 pub repeat_count: f32,
70 pub autoreverses: bool,
71}
72
73impl Animation {
74 pub fn new() -> Animation {
75 Animation {
76 animation_time_instance: Instant::now(),
77 translation_x_running: false,
78 translation_x_starting_time: 0,
79 translation_x_time_duration: 0.0,
80 translation_x_from_value: 0,
81 translation_x_to_value: 0,
82 translation_x_ease: EasingFunction::Linear,
83
84 translation_y_running: false,
85 translation_y_starting_time: 0,
86 translation_y_time_duration: 0.0,
87 translation_y_from_value: 0,
88 translation_y_to_value: 0,
89 translation_y_ease: EasingFunction::Linear,
90
91 scale_running: false,
92 scale_starting_time: 0,
93 scale_time_duration: 0.0,
94 scale_from_value: 0.0,
95 scale_to_value: 0.0,
96 scale_ease: EasingFunction::Linear,
97
98 rotation_running: false,
99 rotation_starting_time: 0,
100 rotation_time_duration: 0.0,
101 rotation_from_value: 0,
102 rotation_to_value: 0,
103 rotation_ease: EasingFunction::Linear,
104
105 opacity_running: false,
106 opacity_starting_time: 0,
107 opacity_time_duration: 0.0,
108 opacity_from_value: 0.0,
109 opacity_to_value: 0.0,
110 opacity_ease: EasingFunction::Linear,
111
112 duration: 0.0,
113 timing_function: None,
114 repeat_count: 0.0,
115 autoreverses: false,
116 }
117 }
118
119 fn easing_function(easing: EasingFunction, from: f32, to: f32, duration: f32) -> f32 {
120 match easing {
121 EasingFunction::EaseIn => ease(EaseIn, from, to, duration),
122 EasingFunction::EaseInCubic => ease(EaseInCubic, from, to, duration),
123 EasingFunction::EaseInOut => ease(EaseInOut, from, to, duration),
124 EasingFunction::EaseInOutCubic => ease(EaseInOutCubic, from, to, duration),
125 EasingFunction::EaseInOutQuad => ease(EaseInOutQuad, from, to, duration),
126 EasingFunction::EaseInOutQuart => ease(EaseInOutQuart, from, to, duration),
127 EasingFunction::EaseInOutQuint => ease(EaseInOutQuint, from, to, duration),
128 EasingFunction::EaseInQuad => ease(EaseInQuad, from, to, duration),
129 EasingFunction::EaseInQuart => ease(EaseInQuart, from, to, duration),
130 EasingFunction::EaseInQuint => ease(EaseInQuint, from, to, duration),
131 EasingFunction::EaseOut => ease(EaseOut, from, to, duration),
132 EasingFunction::EaseOutCubic => ease(EaseOutCubic, from, to, duration),
133 EasingFunction::EaseOutQuad => ease(EaseOutQuad, from, to, duration),
134 EasingFunction::EaseOutQuart => ease(EaseOutQuart, from, to, duration),
135 EasingFunction::EaseOutQuint => ease(EaseOutQuint, from, to, duration),
136 EasingFunction::Linear => ease(Linear, from, to, duration),
137 EasingFunction::Step => ease(Step, from, to, duration),
138 }
139 }
140
141 pub fn apply_translation_x(
142 &mut self,
143 from_value: i32,
144 to_value: i32,
145 time: f32,
146 easing: EasingFunction,
147 ) {
148 self.translation_x_running = true;
149 self.translation_x_ease = easing;
150 self.translation_x_from_value = from_value;
151 self.translation_x_to_value = to_value;
152 self.translation_x_time_duration = time * 1000.0; }
154
155 pub fn apply_translation_y(
156 &mut self,
157 from_value: i32,
158 to_value: i32,
159 time: f32,
160 easing: EasingFunction,
161 ) {
162 self.translation_y_running = true;
163 self.translation_y_ease = easing;
164 self.translation_y_from_value = from_value;
165 self.translation_y_to_value = to_value;
166 self.translation_y_time_duration = time * 1000.0; }
168
169 pub fn apply_rotation(
170 &mut self,
171 from_value: i32,
172 to_value: i32,
173 time: f32,
174 easing: EasingFunction,
175 ) {
176 self.rotation_running = true;
177 self.rotation_ease = easing;
178 self.rotation_from_value = from_value;
179 self.rotation_to_value = to_value;
180 self.rotation_time_duration = time * 1000.0; }
182
183 pub fn apply_scale(&mut self, from_value: f32, to_value: f32, time: f32, easing: EasingFunction) {
184 self.scale_running = true;
185 self.scale_ease = easing;
186 self.scale_from_value = from_value;
187 self.scale_to_value = to_value;
188 self.scale_time_duration = time * 1000.0; }
190
191 pub fn apply_opacity(&mut self, from_value: f32, to_value: f32, time: f32, easing: EasingFunction) {
192 self.opacity_running = true;
193 self.opacity_ease = easing;
194 self.opacity_from_value = from_value;
195 self.opacity_to_value = to_value;
196 self.opacity_time_duration = time * 1000.0; }
198
199 pub fn with_key_path(_key_path: &str) -> Animation {
205 let mut animation = Animation::new();
206 animation.duration = 1.0;
208 animation.timing_function = Some(EasingFunction::Linear);
209 animation
210 }
211
212 pub fn set_from_value_position_x(&mut self, value: i32) {
214 self.translation_x_from_value = value;
215 }
216
217 pub fn set_to_value_position_x(&mut self, value: i32) {
219 self.translation_x_to_value = value;
220 self.translation_x_running = true;
221 if let Some(timing) = self.timing_function {
222 self.translation_x_ease = timing;
223 }
224 self.translation_x_time_duration = self.duration * 1000.0;
225 }
226
227 pub fn set_from_value_position_y(&mut self, value: i32) {
229 self.translation_y_from_value = value;
230 }
231
232 pub fn set_to_value_position_y(&mut self, value: i32) {
234 self.translation_y_to_value = value;
235 self.translation_y_running = true;
236 if let Some(timing) = self.timing_function {
237 self.translation_y_ease = timing;
238 }
239 self.translation_y_time_duration = self.duration * 1000.0;
240 }
241
242 pub fn set_from_value_opacity(&mut self, value: f32) {
244 self.opacity_from_value = value;
245 }
246
247 pub fn set_to_value_opacity(&mut self, value: f32) {
249 self.opacity_to_value = value;
250 self.opacity_running = true;
251 if let Some(timing) = self.timing_function {
252 self.opacity_ease = timing;
253 }
254 self.opacity_time_duration = self.duration * 1000.0;
255 }
256
257 pub fn set_from_value_scale(&mut self, value: f32) {
259 self.scale_from_value = value;
260 }
261
262 pub fn set_to_value_scale(&mut self, value: f32) {
264 self.scale_to_value = value;
265 self.scale_running = true;
266 if let Some(timing) = self.timing_function {
267 self.scale_ease = timing;
268 }
269 self.scale_time_duration = self.duration * 1000.0;
270 }
271
272 pub fn set_from_value_rotation(&mut self, value: i32) {
274 self.rotation_from_value = value;
275 }
276
277 pub fn set_to_value_rotation(&mut self, value: i32) {
279 self.rotation_to_value = value;
280 self.rotation_running = true;
281 if let Some(timing) = self.timing_function {
282 self.rotation_ease = timing;
283 }
284 self.rotation_time_duration = self.duration * 1000.0;
285 }
286
287 pub fn run(&mut self, layer: &mut RALayer) {
288 if self.translation_x_running {
289 if self.translation_x_starting_time == 0 {
290 self.translation_x_starting_time = self.animation_time_instance.elapsed().as_millis();
291 }
292 let cur_time = (self.animation_time_instance.elapsed().as_millis()
293 - self.translation_x_starting_time) as f32
294 / self.translation_x_time_duration;
295 if cur_time <= 1.0 {
296 layer.x = Animation::easing_function(
297 self.translation_x_ease,
298 self.translation_x_from_value as f32,
299 self.translation_x_to_value as f32,
300 cur_time,
301 ) as i32;
302 } else {
303 self.translation_x_running = false;
304 self.translation_x_starting_time = 0;
305 layer.x = self.translation_x_to_value;
306 }
307 }
308
309 if self.translation_y_running {
310 if self.translation_y_starting_time == 0 {
311 self.translation_y_starting_time = self.animation_time_instance.elapsed().as_millis();
312 }
313 let cur_time = (self.animation_time_instance.elapsed().as_millis()
314 - self.translation_y_starting_time) as f32
315 / self.translation_y_time_duration;
316 if cur_time <= 1.0 {
317 layer.y = Animation::easing_function(
318 self.translation_y_ease,
319 self.translation_y_from_value as f32,
320 self.translation_y_to_value as f32,
321 cur_time,
322 ) as i32;
323 } else {
324 self.translation_y_running = false;
325 self.translation_y_starting_time = 0;
326 layer.y = self.translation_y_to_value;
327 }
328 }
329
330 if self.rotation_running {
331 if self.rotation_starting_time == 0 {
332 self.rotation_starting_time = self.animation_time_instance.elapsed().as_millis();
333 }
334
335 let cur_time = (self.animation_time_instance.elapsed().as_millis()
336 - self.rotation_starting_time) as f32
337 / self.rotation_time_duration as f32;
338 if cur_time <= 1.0 {
339 layer.rotation = Animation::easing_function(
340 self.rotation_ease,
341 self.rotation_from_value as f32,
342 self.rotation_to_value as f32,
343 cur_time,
344 ) as i32;
345 } else {
346 self.rotation_running = false;
347 self.rotation_starting_time = 0;
348 layer.rotation = self.rotation_to_value;
349 }
350 }
351
352 if self.scale_running {
353 if self.scale_starting_time == 0 {
354 self.scale_starting_time = self.animation_time_instance.elapsed().as_millis();
355 }
356
357 let cur_time = (self.animation_time_instance.elapsed().as_millis() - self.scale_starting_time)
358 as f32
359 / self.scale_time_duration as f32;
360 if cur_time <= 1.0 {
361 layer.scale_x = Animation::easing_function(
362 self.scale_ease,
363 self.scale_from_value,
364 self.scale_to_value,
365 cur_time,
366 ) as f32;
367 layer.scale_y = Animation::easing_function(
368 self.scale_ease,
369 self.scale_from_value,
370 self.scale_to_value,
371 cur_time,
372 ) as f32;
373 } else {
374 self.scale_running = false;
375 self.scale_starting_time = 0;
376 layer.scale_x = self.scale_to_value;
377 layer.scale_y = self.scale_to_value;
378 }
379 }
380
381 if self.opacity_running {
382 if self.opacity_starting_time == 0 {
383 self.opacity_starting_time = self.animation_time_instance.elapsed().as_millis();
384 }
385
386 let cur_time = (self.animation_time_instance.elapsed().as_millis() - self.opacity_starting_time)
387 as f32
388 / self.opacity_time_duration as f32;
389 if cur_time <= 1.0 {
390 layer.opacity = Animation::easing_function(
391 self.opacity_ease,
392 self.opacity_from_value,
393 self.opacity_to_value,
394 cur_time,
395 );
396 } else {
397 self.opacity_running = false;
398 self.opacity_starting_time = 0;
399 layer.opacity = self.opacity_to_value;
400 }
401 }
402
403 if self.translation_x_running
404 || self.translation_y_running
405 || self.rotation_running
406 || self.scale_running
407 || self.opacity_running
408 {
409 layer.animated = true;
410 } else {
411 layer.animated = false;
412 }
413 }
414}
415
416#[cfg(test)]
417mod tests {
418 use super::*;
419
420 #[test]
421 fn test_animation_with_key_path() {
422 let animation = Animation::with_key_path("position.x");
423 assert_eq!(animation.duration, 1.0);
424 assert!(animation.timing_function.is_some());
425 }
426
427 #[test]
428 fn test_animation_coreanimation_properties() {
429 let mut animation = Animation::with_key_path("position.x");
430 animation.duration = 3.5;
431 animation.timing_function = Some(EasingFunction::EaseInOut);
432 animation.repeat_count = 2.0;
433 animation.autoreverses = true;
434
435 assert_eq!(animation.duration, 3.5);
436 assert_eq!(animation.repeat_count, 2.0);
437 assert!(animation.autoreverses);
438 }
439
440 #[test]
441 fn test_position_animation_setters() {
442 let mut animation = Animation::with_key_path("position.x");
443 animation.duration = 2.0;
444 animation.timing_function = Some(EasingFunction::Linear);
445
446 animation.set_from_value_position_x(100);
447 animation.set_to_value_position_x(400);
448
449 assert_eq!(animation.translation_x_from_value, 100);
450 assert_eq!(animation.translation_x_to_value, 400);
451 assert!(animation.translation_x_running);
452 }
453
454 #[test]
455 fn test_opacity_animation_setters() {
456 let mut animation = Animation::with_key_path("opacity");
457 animation.duration = 1.5;
458
459 animation.set_from_value_opacity(1.0);
460 animation.set_to_value_opacity(0.5);
461
462 assert_eq!(animation.opacity_from_value, 1.0);
463 assert_eq!(animation.opacity_to_value, 0.5);
464 assert!(animation.opacity_running);
465 }
466
467 #[test]
468 fn test_scale_animation_setters() {
469 let mut animation = Animation::with_key_path("transform.scale");
470 animation.duration = 2.5;
471
472 animation.set_from_value_scale(1.0);
473 animation.set_to_value_scale(2.0);
474
475 assert_eq!(animation.scale_from_value, 1.0);
476 assert_eq!(animation.scale_to_value, 2.0);
477 assert!(animation.scale_running);
478 }
479
480 #[test]
481 fn test_rotation_animation_setters() {
482 let mut animation = Animation::with_key_path("transform.rotation");
483 animation.duration = 3.0;
484
485 animation.set_from_value_rotation(0);
486 animation.set_to_value_rotation(360);
487
488 assert_eq!(animation.rotation_from_value, 0);
489 assert_eq!(animation.rotation_to_value, 360);
490 assert!(animation.rotation_running);
491 }
492
493 #[test]
494 fn test_backward_compatibility_animation() {
495 let mut animation = Animation::new();
496 animation.apply_translation_x(0, 100, 1.0, EasingFunction::Linear);
497 animation.apply_translation_y(0, 200, 1.0, EasingFunction::EaseIn);
498 animation.apply_scale(1.0, 2.0, 1.0, EasingFunction::EaseOut);
499 animation.apply_rotation(0, 180, 1.0, EasingFunction::EaseInOut);
500
501 assert!(animation.translation_x_running);
502 assert!(animation.translation_y_running);
503 assert!(animation.scale_running);
504 assert!(animation.rotation_running);
505 }
506}