use bevy::{ asset::diagnostic::AssetCountDiagnosticsPlugin, diagnostic::{ DiagnosticsStore, EntityCountDiagnosticsPlugin, FrameTimeDiagnosticsPlugin, SystemInformationDiagnosticsPlugin, }, input::{keyboard::KeyboardInput, ButtonState}, }; use crate::prelude::*; pub(crate) struct DebugPlugin; impl Plugin for DebugPlugin { fn build(&self, app: &mut App) { app.add_plugins(( FrameTimeDiagnosticsPlugin, EntityCountDiagnosticsPlugin::default(), AssetCountDiagnosticsPlugin::::default(), AssetCountDiagnosticsPlugin::::default(), AssetCountDiagnosticsPlugin::::default(), AssetCountDiagnosticsPlugin::::default(), SystemInformationDiagnosticsPlugin::default(), )) .add_systems(Startup, init_debug_ui) .add_systems( Update, ( toggle_debug_mode.run_if(on_event::()), display_diagnostics.run_if(resource_exists::()), toggle_debug_ui.run_if(resource_changed_or_removed::()), ), ); } } /// Marker resource used to enable Debug mode when present #[derive(Debug, Resource, Default)] struct DebugEnabled; #[derive(Debug, Component)] struct DebugRoot; fn toggle_debug_mode( mut events: EventReader, enabled: Option>, mut commands: Commands, ) { events .iter() .filter( |KeyboardInput { state, key_code, .. }| *state == ButtonState::Pressed && *key_code == Some(KeyCode::F3), ) .for_each(|_| match enabled { Some(_) => commands.remove_resource::(), None => commands.insert_resource(DebugEnabled), }); } fn toggle_debug_ui( mut visibility: Query<&mut Visibility, (With, Without)>, enabled: Option>, ) { visibility.iter_mut().for_each(|mut vis| { *vis = match enabled { Some(_) => Visibility::Visible, None => Visibility::Hidden, } }); } fn init_debug_ui(mut commands: Commands) { commands .spawn(( NodeBundle { style: Style { ..default() }, ..default() }, DebugRoot, )) .with_children(|parent| { parent.spawn(( TextBundle { style: Style { ..default() }, ..default() }, DebugRoot, )); }); } fn display_diagnostics( mut root: Query<&mut Text, With>, diagnostics: Res, ) { root.iter_mut().for_each(|mut text| { text.sections = diagnostics .iter() .map(|diagnostic| { TextSection::new( format!( "{}: {:.0}\n", diagnostic.name, diagnostic.smoothed().unwrap_or(0.0), ), TextStyle { ..default() }, ) }) .collect(); text.sections.sort_unstable_by(|a, b| a.value.cmp(&b.value)); }); }