use phys_geom::shape::{Capsule, Cuboid, Cylinder};
use rustc_hash::FxHashMap;
use crate::collision_tasks::BatchesReductionContext;
use crate::{
CollisionCallBack, ComplexShapeId, ContactContext, ConvexHullId, ReductionId, Shape,
ShapeBatches, ShapeContainer, SphereIncludingPair, StandardPair, Triangle,
};
#[derive(Default, Clone)]
pub struct PluginContainer {
plugins: FxHashMap<u64, Box<dyn CollisionShapePlugin>>,
}
impl PluginContainer {
pub fn add(&mut self, plugin: impl CollisionShapePlugin) {
let plugin_id = plugin.plugin_id();
self.plugins.insert(plugin_id, Box::new(plugin));
}
#[must_use]
pub fn get_plugin(&self, id: u64) -> Option<&(dyn CollisionShapePlugin)> {
if let Some(value) = self.plugins.get(&id) {
Some(value.as_ref())
} else {
None
}
}
pub fn get_plugin_mut(&mut self, id: u64) -> Option<&mut Box<dyn CollisionShapePlugin>> {
self.plugins.get_mut(&id)
}
pub fn execute(
&self,
container: Option<&ShapeContainer>,
reduction_contex: &mut BatchesReductionContext,
callback: &mut dyn CollisionCallBack,
) {
for plugin in self.plugins.values() {
plugin.solve_collision(container, reduction_contex, callback);
}
}
pub fn clear(&mut self) {
for plugin in &mut self.plugins.values_mut() {
plugin.clear_pairs();
}
}
}
pub struct PairGenerateContext<'a> {
pub pair_id: usize,
pub shape_batches: &'a mut ShapeBatches,
pub reduction_context: &'a mut BatchesReductionContext,
pub shape: &'a Shape,
pub complex_shape_id: &'a ComplexShapeId,
pub speculative_margin: f32,
pub flip_mask: bool,
}
impl PairGenerateContext<'_> {
pub fn create_reduction_pair(&mut self) -> ReductionId {
self.reduction_context.create_reduction_pair(self.pair_id)
}
pub fn set_to_concave_reduction(&mut self, reduction_id: ReductionId) {
self.reduction_context
.set_to_concave_reduction(reduction_id);
}
pub fn record_reduction(&mut self, reduction_id: ReductionId, count: usize) {
self.reduction_context.record_reduction(reduction_id, count);
}
pub fn push_sphere_triangle(&mut self, pair: SphereIncludingPair<Triangle>) {
self.shape_batches.push_sphere_triangle(pair);
}
pub fn push_capsule_triangle(&mut self, pair: StandardPair<Capsule, Triangle>) {
self.shape_batches.push_capsule_triangle(pair);
}
pub fn push_cuboid_triangle(&mut self, pair: StandardPair<Cuboid, Triangle>) {
self.shape_batches.push_cuboid_triangle(pair);
}
pub fn push_triangle_cylinder(&mut self, pair: StandardPair<Triangle, Cylinder>) {
self.shape_batches.push_triangle_cylinder(pair);
}
pub fn push_triangle_convex_hull(&mut self, pair: StandardPair<Triangle, ConvexHullId>) {
self.shape_batches.push_triangle_convex_hull(pair);
}
}
pub trait CollisionShapePlugin: 'static + Send + Sync + dyn_clone::DynClone {
fn plugin_id(&self) -> u64;
fn clear_pairs(&mut self);
fn solve_collision(
&self,
container: Option<&ShapeContainer>,
reduction_contex: &mut BatchesReductionContext,
callback: &mut dyn CollisionCallBack,
);
fn on_pair_generate(
&mut self,
ctx: &mut PairGenerateContext,
contact_context: &ContactContext,
shapes: &ShapeContainer,
);
}
dyn_clone::clone_trait_object!(CollisionShapePlugin);
#[cfg(test)]
mod tests {
use wasm_bindgen_test::wasm_bindgen_test;
use super::{CollisionShapePlugin, PluginContainer};
#[derive(Clone)]
struct TestPlugin {
pub value: u64,
}
impl CollisionShapePlugin for TestPlugin {
fn clear_pairs(&mut self) {
self.value = 0;
}
fn on_pair_generate(
&mut self,
_ctx: &mut super::PairGenerateContext,
_contact_context: &crate::ContactContext,
_shapes: &crate::ShapeContainer,
) {
}
fn plugin_id(&self) -> u64 {
0x123456
}
fn solve_collision(
&self,
_container: Option<&crate::ShapeContainer>,
_reduction_contex: &mut crate::BatchesReductionContext,
_callback: &mut dyn crate::CollisionCallBack,
) {
}
}
#[test]
#[wasm_bindgen_test]
fn collision_plugin_test() {
let mut plugins = PluginContainer::default();
let my_plugin = TestPlugin { value: 12 };
let id = my_plugin.plugin_id();
let id_2 = 0x55454;
plugins.add(my_plugin);
{
let result = plugins.get_plugin(id);
assert!(result.is_some());
let result_2 = plugins.get_plugin(id_2);
assert!(result_2.is_none());
}
{
let result_3 = plugins.get_plugin_mut(id).unwrap();
result_3.clear_pairs();
}
}
}