1use crate::data::{Arena, HasModifiedFlag, ModifiedObjects};
2use crate::dynamics::{
3 ImpulseJointSet, IslandManager, MultibodyJointSet, RigidBody, RigidBodyChanges, RigidBodyHandle,
4};
5use crate::geometry::ColliderSet;
6use std::ops::{Index, IndexMut};
7
8#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
10pub struct BodyPair {
12 pub body1: RigidBodyHandle,
14 pub body2: RigidBodyHandle,
16}
17
18impl BodyPair {
19 pub fn new(body1: RigidBodyHandle, body2: RigidBodyHandle) -> Self {
21 BodyPair { body1, body2 }
22 }
23}
24
25pub(crate) type ModifiedRigidBodies = ModifiedObjects<RigidBodyHandle, RigidBody>;
26
27impl HasModifiedFlag for RigidBody {
28 #[inline]
29 fn has_modified_flag(&self) -> bool {
30 self.changes.contains(RigidBodyChanges::MODIFIED)
31 }
32
33 #[inline]
34 fn set_modified_flag(&mut self) {
35 self.changes |= RigidBodyChanges::MODIFIED;
36 }
37}
38
39#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
40#[derive(Clone, Default, Debug)]
41pub struct RigidBodySet {
43 pub(crate) bodies: Arena<RigidBody>,
48 pub(crate) modified_bodies: ModifiedRigidBodies,
49}
50
51impl RigidBodySet {
52 pub fn new() -> Self {
54 RigidBodySet {
55 bodies: Arena::new(),
56 modified_bodies: ModifiedObjects::default(),
57 }
58 }
59
60 pub fn with_capacity(capacity: usize) -> Self {
62 RigidBodySet {
63 bodies: Arena::with_capacity(capacity),
64 modified_bodies: ModifiedRigidBodies::with_capacity(capacity),
65 }
66 }
67
68 pub(crate) fn take_modified(&mut self) -> ModifiedRigidBodies {
69 std::mem::take(&mut self.modified_bodies)
70 }
71
72 pub fn len(&self) -> usize {
74 self.bodies.len()
75 }
76
77 pub fn is_empty(&self) -> bool {
79 self.bodies.is_empty()
80 }
81
82 pub fn contains(&self, handle: RigidBodyHandle) -> bool {
84 self.bodies.contains(handle.0)
85 }
86
87 pub fn insert(&mut self, rb: impl Into<RigidBody>) -> RigidBodyHandle {
89 let mut rb = rb.into();
90 rb.reset_internal_references();
93 rb.changes.set(RigidBodyChanges::all(), true);
94
95 let handle = RigidBodyHandle(self.bodies.insert(rb));
96 self.modified_bodies
99 .push_unchecked(handle, &mut self.bodies[handle.0]);
100 handle
101 }
102
103 #[profiling::function]
105 pub fn remove(
106 &mut self,
107 handle: RigidBodyHandle,
108 islands: &mut IslandManager,
109 colliders: &mut ColliderSet,
110 impulse_joints: &mut ImpulseJointSet,
111 multibody_joints: &mut MultibodyJointSet,
112 remove_attached_colliders: bool,
113 ) -> Option<RigidBody> {
114 let rb = self.bodies.remove(handle.0)?;
115 islands.rigid_body_removed(handle, &rb.ids, self);
119
120 if remove_attached_colliders {
124 for collider in rb.colliders() {
125 colliders.remove(*collider, islands, self, false);
126 }
127 } else {
128 let colliders_to_detach = rb.colliders().to_vec();
130 for co_handle in colliders_to_detach {
131 colliders.set_parent(co_handle, None, self);
132 }
133 }
134
135 impulse_joints.remove_joints_attached_to_rigid_body(handle);
139 multibody_joints.remove_joints_attached_to_rigid_body(handle);
140
141 Some(rb)
142 }
143
144 pub fn get_unknown_gen(&self, i: u32) -> Option<(&RigidBody, RigidBodyHandle)> {
154 self.bodies
155 .get_unknown_gen(i)
156 .map(|(b, h)| (b, RigidBodyHandle(h)))
157 }
158
159 #[cfg(not(feature = "dev-remove-slow-accessors"))]
169 pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut RigidBody, RigidBodyHandle)> {
170 let (rb, handle) = self.bodies.get_unknown_gen_mut(i)?;
171 let handle = RigidBodyHandle(handle);
172 self.modified_bodies.push_once(handle, rb);
173 Some((rb, handle))
174 }
175
176 pub fn get(&self, handle: RigidBodyHandle) -> Option<&RigidBody> {
178 self.bodies.get(handle.0)
179 }
180
181 #[cfg(not(feature = "dev-remove-slow-accessors"))]
183 pub fn get_mut(&mut self, handle: RigidBodyHandle) -> Option<&mut RigidBody> {
184 let result = self.bodies.get_mut(handle.0)?;
185 self.modified_bodies.push_once(handle, result);
186 Some(result)
187 }
188
189 #[cfg(not(feature = "dev-remove-slow-accessors"))]
193 pub fn get_pair_mut(
194 &mut self,
195 handle1: RigidBodyHandle,
196 handle2: RigidBodyHandle,
197 ) -> (Option<&mut RigidBody>, Option<&mut RigidBody>) {
198 if handle1 == handle2 {
199 (self.get_mut(handle1), None)
200 } else {
201 let (mut rb1, mut rb2) = self.bodies.get2_mut(handle1.0, handle2.0);
202 if let Some(rb1) = rb1.as_deref_mut() {
203 self.modified_bodies.push_once(handle1, rb1);
204 }
205 if let Some(rb2) = rb2.as_deref_mut() {
206 self.modified_bodies.push_once(handle2, rb2);
207 }
208 (rb1, rb2)
209 }
210 }
211
212 pub(crate) fn get_mut_internal(&mut self, handle: RigidBodyHandle) -> Option<&mut RigidBody> {
213 self.bodies.get_mut(handle.0)
214 }
215
216 pub(crate) fn index_mut_internal(&mut self, handle: RigidBodyHandle) -> &mut RigidBody {
217 &mut self.bodies[handle.0]
218 }
219
220 pub(crate) fn get_mut_internal_with_modification_tracking(
223 &mut self,
224 handle: RigidBodyHandle,
225 ) -> Option<&mut RigidBody> {
226 let result = self.bodies.get_mut(handle.0)?;
227 self.modified_bodies.push_once(handle, result);
228 Some(result)
229 }
230
231 pub fn iter(&self) -> impl Iterator<Item = (RigidBodyHandle, &RigidBody)> {
233 self.bodies.iter().map(|(h, b)| (RigidBodyHandle(h), b))
234 }
235
236 #[cfg(not(feature = "dev-remove-slow-accessors"))]
238 pub fn iter_mut(&mut self) -> impl Iterator<Item = (RigidBodyHandle, &mut RigidBody)> {
239 self.modified_bodies.clear();
240 let modified_bodies = &mut self.modified_bodies;
241 self.bodies.iter_mut().map(move |(h, b)| {
242 modified_bodies.push_unchecked(RigidBodyHandle(h), b);
245 (RigidBodyHandle(h), b)
246 })
247 }
248
249 pub fn propagate_modified_body_positions_to_colliders(&self, colliders: &mut ColliderSet) {
257 for body in self.modified_bodies.iter().filter_map(|h| self.get(*h)) {
258 if body.changes.contains(RigidBodyChanges::POSITION) {
259 for handle in body.colliders() {
260 if let Some(collider) = colliders.get_mut(*handle) {
261 let new_pos = body.position() * collider.position_wrt_parent().unwrap();
262 collider.set_position(new_pos);
263 }
264 }
265 }
266 }
267 }
268}
269
270impl Index<RigidBodyHandle> for RigidBodySet {
271 type Output = RigidBody;
272
273 fn index(&self, index: RigidBodyHandle) -> &RigidBody {
274 &self.bodies[index.0]
275 }
276}
277
278impl Index<crate::data::Index> for RigidBodySet {
279 type Output = RigidBody;
280
281 fn index(&self, index: crate::data::Index) -> &RigidBody {
282 &self.bodies[index]
283 }
284}
285
286#[cfg(not(feature = "dev-remove-slow-accessors"))]
287impl IndexMut<RigidBodyHandle> for RigidBodySet {
288 fn index_mut(&mut self, handle: RigidBodyHandle) -> &mut RigidBody {
289 let rb = &mut self.bodies[handle.0];
290 self.modified_bodies.push_once(handle, rb);
291 rb
292 }
293}