1use crate::layer::Layer;
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(
192 &mut self,
193 from_value: f32,
194 to_value: f32,
195 time: f32,
196 easing: EasingFunction,
197 ) {
198 self.opacity_running = true;
199 self.opacity_ease = easing;
200 self.opacity_from_value = from_value;
201 self.opacity_to_value = to_value;
202 self.opacity_time_duration = time * 1000.0; }
204
205 pub fn with_key_path(_key_path: &str) -> Animation {
211 let mut animation = Animation::new();
212 animation.duration = 1.0;
214 animation.timing_function = Some(EasingFunction::Linear);
215 animation
216 }
217
218 pub fn set_from_value_position_x(&mut self, value: i32) {
220 self.translation_x_from_value = value;
221 }
222
223 pub fn set_to_value_position_x(&mut self, value: i32) {
225 self.translation_x_to_value = value;
226 self.translation_x_running = true;
227 if let Some(timing) = self.timing_function {
228 self.translation_x_ease = timing;
229 }
230 self.translation_x_time_duration = self.duration * 1000.0;
231 }
232
233 pub fn set_from_value_position_y(&mut self, value: i32) {
235 self.translation_y_from_value = value;
236 }
237
238 pub fn set_to_value_position_y(&mut self, value: i32) {
240 self.translation_y_to_value = value;
241 self.translation_y_running = true;
242 if let Some(timing) = self.timing_function {
243 self.translation_y_ease = timing;
244 }
245 self.translation_y_time_duration = self.duration * 1000.0;
246 }
247
248 pub fn set_from_value_opacity(&mut self, value: f32) {
250 self.opacity_from_value = value;
251 }
252
253 pub fn set_to_value_opacity(&mut self, value: f32) {
255 self.opacity_to_value = value;
256 self.opacity_running = true;
257 if let Some(timing) = self.timing_function {
258 self.opacity_ease = timing;
259 }
260 self.opacity_time_duration = self.duration * 1000.0;
261 }
262
263 pub fn set_from_value_scale(&mut self, value: f32) {
265 self.scale_from_value = value;
266 }
267
268 pub fn set_to_value_scale(&mut self, value: f32) {
270 self.scale_to_value = value;
271 self.scale_running = true;
272 if let Some(timing) = self.timing_function {
273 self.scale_ease = timing;
274 }
275 self.scale_time_duration = self.duration * 1000.0;
276 }
277
278 pub fn set_from_value_rotation(&mut self, value: i32) {
280 self.rotation_from_value = value;
281 }
282
283 pub fn set_to_value_rotation(&mut self, value: i32) {
285 self.rotation_to_value = value;
286 self.rotation_running = true;
287 if let Some(timing) = self.timing_function {
288 self.rotation_ease = timing;
289 }
290 self.rotation_time_duration = self.duration * 1000.0;
291 }
292
293 pub fn run(&mut self, layer: &mut Layer) {
294 if self.translation_x_running {
295 if self.translation_x_starting_time == 0 {
296 self.translation_x_starting_time = self.animation_time_instance.elapsed().as_millis();
297 }
298 let cur_time = (self.animation_time_instance.elapsed().as_millis()
299 - self.translation_x_starting_time) as f32
300 / self.translation_x_time_duration;
301 if cur_time <= 1.0 {
302 layer.x = Animation::easing_function(
303 self.translation_x_ease,
304 self.translation_x_from_value as f32,
305 self.translation_x_to_value as f32,
306 cur_time,
307 ) as i32;
308 } else {
309 self.translation_x_running = false;
310 self.translation_x_starting_time = 0;
311 layer.x = self.translation_x_to_value;
312 }
313 }
314
315 if self.translation_y_running {
316 if self.translation_y_starting_time == 0 {
317 self.translation_y_starting_time = self.animation_time_instance.elapsed().as_millis();
318 }
319 let cur_time = (self.animation_time_instance.elapsed().as_millis()
320 - self.translation_y_starting_time) as f32
321 / self.translation_y_time_duration;
322 if cur_time <= 1.0 {
323 layer.y = Animation::easing_function(
324 self.translation_y_ease,
325 self.translation_y_from_value as f32,
326 self.translation_y_to_value as f32,
327 cur_time,
328 ) as i32;
329 } else {
330 self.translation_y_running = false;
331 self.translation_y_starting_time = 0;
332 layer.y = self.translation_y_to_value;
333 }
334 }
335
336 if self.rotation_running {
337 if self.rotation_starting_time == 0 {
338 self.rotation_starting_time = self.animation_time_instance.elapsed().as_millis();
339 }
340
341 let cur_time = (self.animation_time_instance.elapsed().as_millis()
342 - self.rotation_starting_time) as f32
343 / self.rotation_time_duration as f32;
344 if cur_time <= 1.0 {
345 layer.rotation = Animation::easing_function(
346 self.rotation_ease,
347 self.rotation_from_value as f32,
348 self.rotation_to_value as f32,
349 cur_time,
350 ) as i32;
351 } else {
352 self.rotation_running = false;
353 self.rotation_starting_time = 0;
354 layer.rotation = self.rotation_to_value;
355 }
356 }
357
358 if self.scale_running {
359 if self.scale_starting_time == 0 {
360 self.scale_starting_time = self.animation_time_instance.elapsed().as_millis();
361 }
362
363 let cur_time = (self.animation_time_instance.elapsed().as_millis() - self.scale_starting_time)
364 as f32
365 / self.scale_time_duration as f32;
366 if cur_time <= 1.0 {
367 layer.scale_x = Animation::easing_function(
368 self.scale_ease,
369 self.scale_from_value,
370 self.scale_to_value,
371 cur_time,
372 ) as f32;
373 layer.scale_y = Animation::easing_function(
374 self.scale_ease,
375 self.scale_from_value,
376 self.scale_to_value,
377 cur_time,
378 ) as f32;
379 } else {
380 self.scale_running = false;
381 self.scale_starting_time = 0;
382 layer.scale_x = self.scale_to_value;
383 layer.scale_y = self.scale_to_value;
384 }
385 }
386
387 if self.opacity_running {
388 if self.opacity_starting_time == 0 {
389 self.opacity_starting_time = self.animation_time_instance.elapsed().as_millis();
390 }
391
392 let cur_time = (self.animation_time_instance.elapsed().as_millis()
393 - self.opacity_starting_time) as f32
394 / self.opacity_time_duration as f32;
395 if cur_time <= 1.0 {
396 layer.opacity = Animation::easing_function(
397 self.opacity_ease,
398 self.opacity_from_value,
399 self.opacity_to_value,
400 cur_time,
401 );
402 } else {
403 self.opacity_running = false;
404 self.opacity_starting_time = 0;
405 layer.opacity = self.opacity_to_value;
406 }
407 }
408
409 if self.translation_x_running
410 || self.translation_y_running
411 || self.rotation_running
412 || self.scale_running
413 || self.opacity_running
414 {
415 layer.animated = true;
416 } else {
417 layer.animated = false;
418 }
419 }
420}
421
422#[cfg(test)]
423mod tests {
424 use super::*;
425
426 #[test]
427 fn test_animation_with_key_path() {
428 let animation = Animation::with_key_path("position.x");
429 assert_eq!(animation.duration, 1.0);
430 assert!(animation.timing_function.is_some());
431 }
432
433 #[test]
434 fn test_animation_coreanimation_properties() {
435 let mut animation = Animation::with_key_path("position.x");
436 animation.duration = 3.5;
437 animation.timing_function = Some(EasingFunction::EaseInOut);
438 animation.repeat_count = 2.0;
439 animation.autoreverses = true;
440
441 assert_eq!(animation.duration, 3.5);
442 assert_eq!(animation.repeat_count, 2.0);
443 assert!(animation.autoreverses);
444 }
445
446 #[test]
447 fn test_position_animation_setters() {
448 let mut animation = Animation::with_key_path("position.x");
449 animation.duration = 2.0;
450 animation.timing_function = Some(EasingFunction::Linear);
451
452 animation.set_from_value_position_x(100);
453 animation.set_to_value_position_x(400);
454
455 assert_eq!(animation.translation_x_from_value, 100);
456 assert_eq!(animation.translation_x_to_value, 400);
457 assert!(animation.translation_x_running);
458 }
459
460 #[test]
461 fn test_opacity_animation_setters() {
462 let mut animation = Animation::with_key_path("opacity");
463 animation.duration = 1.5;
464
465 animation.set_from_value_opacity(1.0);
466 animation.set_to_value_opacity(0.5);
467
468 assert_eq!(animation.opacity_from_value, 1.0);
469 assert_eq!(animation.opacity_to_value, 0.5);
470 assert!(animation.opacity_running);
471 }
472
473 #[test]
474 fn test_scale_animation_setters() {
475 let mut animation = Animation::with_key_path("transform.scale");
476 animation.duration = 2.5;
477
478 animation.set_from_value_scale(1.0);
479 animation.set_to_value_scale(2.0);
480
481 assert_eq!(animation.scale_from_value, 1.0);
482 assert_eq!(animation.scale_to_value, 2.0);
483 assert!(animation.scale_running);
484 }
485
486 #[test]
487 fn test_rotation_animation_setters() {
488 let mut animation = Animation::with_key_path("transform.rotation");
489 animation.duration = 3.0;
490
491 animation.set_from_value_rotation(0);
492 animation.set_to_value_rotation(360);
493
494 assert_eq!(animation.rotation_from_value, 0);
495 assert_eq!(animation.rotation_to_value, 360);
496 assert!(animation.rotation_running);
497 }
498
499 #[test]
500 fn test_backward_compatibility_animation() {
501 let mut animation = Animation::new();
502 animation.apply_translation_x(0, 100, 1.0, EasingFunction::Linear);
503 animation.apply_translation_y(0, 200, 1.0, EasingFunction::EaseIn);
504 animation.apply_scale(1.0, 2.0, 1.0, EasingFunction::EaseOut);
505 animation.apply_rotation(0, 180, 1.0, EasingFunction::EaseInOut);
506
507 assert!(animation.translation_x_running);
508 assert!(animation.translation_y_running);
509 assert!(animation.scale_running);
510 assert!(animation.rotation_running);
511 }
512}