repose_devtools/
lib.rs

1use std::time::Instant;
2
3use repose_core::{Color, Rect, Scene, SceneNode};
4
5pub struct Hud {
6    pub inspector_enabled: bool,
7    pub hovered: Option<Rect>,
8    frame_count: u64,
9    last_frame: Option<Instant>,
10    fps_smooth: f32,
11    pub metrics: Option<Metrics>,
12}
13
14impl Hud {
15    pub fn new() -> Self {
16        Self {
17            inspector_enabled: false,
18            hovered: None,
19            frame_count: 0,
20            last_frame: None,
21            fps_smooth: 0.0,
22            metrics: None,
23        }
24    }
25    pub fn toggle_inspector(&mut self) {
26        self.inspector_enabled = !self.inspector_enabled;
27    }
28    pub fn set_hovered(&mut self, r: Option<Rect>) {
29        self.hovered = r;
30    }
31
32    pub fn overlay(&mut self, scene: &mut Scene) {
33        self.frame_count += 1;
34        // FPS
35        let now = Instant::now();
36        if let Some(prev) = self.last_frame.replace(now) {
37            let dt = (now - prev).as_secs_f32();
38            if dt > 0.0 {
39                let fps = 1.0 / dt;
40                // simple EMA
41                let a = 0.2;
42                self.fps_smooth = if self.fps_smooth == 0.0 {
43                    fps
44                } else {
45                    (1.0 - a) * self.fps_smooth + a * fps
46                };
47            }
48        }
49        let mut lines = vec![
50            format!("frame: {}", self.frame_count),
51            format!("fps: {:.1}", self.fps_smooth),
52        ];
53        if let Some(m) = &self.metrics {
54            lines.push(format!("build+layout: {:.2} ms", m.build_layout_ms));
55            lines.push(format!("nodes: {}", m.scene_nodes));
56        }
57        let text = lines.join("  |  ");
58        scene.nodes.push(SceneNode::Text {
59            rect: Rect {
60                x: 8.0,
61                y: 8.0,
62                w: 200.0,
63                h: 16.0,
64            },
65            text,
66            color: Color::from_hex("#AAAAAA"),
67            size: 14.0,
68        });
69
70        if let Some(r) = self.hovered {
71            scene.nodes.push(SceneNode::Border {
72                rect: r,
73                color: Color::from_hex("#44AAFF"),
74                width: 2.0,
75                radius: 0.0,
76            });
77        }
78    }
79}
80
81#[derive(Clone, Debug, Default)]
82pub struct Metrics {
83    pub build_layout_ms: f32,
84    pub scene_nodes: usize,
85}
86
87pub struct Inspector {
88    pub hud: Hud,
89}
90impl Inspector {
91    pub fn new() -> Self {
92        Self { hud: Hud::new() }
93    }
94    pub fn frame(&mut self, scene: &mut Scene) {
95        if self.hud.inspector_enabled {
96            self.hud.overlay(scene);
97        }
98    }
99}