use super::{aabb::Aabb, Shared};
use crate::object::Object;
use alloc::{sync::Arc, vec::Vec};
use bvh_arena::Bvh;
use delegate::delegate;
use spin::RwLock;
pub struct Set<O> {
pub(crate) objects: Vec<Shared<O>>,
pub(crate) partition: Bvh<Shared<O>, Aabb>,
}
impl<O> Default for Set<O> {
fn default() -> Self {
Self {
objects: Default::default(),
partition: Default::default(),
}
}
}
impl<O> Set<O> {
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
objects: Vec::with_capacity(capacity),
partition: Bvh::default(),
}
}
delegate! {
to self.objects {
pub fn len(&self) -> usize;
pub fn is_empty(&self) -> bool;
pub fn reserve(&mut self, additional: usize);
pub fn reserve_exact(&mut self, additional: usize);
pub fn shrink_to_fit(&mut self);
pub fn shrink_to(&mut self, min_capacity: usize);
pub fn iter(&self) -> impl Iterator<Item = &Arc<RwLock<O>>>;
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Arc<RwLock<O>>>;
}
}
pub fn store(&mut self, object: Shared<O>) {
self.objects.push(object);
}
pub fn quick_remove(&mut self, object: &Shared<O>) -> bool {
for (index, value) in self.objects.iter().enumerate() {
if Arc::ptr_eq(object, value) {
self.objects.swap_remove(index);
return true;
}
}
false
}
#[inline]
pub fn quick_reset(&mut self) {
self.partition.clear();
}
}
impl<O> Set<O>
where
O: Object,
{
pub fn add(&mut self, object: Shared<O>) {
self.objects.push(object.clone());
let mut mut_obj = object.write();
let handle = self.partition.insert(object.clone(), mut_obj.aabb());
mut_obj.set_handle(handle);
}
pub fn clean_remove(&mut self, object: &Shared<O>) -> bool {
for (index, value) in self.objects.iter().enumerate() {
if Arc::ptr_eq(object, value) {
self.objects.swap_remove(index);
let mut mut_obj = object.write();
let handle = mut_obj.handle();
mut_obj.unset_handle();
if let Some(handle) = handle {
self.partition.remove(handle);
}
return true;
}
}
false
}
pub fn repartition(&mut self) {
self.partition.clear();
for object in &self.objects {
let mut mut_obj = object.write();
let handle = self.partition.insert(object.clone(), mut_obj.aabb());
mut_obj.set_handle(handle);
}
}
#[inline]
pub fn query(&self, aabb: &Aabb, on_overlap: impl FnMut(&Shared<O>)) {
self.partition.for_each_overlaps(aabb, on_overlap);
}
}