rapier2d/pipeline/
user_changes.rs1use crate::alloc_prelude::*;
2use crate::dynamics::{
3 ImpulseJointSet, IslandManager, JointEnabled, MultibodyJointSet, RigidBodyChanges,
4 RigidBodyHandle, RigidBodySet,
5};
6use crate::geometry::{
7 ColliderChanges, ColliderEnabled, ColliderHandle, ColliderPosition, ColliderSet,
8 ModifiedColliders,
9};
10
11pub(crate) fn handle_user_changes_to_colliders(
12 bodies: &mut RigidBodySet,
13 colliders: &mut ColliderSet,
14 modified_colliders: &[ColliderHandle],
15) {
16 for handle in modified_colliders {
17 if let Some(co) = colliders.get_mut_internal(*handle) {
20 if co.changes.contains(ColliderChanges::PARENT) {
21 if let Some(co_parent) = co.parent {
22 let parent_rb = &bodies[co_parent.handle];
23
24 co.pos = ColliderPosition(parent_rb.pos.position * co_parent.pos_wrt_parent);
25 co.changes |= ColliderChanges::POSITION;
26 }
27 }
28
29 if co.changes.intersects(
30 ColliderChanges::SHAPE
31 | ColliderChanges::LOCAL_MASS_PROPERTIES
32 | ColliderChanges::ENABLED_OR_DISABLED
33 | ColliderChanges::PARENT,
34 ) {
35 if let Some(rb) = co
36 .parent
37 .and_then(|p| bodies.get_mut_internal_with_modification_tracking(p.handle))
38 {
39 rb.changes |= RigidBodyChanges::LOCAL_MASS_PROPERTIES;
40 }
41 }
42 }
43 }
44}
45
46pub(crate) fn handle_user_changes_to_rigid_bodies(
47 mut islands: Option<&mut IslandManager>,
48 bodies: &mut RigidBodySet,
49 colliders: &mut ColliderSet,
50 impulse_joints: &mut ImpulseJointSet,
51 multibody_joints: &mut MultibodyJointSet, modified_bodies: &[RigidBodyHandle],
53 modified_colliders: &mut ModifiedColliders,
54) {
55 enum FinalAction {
56 RemoveFromIsland,
57 }
58
59 let mut any_jointed_body_modified = false;
60
61 for handle in modified_bodies {
62 let mut final_action = None;
63 let type_changed;
64
65 if !bodies.contains(*handle) {
66 continue;
68 }
69
70 any_jointed_body_modified =
74 any_jointed_body_modified || impulse_joints.body_may_have_joints(*handle);
75
76 {
77 let rb = bodies.index_mut_internal(*handle);
78 let changes = rb.changes;
79 let activation = rb.activation;
80
81 if rb.is_enabled() {
82 if let Some(islands) = islands.as_deref_mut() {
85 islands.rigid_body_updated(*handle, bodies);
86 }
87 }
88
89 let rb = bodies.index_mut_internal(*handle);
90
91 if changes.contains(RigidBodyChanges::POSITION)
93 || changes.contains(RigidBodyChanges::COLLIDERS)
94 {
95 rb.colliders
96 .update_positions(colliders, modified_colliders, &rb.pos.position);
97
98 rb.mprops
103 .update_world_mass_properties(rb.body_type, &rb.pos.position);
104 }
105
106 type_changed = changes.contains(RigidBodyChanges::TYPE);
107
108 if changes.contains(RigidBodyChanges::DOMINANCE)
109 || changes.contains(RigidBodyChanges::TYPE)
110 {
111 for handle in rb.colliders.0.iter() {
112 let co = colliders.index_mut_internal(*handle);
116 modified_colliders.push_once(*handle, co);
117 co.changes |= ColliderChanges::PARENT_EFFECTIVE_DOMINANCE;
118 }
119 }
120
121 if changes.contains(RigidBodyChanges::ENABLED_OR_DISABLED) {
122 for handle in rb.colliders.0.iter() {
124 let co = colliders.index_mut_internal(*handle);
128 modified_colliders.push_once(*handle, co);
129
130 if rb.enabled && co.flags.enabled == ColliderEnabled::DisabledByParent {
131 co.flags.enabled = ColliderEnabled::Enabled;
132 } else if !rb.enabled && co.flags.enabled == ColliderEnabled::Enabled {
133 co.flags.enabled = ColliderEnabled::DisabledByParent;
134 }
135
136 co.changes |= ColliderChanges::ENABLED_OR_DISABLED;
137 }
138
139 let mut joint_island_events = Vec::new();
141 impulse_joints.map_attached_joints_mut(*handle, |rb1, rb2, joint_handle, joint| {
142 if rb.enabled && joint.data.enabled == JointEnabled::DisabledByAttachedBody {
143 joint.data.enabled = JointEnabled::Enabled;
144 joint_island_events.push(crate::dynamics::ImpulseJointIslandEvent::Link {
145 handle: joint_handle,
146 body1: rb1,
147 body2: rb2,
148 });
149 } else if !rb.enabled && joint.data.enabled == JointEnabled::Enabled {
150 joint.data.enabled = JointEnabled::DisabledByAttachedBody;
151 joint_island_events.push(
152 crate::dynamics::ImpulseJointIslandEvent::Unlink {
153 handle: joint_handle,
154 },
155 );
156 }
157 });
158 impulse_joints.island_events.extend(joint_island_events);
159
160 if let Some(link) = multibody_joints.rigid_body_link(*handle).copied() {
163 multibody_joints.island_chain_events.push(link.multibody);
164 }
165
166 if !rb.enabled {
170 final_action = Some(FinalAction::RemoveFromIsland);
171 }
172 }
173
174 if changes
178 .intersects(RigidBodyChanges::LOCAL_MASS_PROPERTIES | RigidBodyChanges::COLLIDERS)
179 {
180 rb.mprops.recompute_mass_properties_from_colliders(
181 colliders,
182 &rb.colliders,
183 rb.body_type,
184 &rb.pos.position,
185 );
186 }
187
188 rb.activation = activation;
189 }
190
191 if let Some(islands) = islands.as_deref_mut() {
193 if let Some(action) = final_action {
194 match action {
195 FinalAction::RemoveFromIsland => {
196 let rb = bodies.index_mut_internal(*handle);
197 let ids = rb.ids;
198 islands.rigid_body_removed_or_disabled(*handle, &ids, bodies);
199 }
200 };
201 }
202
203 if type_changed {
204 let mut joint_island_events = Vec::new();
210 impulse_joints.map_attached_joints_mut(*handle, |rb1, rb2, joint_handle, joint| {
211 joint_island_events.push(crate::dynamics::ImpulseJointIslandEvent::Unlink {
212 handle: joint_handle,
213 });
214 if joint.data.is_enabled() {
215 joint_island_events.push(crate::dynamics::ImpulseJointIslandEvent::Link {
216 handle: joint_handle,
217 body1: rb1,
218 body2: rb2,
219 });
220 }
221 });
222 impulse_joints.island_events.extend(joint_island_events);
223 if let Some(link) = multibody_joints.rigid_body_link(*handle).copied() {
224 multibody_joints.island_chain_events.push(link.multibody);
225 }
226 }
227
228 let rb = &bodies[*handle];
234 if rb.is_fixed() && rb.changes.contains(RigidBodyChanges::POSITION) {
235 let mut to_wake = Vec::new();
236 impulse_joints.map_attached_joints_mut(*handle, |rb1, rb2, _, _| {
237 to_wake.push(if rb1 == *handle { rb2 } else { rb1 });
238 });
239 for other in multibody_joints.bodies_attached_with_enabled_joint(*handle) {
240 to_wake.push(other);
241 }
242 for partner in to_wake {
243 islands.wake_up(bodies, partner, true);
244 }
245 }
246 }
247 }
248
249 if any_jointed_body_modified {
250 impulse_joints.bump_assembly_epoch();
251 }
252}