#![cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
#![cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
#[cfg(feature = "bevy_diagnostic")]
mod entity_counters;
mod path_macro;
#[cfg(feature = "bevy_diagnostic")]
mod total;
#[cfg(feature = "diagnostic_ui")]
pub mod ui;
#[cfg(feature = "bevy_diagnostic")]
pub use entity_counters::{PhysicsEntityDiagnostics, PhysicsEntityDiagnosticsPlugin};
pub(crate) use path_macro::impl_diagnostic_paths;
#[cfg(feature = "bevy_diagnostic")]
pub use total::{PhysicsTotalDiagnostics, PhysicsTotalDiagnosticsPlugin};
use crate::{PhysicsStepSystems, schedule::PhysicsSchedule};
use bevy::{
diagnostic::DiagnosticPath,
prelude::{App, IntoScheduleConfigs, ResMut, Resource, SystemSet},
};
#[cfg(feature = "bevy_diagnostic")]
use bevy::{
diagnostic::{Diagnostic, Diagnostics, RegisterDiagnostic},
prelude::{Plugin, Res},
};
use core::time::Duration;
#[cfg(feature = "bevy_diagnostic")]
pub struct PhysicsDiagnosticsPlugin;
#[cfg(feature = "bevy_diagnostic")]
impl Plugin for PhysicsDiagnosticsPlugin {
fn build(&self, app: &mut App) {
app.configure_sets(
PhysicsSchedule,
(
PhysicsDiagnosticsSystems::Reset.before(PhysicsStepSystems::First),
PhysicsDiagnosticsSystems::WriteDiagnostics.after(PhysicsStepSystems::Last),
),
);
}
}
#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum PhysicsDiagnosticsSystems {
Reset,
WriteDiagnostics,
}
pub trait PhysicsDiagnostics: Default + Resource {
fn timer_paths(&self) -> Vec<(&'static DiagnosticPath, Duration)> {
Vec::new()
}
fn counter_paths(&self) -> Vec<(&'static DiagnosticPath, u32)> {
Vec::new()
}
fn reset(mut physics_diagnostics: ResMut<Self>) {
*physics_diagnostics = Self::default();
}
#[cfg(feature = "bevy_diagnostic")]
fn write_diagnostics(physics_diagnostics: Res<Self>, mut diagnostics: Diagnostics) {
for (path, duration) in physics_diagnostics.timer_paths() {
diagnostics.add_measurement(path, || duration.as_secs_f64() * 1000.0);
}
for (path, count) in physics_diagnostics.counter_paths() {
diagnostics.add_measurement(path, || count as f64);
}
}
}
pub trait AppDiagnosticsExt {
fn register_physics_diagnostics<T: PhysicsDiagnostics>(&mut self);
}
impl AppDiagnosticsExt for App {
fn register_physics_diagnostics<T: PhysicsDiagnostics>(&mut self) {
if self.world().is_resource_added::<T>() {
return;
}
self.init_resource::<T>();
self.configure_sets(
PhysicsSchedule,
PhysicsDiagnosticsSystems::Reset.before(PhysicsStepSystems::First),
);
self.add_systems(
PhysicsSchedule,
T::reset
.in_set(PhysicsDiagnosticsSystems::Reset)
.ambiguous_with_all(),
);
#[cfg(feature = "bevy_diagnostic")]
{
if !self.is_plugin_added::<PhysicsDiagnosticsPlugin>() {
return;
}
let diagnostics = T::default();
let timer_paths = diagnostics.timer_paths();
let counter_paths = diagnostics.counter_paths();
for path in timer_paths.iter().map(|(path, _)| *path) {
self.register_diagnostic(Diagnostic::new(path.clone()).with_suffix("ms"));
}
for path in counter_paths.iter().map(|(path, _)| *path) {
self.register_diagnostic(Diagnostic::new(path.clone()).with_smoothing_factor(0.0));
}
self.add_systems(
PhysicsSchedule,
T::write_diagnostics
.in_set(PhysicsDiagnosticsSystems::WriteDiagnostics)
.ambiguous_with_all(),
);
}
}
}