use crate::data::{Arena, HasModifiedFlag, ModifiedObjects};
use crate::dynamics::{
ImpulseJointSet, IslandManager, MultibodyJointSet, RigidBody, RigidBodyBuilder,
RigidBodyChanges, RigidBodyHandle,
};
use crate::geometry::ColliderSet;
use std::ops::{Index, IndexMut};
#[cfg(doc)]
use crate::pipeline::PhysicsPipeline;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct BodyPair {
pub body1: RigidBodyHandle,
pub body2: RigidBodyHandle,
}
impl BodyPair {
pub fn new(body1: RigidBodyHandle, body2: RigidBodyHandle) -> Self {
BodyPair { body1, body2 }
}
}
pub(crate) type ModifiedRigidBodies = ModifiedObjects<RigidBodyHandle, RigidBody>;
impl HasModifiedFlag for RigidBody {
#[inline]
fn has_modified_flag(&self) -> bool {
self.changes.contains(RigidBodyChanges::IN_MODIFIED_SET)
}
#[inline]
fn set_modified_flag(&mut self) {
self.changes |= RigidBodyChanges::IN_MODIFIED_SET;
}
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone, Default, Debug)]
pub struct RigidBodySet {
pub(crate) bodies: Arena<RigidBody>,
pub(crate) modified_bodies: ModifiedRigidBodies,
#[cfg_attr(feature = "serde-serialize", serde(skip))]
pub(crate) default_fixed: RigidBody,
}
impl RigidBodySet {
pub fn new() -> Self {
RigidBodySet {
bodies: Arena::new(),
modified_bodies: ModifiedObjects::default(),
default_fixed: RigidBodyBuilder::fixed().build(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
RigidBodySet {
bodies: Arena::with_capacity(capacity),
modified_bodies: ModifiedRigidBodies::with_capacity(capacity),
default_fixed: RigidBodyBuilder::fixed().build(),
}
}
pub(crate) fn take_modified(&mut self) -> ModifiedRigidBodies {
std::mem::take(&mut self.modified_bodies)
}
pub fn len(&self) -> usize {
self.bodies.len()
}
pub fn is_empty(&self) -> bool {
self.bodies.is_empty()
}
pub fn contains(&self, handle: RigidBodyHandle) -> bool {
self.bodies.contains(handle.0)
}
pub fn insert(&mut self, rb: impl Into<RigidBody>) -> RigidBodyHandle {
let mut rb = rb.into();
rb.reset_internal_references();
rb.changes.set(RigidBodyChanges::all(), true);
let handle = RigidBodyHandle(self.bodies.insert(rb));
self.modified_bodies
.push_unchecked(handle, &mut self.bodies[handle.0]);
handle
}
#[profiling::function]
pub fn remove(
&mut self,
handle: RigidBodyHandle,
islands: &mut IslandManager,
colliders: &mut ColliderSet,
impulse_joints: &mut ImpulseJointSet,
multibody_joints: &mut MultibodyJointSet,
remove_attached_colliders: bool,
) -> Option<RigidBody> {
let rb = self.bodies.remove(handle.0)?;
islands.rigid_body_removed_or_disabled(handle, &rb.ids, self);
if remove_attached_colliders {
for collider in rb.colliders() {
colliders.remove(*collider, islands, self, false);
}
} else {
let colliders_to_detach = rb.colliders().to_vec();
for co_handle in colliders_to_detach {
colliders.set_parent(co_handle, None, self);
}
}
impulse_joints.remove_joints_attached_to_rigid_body(handle);
multibody_joints.remove_joints_attached_to_rigid_body(handle);
Some(rb)
}
pub fn get_unknown_gen(&self, i: u32) -> Option<(&RigidBody, RigidBodyHandle)> {
self.bodies
.get_unknown_gen(i)
.map(|(b, h)| (b, RigidBodyHandle(h)))
}
#[cfg(not(feature = "dev-remove-slow-accessors"))]
pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut RigidBody, RigidBodyHandle)> {
let (rb, handle) = self.bodies.get_unknown_gen_mut(i)?;
let handle = RigidBodyHandle(handle);
self.modified_bodies.push_once(handle, rb);
Some((rb, handle))
}
pub fn get(&self, handle: RigidBodyHandle) -> Option<&RigidBody> {
self.bodies.get(handle.0)
}
#[cfg(not(feature = "dev-remove-slow-accessors"))]
pub fn get_mut(&mut self, handle: RigidBodyHandle) -> Option<&mut RigidBody> {
let result = self.bodies.get_mut(handle.0)?;
self.modified_bodies.push_once(handle, result);
Some(result)
}
#[cfg(not(feature = "dev-remove-slow-accessors"))]
pub fn get_pair_mut(
&mut self,
handle1: RigidBodyHandle,
handle2: RigidBodyHandle,
) -> (Option<&mut RigidBody>, Option<&mut RigidBody>) {
if handle1 == handle2 {
(self.get_mut(handle1), None)
} else {
let (mut rb1, mut rb2) = self.bodies.get2_mut(handle1.0, handle2.0);
if let Some(rb1) = rb1.as_deref_mut() {
self.modified_bodies.push_once(handle1, rb1);
}
if let Some(rb2) = rb2.as_deref_mut() {
self.modified_bodies.push_once(handle2, rb2);
}
(rb1, rb2)
}
}
pub(crate) fn get_mut_internal(&mut self, handle: RigidBodyHandle) -> Option<&mut RigidBody> {
self.bodies.get_mut(handle.0)
}
pub(crate) fn index_mut_internal(&mut self, handle: RigidBodyHandle) -> &mut RigidBody {
&mut self.bodies[handle.0]
}
pub(crate) fn get_mut_internal_with_modification_tracking(
&mut self,
handle: RigidBodyHandle,
) -> Option<&mut RigidBody> {
let result = self.bodies.get_mut(handle.0)?;
self.modified_bodies.push_once(handle, result);
Some(result)
}
pub fn iter(&self) -> impl Iterator<Item = (RigidBodyHandle, &RigidBody)> {
self.bodies.iter().map(|(h, b)| (RigidBodyHandle(h), b))
}
#[cfg(not(feature = "dev-remove-slow-accessors"))]
pub fn iter_mut(&mut self) -> impl Iterator<Item = (RigidBodyHandle, &mut RigidBody)> {
self.modified_bodies.clear();
let modified_bodies = &mut self.modified_bodies;
self.bodies.iter_mut().map(move |(h, b)| {
modified_bodies.push_unchecked(RigidBodyHandle(h), b);
(RigidBodyHandle(h), b)
})
}
pub fn propagate_modified_body_positions_to_colliders(&self, colliders: &mut ColliderSet) {
for body in self.modified_bodies.iter().filter_map(|h| self.get(*h)) {
if body.changes.contains(RigidBodyChanges::POSITION) {
for handle in body.colliders() {
if let Some(collider) = colliders.get_mut(*handle) {
let new_pos = body.position() * collider.position_wrt_parent().unwrap();
collider.set_position(new_pos);
}
}
}
}
}
}
impl Index<RigidBodyHandle> for RigidBodySet {
type Output = RigidBody;
fn index(&self, index: RigidBodyHandle) -> &RigidBody {
&self.bodies[index.0]
}
}
impl Index<crate::data::Index> for RigidBodySet {
type Output = RigidBody;
fn index(&self, index: crate::data::Index) -> &RigidBody {
&self.bodies[index]
}
}
#[cfg(not(feature = "dev-remove-slow-accessors"))]
impl IndexMut<RigidBodyHandle> for RigidBodySet {
fn index_mut(&mut self, handle: RigidBodyHandle) -> &mut RigidBody {
let rb = &mut self.bodies[handle.0];
self.modified_bodies.push_once(handle, rb);
rb
}
}