bones_framework/
debug.rs

1//! Implements bones egui debug windows and tools. Requires 'ui' feature flag.
2
3use crate::prelude::*;
4
5/// Track frame time state synced from bevy frame time diagnostics for bones app.
6#[derive(HasSchema, Clone)]
7#[allow(missing_docs)]
8pub struct FrameDiagState {
9    pub fps: f64,
10    pub fps_avg: f64,
11    pub min_fps: f64,
12    pub max_fps: f64,
13    pub frame_time: f64,
14    pub frame_time_avg: f64,
15    pub min_frame_time: f64,
16    pub max_frame_time: f64,
17}
18
19impl Default for FrameDiagState {
20    fn default() -> Self {
21        Self {
22            fps: 0.0,
23            fps_avg: 0.0,
24            min_fps: f64::MAX,
25            max_fps: 0.0,
26            frame_time: 0.0,
27            frame_time_avg: 0.0,
28            min_frame_time: f64::MAX,
29            max_frame_time: 0.0,
30        }
31    }
32}
33
34impl FrameDiagState {
35    /// Reset min/max values to default
36    pub fn reset(&mut self) {
37        self.min_fps = f64::MAX;
38        self.max_fps = 0.0;
39        self.min_frame_time = f64::MAX;
40        self.max_frame_time = 0.0;
41    }
42}
43
44/// State of frame time diagnostic window. Stored in [`EguiCtx`] state,
45/// setting open = true will open window if plugin installed.
46#[derive(Clone, Default)]
47pub struct FrameTimeWindowState {
48    /// Is window open?
49    pub open: bool,
50}
51
52/// If installed, allows opening egui window with [`FrameTimeWindowState`] in [`EguiCtx`] state
53/// to get frame time information.
54pub fn frame_time_diagnostics_plugin(core: &mut SessionBuilder) {
55    core.stages
56        .add_system_to_stage(CoreStage::Last, frame_diagnostic_window);
57}
58
59/// Renders frame time diagnostic window in Egui if window is set to open in [`FrameTimeWindowState`]
60/// stored in [`EguiCtx`] state.
61pub fn frame_diagnostic_window(
62    mut state: Option<ResMut<FrameDiagState>>,
63    // localization: Res<Localization>,
64    egui_ctx: ResMut<EguiCtx>,
65) {
66    let mut window_state = egui_ctx.get_state::<FrameTimeWindowState>();
67    let window_open = &mut window_state.open;
68
69    if *window_open {
70        // egui::Window::new(&localization.get("frame-diagnostics"))
71        egui::Window::new("Frame Diagnostics")
72            .id(egui::Id::new("frame_diagnostics"))
73            .default_width(500.0)
74            .open(window_open)
75            .show(&egui_ctx, |ui| {
76                if let Some(state) = state.as_mut() {
77                    // if ui.button(&localization.get("reset-min-max")).clicked() {
78                    if ui.button("Reset Min/Max").clicked() {
79                        state.reset();
80                    }
81
82                    ui.monospace(format!(
83                        "{label:20}: {fps:4.0}{suffix:3} ( {min:4.0}{suffix:3}, {avg:4.0}{suffix:3}, {max:4.0}{suffix:3} )",
84                        // label = localization.get("frames-per-second"),
85                        label = "Frames Per Second",
86                        fps = state.fps,
87                        // suffix = fps.suffix,
88                        suffix = "fps",
89                        min = state.min_fps,
90                        avg = state.fps_avg,
91                        max = state.max_fps,
92                    ));
93                    ui.monospace(format!(
94                        "{label:20}: {fps:4.1}{suffix:3} ( {min:4.1}{suffix:3}, {avg:4.0}{suffix:3}, {max:4.1}{suffix:3} )",
95                        // label = localization.get("frame-time"),
96                        label = "Frame Time",
97                        fps = state.frame_time,
98                        suffix = "ms",
99                        min = state.min_frame_time,
100                        avg = state.frame_time_avg,
101                        max = state.max_frame_time,
102                    ));
103                }
104                else {
105                    ui.monospace(
106                        "No frame time data from Bevy diagnostics.",
107                    );
108                }
109            });
110    }
111
112    egui_ctx.set_state(window_state);
113}