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