bevy_rapier3d/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::QueryData;
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 mut removed_bodies: RemovedComponents<RapierRigidBodyHandle>,
31 mut removed_colliders: RemovedComponents<RapierColliderHandle>,
32 mut removed_impulse_joints: RemovedComponents<RapierImpulseJointHandle>,
33 mut removed_multibody_joints: RemovedComponents<RapierMultibodyJointHandle>,
34 orphan_bodies: Query<Entity, (With<RapierRigidBodyHandle>, Without<RigidBody>)>,
35 orphan_colliders: Query<Entity, (With<RapierColliderHandle>, Without<Collider>)>,
36 orphan_impulse_joints: Query<Entity, (With<RapierImpulseJointHandle>, Without<ImpulseJoint>)>,
37 orphan_multibody_joints: Query<
38 Entity,
39 (With<RapierMultibodyJointHandle>, Without<MultibodyJoint>),
40 >,
41
42 mut removed_sensors: RemovedComponents<Sensor>,
43 mut removed_rigid_body_disabled: RemovedComponents<RigidBodyDisabled>,
44 mut removed_colliders_disabled: RemovedComponents<ColliderDisabled>,
45
46 mut mass_modified: MessageWriter<MassModifiedEvent>,
47) {
48 for entity in removed_bodies.read() {
52 let Some(((mut context, mut context_colliders, mut joints, mut rigidbody_set), handle)) =
53 find_context(&mut context_writer, |res| res.3.entity2body.remove(&entity))
54 else {
55 continue;
56 };
57 let context = &mut *context;
58 let joints = &mut *joints;
59
60 let _ = rigidbody_set.last_body_transform_set.remove(&handle);
61 rigidbody_set.bodies.remove(
62 handle,
63 &mut context.islands,
64 &mut context_colliders.colliders,
65 &mut joints.impulse_joints,
66 &mut joints.multibody_joints,
67 false,
68 );
69 }
70
71 for entity in orphan_bodies.iter() {
72 if let Some(((mut context, mut context_colliders, mut joints, mut rigidbody_set), handle)) =
73 find_context(&mut context_writer, |res| res.3.entity2body.remove(&entity))
74 {
75 let context = &mut *context;
76 let joints = &mut *joints;
77 let _ = rigidbody_set.last_body_transform_set.remove(&handle);
78 rigidbody_set.bodies.remove(
79 handle,
80 &mut context.islands,
81 &mut context_colliders.colliders,
82 &mut joints.impulse_joints,
83 &mut joints.multibody_joints,
84 false,
85 );
86 }
87 commands.entity(entity).remove::<RapierRigidBodyHandle>();
88 }
89
90 for entity in removed_colliders.read() {
94 let Some(((mut context, mut context_colliders, _, mut rigidbody_set), handle)) =
95 find_context(&mut context_writer, |res| {
96 res.1.entity2collider.remove(&entity)
97 })
98 else {
99 continue;
100 };
101 let context = &mut *context;
102 if let Some(parent) = context_colliders.collider_parent(&rigidbody_set, entity) {
103 mass_modified.write(parent.into());
104 }
105
106 context_colliders.colliders.remove(
107 handle,
108 &mut context.islands,
109 &mut rigidbody_set.bodies,
110 true,
111 );
112 context.deleted_colliders.insert(handle, entity);
113 }
114
115 for entity in orphan_colliders.iter() {
116 if let Some(((mut context, mut context_colliders, _, mut rigidbody_set), handle)) =
117 find_context(&mut context_writer, |res| {
118 res.1.entity2collider.remove(&entity)
119 })
120 {
121 let context = &mut *context;
122 let context_colliders = &mut *context_colliders;
123 if let Some(parent) = context_colliders.collider_parent(&rigidbody_set, entity) {
124 mass_modified.write(parent.into());
125 }
126
127 context_colliders.colliders.remove(
128 handle,
129 &mut context.islands,
130 &mut rigidbody_set.bodies,
131 true,
132 );
133 context.deleted_colliders.insert(handle, entity);
134 }
135 commands.entity(entity).remove::<RapierColliderHandle>();
136 }
137
138 for entity in removed_impulse_joints.read() {
142 let Some(((_, _, mut joints, _), handle)) = find_context(&mut context_writer, |res| {
143 res.2.entity2impulse_joint.remove(&entity)
144 }) else {
145 continue;
146 };
147 joints.impulse_joints.remove(handle, true);
148 }
149
150 for entity in orphan_impulse_joints.iter() {
151 if let Some(((_, _, mut joints, _), handle)) = find_context(&mut context_writer, |res| {
152 res.2.entity2impulse_joint.remove(&entity)
153 }) {
154 joints.impulse_joints.remove(handle, true);
155 }
156 commands.entity(entity).remove::<RapierImpulseJointHandle>();
157 }
158
159 for entity in removed_multibody_joints.read() {
163 let Some(((_, _, mut joints, _), handle)) = find_context(&mut context_writer, |res| {
164 res.2.entity2multibody_joint.remove(&entity)
165 }) else {
166 continue;
167 };
168 joints.multibody_joints.remove(handle, true);
169 }
170
171 for entity in orphan_multibody_joints.iter() {
172 if let Some(((_, _, mut joints, _), handle)) = find_context(&mut context_writer, |res| {
173 res.2.entity2multibody_joint.remove(&entity)
174 }) {
175 joints.multibody_joints.remove(handle, true);
176 }
177 commands
178 .entity(entity)
179 .remove::<RapierMultibodyJointHandle>();
180 }
181
182 for entity in removed_sensors.read() {
186 if let Some((mut context, handle)) = find_context(&mut context_writer, |context| {
187 context.1.entity2collider.get(&entity).copied()
188 }) {
189 if let Some(co) = context.1.colliders.get_mut(handle) {
190 co.set_sensor(false);
191 }
192 }
193 }
194
195 for entity in removed_colliders_disabled.read() {
196 if let Some((mut context, handle)) = find_context(&mut context_writer, |context| {
197 context.1.entity2collider.get(&entity).copied()
198 }) {
199 if let Some(co) = context.1.colliders.get_mut(handle) {
200 co.set_enabled(true);
201 }
202 }
203 }
204
205 for entity in removed_rigid_body_disabled.read() {
206 if let Some(((_, _, _, mut rigidbody_set), handle)) =
207 find_context(&mut context_writer, |res| {
208 res.3.entity2body.get(&entity).copied()
209 })
210 {
211 if let Some(rb) = rigidbody_set.bodies.get_mut(handle) {
212 rb.set_enabled(true);
213 }
214 }
215 }
216
217 }
219
220fn find_context<'a, TReturn, TQueryParams: QueryData>(
221 context_writer: &'a mut Query<TQueryParams>,
222 item_finder: impl Fn(&mut TQueryParams::Item<'_, '_>) -> Option<TReturn>,
223) -> Option<(TQueryParams::Item<'a, 'a>, TReturn)> {
224 let ret: Option<(TQueryParams::Item<'_, '_>, TReturn)> = context_writer
225 .iter_mut()
226 .find_map(|mut context| item_finder(&mut context).map(|handle| (context, handle)));
227 ret
228}