rapier3d/pipeline/
user_changes.rs1use crate::dynamics::{
2 ImpulseJointSet, IslandManager, JointEnabled, MultibodyJointSet, RigidBodyChanges,
3 RigidBodyHandle, RigidBodySet,
4};
5use crate::geometry::{
6 ColliderChanges, ColliderEnabled, ColliderHandle, ColliderPosition, ColliderSet,
7 ModifiedColliders,
8};
9
10pub(crate) fn handle_user_changes_to_colliders(
11 bodies: &mut RigidBodySet,
12 colliders: &mut ColliderSet,
13 modified_colliders: &[ColliderHandle],
14) {
15 for handle in modified_colliders {
16 if let Some(co) = colliders.get_mut_internal(*handle) {
19 if co.changes.contains(ColliderChanges::PARENT) {
20 if let Some(co_parent) = co.parent {
21 let parent_rb = &bodies[co_parent.handle];
22
23 co.pos = ColliderPosition(parent_rb.pos.position * co_parent.pos_wrt_parent);
24 co.changes |= ColliderChanges::POSITION;
25 }
26 }
27
28 if co.changes.intersects(
29 ColliderChanges::SHAPE
30 | ColliderChanges::LOCAL_MASS_PROPERTIES
31 | ColliderChanges::ENABLED_OR_DISABLED
32 | ColliderChanges::PARENT,
33 ) {
34 if let Some(rb) = co
35 .parent
36 .and_then(|p| bodies.get_mut_internal_with_modification_tracking(p.handle))
37 {
38 rb.changes |= RigidBodyChanges::LOCAL_MASS_PROPERTIES;
39 }
40 }
41 }
42 }
43}
44
45pub(crate) fn handle_user_changes_to_rigid_bodies(
46 mut islands: Option<&mut IslandManager>,
47 bodies: &mut RigidBodySet,
48 colliders: &mut ColliderSet,
49 impulse_joints: &mut ImpulseJointSet,
50 _multibody_joints: &mut MultibodyJointSet, modified_bodies: &[RigidBodyHandle],
52 modified_colliders: &mut ModifiedColliders,
53) {
54 enum FinalAction {
55 RemoveFromIsland,
56 }
57
58 for handle in modified_bodies {
59 let mut final_action = None;
60
61 if !bodies.contains(*handle) {
62 continue;
64 }
65
66 let rb = bodies.index_mut_internal(*handle);
67 let mut ids = rb.ids;
68 let changes = rb.changes;
69 let activation = rb.activation;
70
71 {
72 if rb.is_enabled() {
73 if let Some(islands) = islands.as_deref_mut() {
76 if (changes.contains(RigidBodyChanges::SLEEP) || changes.contains(RigidBodyChanges::TYPE))
79 && rb.is_enabled()
80 && !rb.activation.sleeping && rb.is_dynamic_or_kinematic() && islands.active_set.get(ids.active_set_id) != Some(handle)
83 {
84 ids.active_set_id = islands.active_set.len(); islands.active_set.push(*handle);
86 }
87 }
88 }
89
90 if changes.contains(RigidBodyChanges::POSITION)
92 || changes.contains(RigidBodyChanges::COLLIDERS)
93 {
94 rb.colliders
95 .update_positions(colliders, modified_colliders, &rb.pos.position);
96 }
97
98 if changes.contains(RigidBodyChanges::DOMINANCE)
99 || changes.contains(RigidBodyChanges::TYPE)
100 {
101 for handle in rb.colliders.0.iter() {
102 let co = colliders.index_mut_internal(*handle);
106 modified_colliders.push_once(*handle, co);
107 co.changes |= ColliderChanges::PARENT_EFFECTIVE_DOMINANCE;
108 }
109 }
110
111 if changes.contains(RigidBodyChanges::ENABLED_OR_DISABLED) {
112 for handle in rb.colliders.0.iter() {
114 let co = colliders.index_mut_internal(*handle);
118 modified_colliders.push_once(*handle, co);
119
120 if rb.enabled && co.flags.enabled == ColliderEnabled::DisabledByParent {
121 co.flags.enabled = ColliderEnabled::Enabled;
122 } else if !rb.enabled && co.flags.enabled == ColliderEnabled::Enabled {
123 co.flags.enabled = ColliderEnabled::DisabledByParent;
124 }
125
126 co.changes |= ColliderChanges::ENABLED_OR_DISABLED;
127 }
128
129 impulse_joints.map_attached_joints_mut(*handle, |_, _, _, joint| {
131 if rb.enabled && joint.data.enabled == JointEnabled::DisabledByAttachedBody {
132 joint.data.enabled = JointEnabled::Enabled;
133 } else if !rb.enabled && joint.data.enabled == JointEnabled::Enabled {
134 joint.data.enabled = JointEnabled::DisabledByAttachedBody;
135 }
136 });
137
138 if !rb.enabled {
142 final_action = Some(FinalAction::RemoveFromIsland);
143 }
144 }
145
146 if changes
150 .intersects(RigidBodyChanges::LOCAL_MASS_PROPERTIES | RigidBodyChanges::COLLIDERS)
151 {
152 rb.mprops.recompute_mass_properties_from_colliders(
153 colliders,
154 &rb.colliders,
155 rb.body_type,
156 &rb.pos.position,
157 );
158 }
159
160 rb.ids = ids;
161 rb.activation = activation;
162 }
163
164 if let Some(islands) = islands.as_deref_mut() {
166 if let Some(action) = final_action {
167 match action {
168 FinalAction::RemoveFromIsland => {
169 let ids = rb.ids;
170 islands.rigid_body_removed(*handle, &ids, bodies);
171 }
172 };
173 }
174 }
175 }
176}