use generational_arena::Arena;
use std::hash::Hash;
use crate::object::{Body, DefaultColliderHandle, Multibody, RigidBody};
use crate::world::GeometricalWorld;
use na::RealField;
pub trait BodyHandle: Copy + Hash + PartialEq + Eq + 'static + Send + Sync {}
impl<T: Copy + Hash + PartialEq + Eq + 'static + Send + Sync> BodyHandle for T {}
pub trait BodySet<N: RealField + Copy> {
type Handle: BodyHandle;
fn get(&self, handle: Self::Handle) -> Option<&dyn Body<N>>;
fn get_mut(&mut self, handle: Self::Handle) -> Option<&mut dyn Body<N>>;
fn get_pair(
&self,
handle1: Self::Handle,
handle2: Self::Handle,
) -> (Option<&dyn Body<N>>, Option<&dyn Body<N>>) {
(self.get(handle1), self.get(handle2))
}
fn contains(&self, handle: Self::Handle) -> bool;
fn foreach(&self, f: &mut dyn FnMut(Self::Handle, &dyn Body<N>));
fn foreach_mut(&mut self, f: &mut dyn FnMut(Self::Handle, &mut dyn Body<N>));
fn pop_removal_event(&mut self) -> Option<Self::Handle>;
}
pub struct DefaultBodySet<N: RealField + Copy> {
bodies: Arena<Box<dyn Body<N>>>,
removed: Vec<DefaultBodyHandle>,
}
impl<N: RealField + Copy> DefaultBodySet<N> {
pub fn new() -> Self {
DefaultBodySet {
bodies: Arena::new(),
removed: Vec::new(),
}
}
pub fn insert(&mut self, body: impl Body<N>) -> DefaultBodyHandle {
self.bodies.insert(Box::new(body))
}
pub fn insert_boxed(&mut self, body: Box<dyn Body<N>>) -> DefaultBodyHandle {
self.bodies.insert(body)
}
pub fn remove(&mut self, to_remove: DefaultBodyHandle) -> Option<Box<dyn Body<N>>> {
let res = self.bodies.remove(to_remove)?;
self.removed.push(to_remove);
Some(res)
}
fn contains(&self, handle: DefaultBodyHandle) -> bool {
self.bodies.contains(handle)
}
pub fn get(&self, handle: DefaultBodyHandle) -> Option<&dyn Body<N>> {
self.bodies.get(handle).map(|b| &**b)
}
pub fn get_mut(&mut self, handle: DefaultBodyHandle) -> Option<&mut dyn Body<N>> {
self.bodies.get_mut(handle).map(|b| &mut **b)
}
pub fn iter(&self) -> impl Iterator<Item = (DefaultBodyHandle, &dyn Body<N>)> {
self.bodies.iter().map(|b| (b.0, &**b.1))
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (DefaultBodyHandle, &mut dyn Body<N>)> {
self.bodies.iter_mut().map(|b| (b.0, &mut **b.1))
}
pub fn rigid_body(&self, handle: DefaultBodyHandle) -> Option<&RigidBody<N>> {
self.get(handle).and_then(|b| b.downcast_ref())
}
pub fn rigid_body_mut(&mut self, handle: DefaultBodyHandle) -> Option<&mut RigidBody<N>> {
self.get_mut(handle).and_then(|b| b.downcast_mut())
}
pub fn multibody(&self, handle: DefaultBodyHandle) -> Option<&Multibody<N>> {
self.get(handle).and_then(|b| b.downcast_ref())
}
pub fn multibody_mut(&mut self, handle: DefaultBodyHandle) -> Option<&mut Multibody<N>> {
self.get_mut(handle).and_then(|b| b.downcast_mut())
}
}
impl<N: RealField + Copy> BodySet<N> for DefaultBodySet<N> {
type Handle = DefaultBodyHandle;
fn get(&self, handle: Self::Handle) -> Option<&dyn Body<N>> {
self.get(handle)
}
fn get_mut(&mut self, handle: Self::Handle) -> Option<&mut dyn Body<N>> {
self.get_mut(handle)
}
fn contains(&self, handle: Self::Handle) -> bool {
self.contains(handle)
}
fn foreach(&self, f: &mut dyn FnMut(Self::Handle, &dyn Body<N>)) {
for (h, b) in self.iter() {
f(h, b)
}
}
fn foreach_mut(&mut self, f: &mut dyn FnMut(Self::Handle, &mut dyn Body<N>)) {
for (h, b) in self.iter_mut() {
f(h, b)
}
}
fn pop_removal_event(&mut self) -> Option<Self::Handle> {
self.removed.pop()
}
}
pub type DefaultBodyHandle = generational_arena::Index;
pub type DefaultBodyPartHandle = BodyPartHandle<DefaultBodyHandle>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct BodyPartHandle<Handle: BodyHandle>(pub Handle, pub usize);
pub trait BodyDesc<N: RealField + Copy> {
type Body: Body<N>;
fn build_with_handle(
&self,
gworld: &mut GeometricalWorld<N, DefaultBodyHandle, DefaultColliderHandle>,
handle: DefaultBodyHandle,
) -> Self::Body;
}