bevy_rapier2d/plugin/systems/
remove.rs1use crate::dynamics::ImpulseJoint;
2use crate::dynamics::MultibodyJoint;
3use crate::dynamics::RapierImpulseJointHandle;
4use crate::dynamics::RapierMultibodyJointHandle;
5use crate::dynamics::RapierRigidBodyHandle;
6use crate::dynamics::RigidBody;
7use crate::geometry::Collider;
8use crate::geometry::ColliderDisabled;
9use crate::geometry::RapierColliderHandle;
10use crate::plugin::context::{
11 RapierContextColliders, RapierContextJoints, RapierContextSimulation, RapierRigidBodySet,
12};
13use crate::prelude::MassModifiedEvent;
14use crate::prelude::RigidBodyDisabled;
15use crate::prelude::Sensor;
16use bevy::ecs::query::IterQueryData;
17use bevy::prelude::*;
18
19pub fn sync_removals(
23 mut commands: Commands,
24 mut context_writer: Query<(
25 &mut RapierContextSimulation,
26 &mut RapierContextColliders,
27 &mut RapierContextJoints,
28 &mut RapierRigidBodySet,
29 )>,
30 (
33 q_has_rigidbody_handle,
34 q_has_collider_handle,
35 q_has_multibody_joint_handle,
36 q_has_impulse_joint_handle,
37 ): (
38 Query<(), With<RapierRigidBodyHandle>>,
39 Query<(), With<RapierColliderHandle>>,
40 Query<(), With<RapierMultibodyJointHandle>>,
41 Query<(), With<RapierImpulseJointHandle>>,
42 ),
43 mut removed_bodies: RemovedComponents<RapierRigidBodyHandle>,
44 mut removed_colliders: RemovedComponents<RapierColliderHandle>,
45 mut removed_impulse_joints: RemovedComponents<RapierImpulseJointHandle>,
46 mut removed_multibody_joints: RemovedComponents<RapierMultibodyJointHandle>,
47 orphan_bodies: Query<Entity, (With<RapierRigidBodyHandle>, Without<RigidBody>)>,
48 orphan_colliders: Query<Entity, (With<RapierColliderHandle>, Without<Collider>)>,
49 orphan_impulse_joints: Query<Entity, (With<RapierImpulseJointHandle>, Without<ImpulseJoint>)>,
50 orphan_multibody_joints: Query<
51 Entity,
52 (With<RapierMultibodyJointHandle>, Without<MultibodyJoint>),
53 >,
54
55 mut removed_sensors: RemovedComponents<Sensor>,
56 mut removed_rigid_body_disabled: RemovedComponents<RigidBodyDisabled>,
57 mut removed_colliders_disabled: RemovedComponents<ColliderDisabled>,
58
59 mut mass_modified: MessageWriter<MassModifiedEvent>,
60) {
61 for entity in removed_bodies
65 .read()
66 .filter(|e| !q_has_rigidbody_handle.contains(*e))
67 {
68 let Some(((mut context, mut context_colliders, mut joints, mut rigidbody_set), handle)) =
69 find_context(&mut context_writer, |res| res.3.entity2body.remove(&entity))
70 else {
71 continue;
72 };
73 let context = &mut *context;
74 let joints = &mut *joints;
75
76 let _ = rigidbody_set.last_body_transform_set.remove(&handle);
77 rigidbody_set.bodies.remove(
78 handle,
79 &mut context.islands,
80 &mut context_colliders.colliders,
81 &mut joints.impulse_joints,
82 &mut joints.multibody_joints,
83 false,
84 );
85 }
86
87 for entity in orphan_bodies.iter() {
88 if let Some(((mut context, mut context_colliders, mut joints, mut rigidbody_set), handle)) =
89 find_context(&mut context_writer, |res| res.3.entity2body.remove(&entity))
90 {
91 let context = &mut *context;
92 let joints = &mut *joints;
93 let _ = rigidbody_set.last_body_transform_set.remove(&handle);
94 rigidbody_set.bodies.remove(
95 handle,
96 &mut context.islands,
97 &mut context_colliders.colliders,
98 &mut joints.impulse_joints,
99 &mut joints.multibody_joints,
100 false,
101 );
102 }
103 commands.entity(entity).remove::<RapierRigidBodyHandle>();
104 }
105
106 for entity in removed_colliders
110 .read()
111 .filter(|e| !q_has_collider_handle.contains(*e))
112 {
113 let Some(((mut context, mut context_colliders, _, mut rigidbody_set), handle)) =
114 find_context(&mut context_writer, |res| {
115 res.1.entity2collider.remove(&entity)
116 })
117 else {
118 continue;
119 };
120 let context = &mut *context;
121 if let Some(parent) = context_colliders.collider_parent(&rigidbody_set, entity) {
122 mass_modified.write(parent.into());
123 }
124
125 context_colliders.colliders.remove(
126 handle,
127 &mut context.islands,
128 &mut rigidbody_set.bodies,
129 true,
130 );
131 context.deleted_colliders.insert(handle, entity);
132 }
133
134 for entity in orphan_colliders.iter() {
135 if let Some(((mut context, mut context_colliders, _, mut rigidbody_set), handle)) =
136 find_context(&mut context_writer, |res| {
137 res.1.entity2collider.remove(&entity)
138 })
139 {
140 let context = &mut *context;
141 let context_colliders = &mut *context_colliders;
142 if let Some(parent) = context_colliders.collider_parent(&rigidbody_set, entity) {
143 mass_modified.write(parent.into());
144 }
145
146 context_colliders.colliders.remove(
147 handle,
148 &mut context.islands,
149 &mut rigidbody_set.bodies,
150 true,
151 );
152 context.deleted_colliders.insert(handle, entity);
153 }
154 commands.entity(entity).remove::<RapierColliderHandle>();
155 }
156
157 for entity in removed_impulse_joints
161 .read()
162 .filter(|e| !q_has_impulse_joint_handle.contains(*e))
163 {
164 let Some(((_, _, mut joints, _), handle)) = find_context(&mut context_writer, |res| {
165 res.2.entity2impulse_joint.remove(&entity)
166 }) else {
167 continue;
168 };
169 joints.impulse_joints.remove(handle, true);
170 }
171
172 for entity in orphan_impulse_joints.iter() {
173 if let Some(((_, _, mut joints, _), handle)) = find_context(&mut context_writer, |res| {
174 res.2.entity2impulse_joint.remove(&entity)
175 }) {
176 joints.impulse_joints.remove(handle, true);
177 }
178 commands.entity(entity).remove::<RapierImpulseJointHandle>();
179 }
180
181 for entity in removed_multibody_joints
185 .read()
186 .filter(|e| !q_has_multibody_joint_handle.contains(*e))
187 {
188 let Some(((_, _, mut joints, _), handle)) = find_context(&mut context_writer, |res| {
189 res.2.entity2multibody_joint.remove(&entity)
190 }) else {
191 continue;
192 };
193 joints.multibody_joints.remove(handle, true);
194 }
195
196 for entity in orphan_multibody_joints.iter() {
197 if let Some(((_, _, mut joints, _), handle)) = find_context(&mut context_writer, |res| {
198 res.2.entity2multibody_joint.remove(&entity)
199 }) {
200 joints.multibody_joints.remove(handle, true);
201 }
202 commands
203 .entity(entity)
204 .remove::<RapierMultibodyJointHandle>();
205 }
206
207 for entity in removed_sensors.read() {
211 if let Some((mut context, handle)) = find_context(&mut context_writer, |context| {
212 context.1.entity2collider.get(&entity).copied()
213 }) {
214 if let Some(co) = context.1.colliders.get_mut(handle) {
215 co.set_sensor(false);
216 }
217 }
218 }
219
220 for entity in removed_colliders_disabled.read() {
221 if let Some((mut context, handle)) = find_context(&mut context_writer, |context| {
222 context.1.entity2collider.get(&entity).copied()
223 }) {
224 if let Some(co) = context.1.colliders.get_mut(handle) {
225 co.set_enabled(true);
226 }
227 }
228 }
229
230 for entity in removed_rigid_body_disabled.read() {
231 if let Some(((_, _, _, mut rigidbody_set), handle)) =
232 find_context(&mut context_writer, |res| {
233 res.3.entity2body.get(&entity).copied()
234 })
235 {
236 if let Some(rb) = rigidbody_set.bodies.get_mut(handle) {
237 rb.set_enabled(true);
238 }
239 }
240 }
241
242 }
244
245fn find_context<'a, TReturn, TQueryParams: IterQueryData>(
246 context_writer: &'a mut Query<TQueryParams>,
247 item_finder: impl Fn(&mut TQueryParams::Item<'_, '_>) -> Option<TReturn>,
248) -> Option<(TQueryParams::Item<'a, 'a>, TReturn)> {
249 let ret: Option<(TQueryParams::Item<'_, '_>, TReturn)> = context_writer
250 .iter_mut()
251 .find_map(|mut context| item_finder(&mut context).map(|handle| (context, handle)));
252 ret
253}