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