use oxijolt_sys::*;
use crate::body::INVALID_BODY_ID;
use crate::{BodyId, MotionType, PhysicsWorld, StateError};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum BodySelection<'a> {
All,
Movable,
Only(&'a [BodyId]),
}
impl PhysicsWorld {
pub(super) fn select_bodies<'v>(
&self,
selection: BodySelection<'_>,
ids: &'v mut Vec<u32>,
) -> Result<Option<&'v [u32]>, StateError> {
match selection {
BodySelection::All => return Ok(None),
BodySelection::Movable => {
self.all_body_ids_into(ids);
ids.retain(|&raw| self.raw_motion_type(raw) != MotionType::Static);
}
BodySelection::Only(listed) => {
for &id in listed {
self.check(id).map_err(StateError::Body)?;
}
ids.clear();
ids.extend(listed.iter().map(|id| id.to_raw()));
ids.sort_unstable();
ids.dedup();
}
}
Ok(Some(ids))
}
pub(super) fn all_body_ids_into(&self, ids: &mut Vec<u32>) {
let count = self.body_count();
ids.clear();
ids.resize(count as usize, INVALID_BODY_ID);
if count > 0 {
unsafe { JPH_PhysicsSystem_GetBodies(self.system.as_ptr(), ids.as_mut_ptr(), count) };
}
ids.sort_unstable();
}
pub(super) fn unselected_body_ids_into(&self, selected: &[u32], ids: &mut Vec<u32>) {
self.all_body_ids_into(ids);
ids.retain(|raw| selected.binary_search(raw).is_err() && !self.inner_bodies.contains(raw));
}
pub(super) fn raw_motion_type(&self, raw: u32) -> MotionType {
MotionType::from_jph(unsafe {
JPH_BodyInterface_GetMotionType(self.body_interface.as_ptr(), raw)
})
}
}