bevy_rapier3d/plugin/systems/
writeback.rs

1use crate::dynamics::MassProperties;
2use crate::dynamics::ReadMassProperties;
3use crate::plugin::context::{RapierContextEntityLink, RapierRigidBodySet};
4use crate::plugin::RapierConfiguration;
5use crate::prelude::MassModifiedEvent;
6use bevy::prelude::*;
7
8/// System responsible for writing updated mass properties back into the [`ReadMassProperties`] component.
9pub fn writeback_mass_properties(
10    link: Query<&RapierContextEntityLink>,
11    rigidbody_set: Query<&RapierRigidBodySet>,
12    config: Query<&RapierConfiguration>,
13
14    mut mass_props: Query<&mut ReadMassProperties>,
15    mut mass_modified: MessageReader<MassModifiedEvent>,
16) {
17    for entity in mass_modified.read() {
18        let link = link
19            .get(entity.0)
20            .expect("Could not find `RapierContextEntityLink`");
21        let config = config
22            .get(link.0)
23            .expect("Could not find `RapierConfiguration`");
24        if config.physics_pipeline_active {
25            let Ok(rigidbody_set) = rigidbody_set.get(link.0) else {
26                continue;
27            };
28
29            if let Some(handle) = rigidbody_set.entity2body.get(entity).copied() {
30                if let Some(rb) = rigidbody_set.bodies.get(handle) {
31                    if let Ok(mut mass_props) = mass_props.get_mut(**entity) {
32                        let new_mass_props =
33                            MassProperties::from_rapier(rb.mass_properties().local_mprops);
34
35                        // NOTE: we write the new value only if there was an
36                        //       actual change, in order to not trigger bevy’s
37                        //       change tracking when the values didn’t change.
38                        if mass_props.get() != &new_mass_props {
39                            mass_props.set(new_mass_props);
40                        }
41                    }
42                }
43            }
44        }
45    }
46}