Skip to main content

egui_map/map/
animation.rs

1use crate::map::{Error, objects::RawPoint};
2use egui::{Color32, Painter, Shape, epaint::CircleShape};
3use std::time::Instant;
4
5pub(crate) struct Animation {}
6
7impl Animation {
8    pub(crate) fn pulse(
9        painter: &Painter,
10        center: RawPoint,
11        zoom: f32,
12        initial_time: Instant,
13        color: Color32,
14    ) -> Result<bool, Error> {
15        let current_instant = Instant::now();
16        let mut result = false;
17        let time_diff = current_instant.duration_since(initial_time);
18        let secs_played = time_diff.as_secs_f32();
19        let radius = (4.00 + (40.00 * secs_played)) * zoom;
20        let mut transparency = 1.00 - (secs_played / 3.50).abs();
21        if transparency < 0.00 {
22            transparency = 0.00;
23        }
24        let corrected_color = Color32::from_rgba_unmultiplied(
25            color.r(),
26            color.g(),
27            color.b(),
28            (255.00 * transparency).round() as u8,
29        );
30        let circle = Shape::Circle(CircleShape::filled(center.into(), radius, corrected_color));
31        painter.extend(vec![circle]);
32        if secs_played < 3.50 {
33            result = true;
34        }
35        Ok(result)
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42    use egui::{Context, LayerId, Pos2, Rect, Vec2};
43    use std::time::Duration;
44
45    fn headless_painter() -> Painter {
46        Painter::new(
47            Context::default(),
48            LayerId::background(),
49            Rect::from_min_size(Pos2::ZERO, Vec2::new(100.0, 100.0)),
50        )
51    }
52
53    #[test]
54    fn pulse_returns_true_while_running() {
55        let painter = headless_painter();
56        let result = Animation::pulse(
57            &painter,
58            RawPoint::default(),
59            1.0,
60            Instant::now(),
61            Color32::RED,
62        );
63        assert!(matches!(result, Ok(true)));
64    }
65
66    #[test]
67    fn pulse_returns_false_when_finished() {
68        let painter = headless_painter();
69        // la animación dura 3.5 segundos; 4 segundos después ya terminó
70        let initial_time = Instant::now() - Duration::from_secs(4);
71        let result = Animation::pulse(
72            &painter,
73            RawPoint::default(),
74            1.0,
75            initial_time,
76            Color32::RED,
77        );
78        assert!(matches!(result, Ok(false)));
79    }
80}