
- changed `EntityCountDiagnosticsPlugin` to not use an exclusive system to get its entity count - removed mention of `WgpuResourceDiagnosticsPlugin` in example `log_diagnostics` as it doesn't exist anymore - added ability to enable, disable ~~or toggle~~ a diagnostic (fix #3767) - made diagnostic values lazy, so they are only computed if the diagnostic is enabled - do not log an average for diagnostics with only one value - removed `sum` function from diagnostic as it isn't really useful - ~~do not keep an average of the FPS diagnostic. it is already an average on the last 20 frames, so the average FPS was an average of the last 20 frames over the last 20 frames~~ - do not compute the FPS value as an average over the last 20 frames but give the actual "instant FPS" - updated log format to use variable capture - added some doc - the frame counter diagnostic value can be reseted to 0
132 lines
4.3 KiB
Rust
132 lines
4.3 KiB
Rust
use super::{Diagnostic, DiagnosticId, Diagnostics};
|
|
use bevy_app::prelude::*;
|
|
use bevy_ecs::system::{Res, ResMut};
|
|
use bevy_log::{debug, info};
|
|
use bevy_time::{Time, Timer};
|
|
use bevy_utils::Duration;
|
|
|
|
/// An App Plugin that logs diagnostics to the console
|
|
pub struct LogDiagnosticsPlugin {
|
|
pub debug: bool,
|
|
pub wait_duration: Duration,
|
|
pub filter: Option<Vec<DiagnosticId>>,
|
|
}
|
|
|
|
/// State used by the [`LogDiagnosticsPlugin`]
|
|
struct LogDiagnosticsState {
|
|
timer: Timer,
|
|
filter: Option<Vec<DiagnosticId>>,
|
|
}
|
|
|
|
impl Default for LogDiagnosticsPlugin {
|
|
fn default() -> Self {
|
|
LogDiagnosticsPlugin {
|
|
debug: false,
|
|
wait_duration: Duration::from_secs(1),
|
|
filter: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Plugin for LogDiagnosticsPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.insert_resource(LogDiagnosticsState {
|
|
timer: Timer::new(self.wait_duration, true),
|
|
filter: self.filter.clone(),
|
|
});
|
|
|
|
if self.debug {
|
|
app.add_system_to_stage(CoreStage::PostUpdate, Self::log_diagnostics_debug_system);
|
|
} else {
|
|
app.add_system_to_stage(CoreStage::PostUpdate, Self::log_diagnostics_system);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl LogDiagnosticsPlugin {
|
|
pub fn filtered(filter: Vec<DiagnosticId>) -> Self {
|
|
LogDiagnosticsPlugin {
|
|
filter: Some(filter),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
fn log_diagnostic(diagnostic: &Diagnostic) {
|
|
if let Some(value) = diagnostic.value() {
|
|
if diagnostic.get_max_history_length() > 1 {
|
|
if let Some(average) = diagnostic.average() {
|
|
info!(
|
|
target: "bevy diagnostic",
|
|
// Suffix is only used for 's' as in seconds currently,
|
|
// so we reserve one column for it; however,
|
|
// Do not reserve one column for the suffix in the average
|
|
// The ) hugging the value is more aesthetically pleasing
|
|
"{name:<name_width$}: {value:>11.6}{suffix:1} (avg {average:>.6}{suffix:})",
|
|
name = diagnostic.name,
|
|
suffix = diagnostic.suffix,
|
|
name_width = crate::MAX_DIAGNOSTIC_NAME_WIDTH,
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
info!(
|
|
target: "bevy diagnostic",
|
|
"{name:<name_width$}: {value:>.6}{suffix:}",
|
|
name = diagnostic.name,
|
|
suffix = diagnostic.suffix,
|
|
name_width = crate::MAX_DIAGNOSTIC_NAME_WIDTH,
|
|
);
|
|
}
|
|
}
|
|
|
|
fn log_diagnostics_system(
|
|
mut state: ResMut<LogDiagnosticsState>,
|
|
time: Res<Time>,
|
|
diagnostics: Res<Diagnostics>,
|
|
) {
|
|
if state.timer.tick(time.delta()).finished() {
|
|
if let Some(ref filter) = state.filter {
|
|
for diagnostic in filter.iter().flat_map(|id| {
|
|
diagnostics
|
|
.get(*id)
|
|
.filter(|diagnostic| diagnostic.is_enabled)
|
|
}) {
|
|
Self::log_diagnostic(diagnostic);
|
|
}
|
|
} else {
|
|
for diagnostic in diagnostics
|
|
.iter()
|
|
.filter(|diagnostic| diagnostic.is_enabled)
|
|
{
|
|
Self::log_diagnostic(diagnostic);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn log_diagnostics_debug_system(
|
|
mut state: ResMut<LogDiagnosticsState>,
|
|
time: Res<Time>,
|
|
diagnostics: Res<Diagnostics>,
|
|
) {
|
|
if state.timer.tick(time.delta()).finished() {
|
|
if let Some(ref filter) = state.filter {
|
|
for diagnostic in filter.iter().flat_map(|id| {
|
|
diagnostics
|
|
.get(*id)
|
|
.filter(|diagnostic| diagnostic.is_enabled)
|
|
}) {
|
|
debug!("{:#?}\n", diagnostic);
|
|
}
|
|
} else {
|
|
for diagnostic in diagnostics
|
|
.iter()
|
|
.filter(|diagnostic| diagnostic.is_enabled)
|
|
{
|
|
debug!("{:#?}\n", diagnostic);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|