avian3d/diagnostics/
entity_counters.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use bevy::{diagnostic::DiagnosticPath, prelude::*};

use crate::{
    dynamics::solver::joints::*, ColliderMarker, PhysicsSchedule, PhysicsStepSet, RigidBody,
};

use super::{impl_diagnostic_paths, AppDiagnosticsExt, PhysicsDiagnostics};

/// A plugin that adds diagnostics for physics entity counts.
pub struct PhysicsEntityDiagnosticsPlugin;

impl Plugin for PhysicsEntityDiagnosticsPlugin {
    fn build(&self, app: &mut App) {
        // Register diagnostics for physics entity counts.
        // NOTE: This should be done after the `PhysicsDiagnosticsPlugin` is added.
        app.register_physics_diagnostics::<PhysicsEntityDiagnostics>();

        app.add_systems(
            PhysicsSchedule,
            diagnostic_entity_counts.in_set(PhysicsStepSet::First),
        );
    }
}

/// Diagnostics for physics entity counts.
#[derive(Resource, Debug, Default, Reflect)]
#[reflect(Resource, Debug)]
pub struct PhysicsEntityDiagnostics {
    /// The number of dynamic bodies.
    pub dynamic_body_count: u32,
    /// The number of kinematic bodies.
    pub kinematic_body_count: u32,
    /// The number of static bodies.
    pub static_body_count: u32,
    /// The number of colliders.
    pub collider_count: u32,
    /// The number of joint.
    pub joint_count: u32,
}

impl PhysicsDiagnostics for PhysicsEntityDiagnostics {
    fn counter_paths(&self) -> Vec<(&'static DiagnosticPath, u32)> {
        vec![
            (Self::DYNAMIC_BODY_COUNT, self.dynamic_body_count),
            (Self::KINEMATIC_BODY_COUNT, self.kinematic_body_count),
            (Self::STATIC_BODY_COUNT, self.static_body_count),
            (Self::COLLIDER_COUNT, self.collider_count),
            (Self::JOINT_COUNT, self.joint_count),
        ]
    }
}

impl_diagnostic_paths! {
    impl PhysicsEntityDiagnostics {
        DYNAMIC_BODY_COUNT: "avian/entity_count/dynamic_bodies",
        KINEMATIC_BODY_COUNT: "avian/entity_count/kinematic_bodies",
        STATIC_BODY_COUNT: "avian/entity_count/static_bodies",
        COLLIDER_COUNT: "avian/entity_count/colliders",
        JOINT_COUNT: "avian/entity_count/joints",
    }
}

// TODO: This is pretty inefficient.
fn diagnostic_entity_counts(
    rigid_bodies_query: Query<&RigidBody>,
    colliders_query: Query<&ColliderMarker>,
    fixed_joint_query: Query<&FixedJoint>,
    prismatic_joint_query: Query<&PrismaticJoint>,
    distance_joint_query: Query<&DistanceJoint>,
    revolute_joint_query: Query<&RevoluteJoint>,
    #[cfg(feature = "3d")] spherical_joint_query: Query<&SphericalJoint>,
    mut diagnostics: ResMut<PhysicsEntityDiagnostics>,
) {
    diagnostics.dynamic_body_count = rigid_bodies_query
        .iter()
        .filter(|rb| rb.is_dynamic())
        .count() as u32;
    diagnostics.kinematic_body_count = rigid_bodies_query
        .iter()
        .filter(|rb| rb.is_kinematic())
        .count() as u32;
    diagnostics.static_body_count = rigid_bodies_query
        .iter()
        .filter(|rb| rb.is_static())
        .count() as u32;
    diagnostics.collider_count = colliders_query.iter().count() as u32;
    diagnostics.joint_count = fixed_joint_query.iter().count() as u32
        + prismatic_joint_query.iter().count() as u32
        + distance_joint_query.iter().count() as u32
        + revolute_joint_query.iter().count() as u32;
    #[cfg(feature = "3d")]
    {
        diagnostics.joint_count += spherical_joint_query.iter().count() as u32;
    }
}