#![allow(non_upper_case_globals)]
use crate::{
material::Material,
owner::Owner,
traits::{Class, UserData},
};
use std::{marker::PhantomData, ptr::drop_in_place};
#[rustfmt::skip]
use physx_sys::{
PxFilterData,
PxFilterData_new_1,
PxShape_getMaterials,
PxShape_getNbMaterials,
PxShape_getQueryFilterData,
PxShape_getSimulationFilterData,
PxShape_setFlag_mut,
PxShape_setFlags_mut,
PxShape_setQueryFilterData_mut,
PxShape_setSimulationFilterData_mut,
};
bitflags::bitflags! {
#[repr(transparent)]
pub struct CollisionLayers: u32 {
const Ghost = 1 << 0;
const Terrain = 1 << 1;
const Static = 1 << 2;
const Character = 1 << 3;
}
}
pub use physx_sys::{PxShapeFlag as ShapeFlag, PxShapeFlags as ShapeFlags};
#[repr(transparent)]
pub struct PxShape<U, M: Material> {
pub(crate) obj: physx_sys::PxShape,
phantom_user_data: PhantomData<(U, M)>,
}
unsafe impl<U, M: Material> UserData for PxShape<U, M> {
type UserData = U;
fn user_data_ptr(&self) -> &*mut std::ffi::c_void {
&self.obj.userData
}
fn user_data_ptr_mut(&mut self) -> &mut *mut std::ffi::c_void {
&mut self.obj.userData
}
}
impl<U, M: Material> Drop for PxShape<U, M> {
fn drop(&mut self) {
unsafe {
for material in self.get_materials_mut() {
drop_in_place(material as *mut _);
}
drop_in_place(self.get_user_data_mut());
use crate::base::RefCounted;
self.release();
}
}
}
unsafe impl<S, U, M: Material> Class<S> for PxShape<U, M>
where
physx_sys::PxShape: Class<S>,
{
fn as_ptr(&self) -> *const S {
self.obj.as_ptr()
}
fn as_mut_ptr(&mut self) -> *mut S {
self.obj.as_mut_ptr()
}
}
unsafe impl<U: Send, M: Material + Send> Send for PxShape<U, M> {}
unsafe impl<U: Sync, M: Material + Send> Sync for PxShape<U, M> {}
impl<U, M: Material> Shape for PxShape<U, M> {
type Material = M;
}
pub trait Shape: Class<physx_sys::PxShape> + UserData {
type Material: Material;
unsafe fn from_raw(
ptr: *mut physx_sys::PxShape,
user_data: Self::UserData,
) -> Option<Owner<Self>> {
unsafe {
let shape = (ptr as *mut Self).as_mut();
Owner::from_raw(shape?.init_user_data(user_data))
}
}
fn get_user_data(&self) -> &Self::UserData {
unsafe { UserData::get_user_data(self) }
}
fn get_user_data_mut(&mut self) -> &mut Self::UserData {
unsafe { UserData::get_user_data_mut(self) }
}
fn set_simulation_filter_data(
&mut self,
this_layers: CollisionLayers,
other_layers: CollisionLayers,
word3: u32,
word4: u32,
) {
let mut data = unsafe { PxFilterData_new_1() };
data.word0 = this_layers.bits();
data.word1 = other_layers.bits();
data.word2 = word3;
data.word3 = word4;
unsafe { PxShape_setSimulationFilterData_mut(self.as_mut_ptr(), &data) }
}
fn get_simulation_filter_data(&self) -> PxFilterData {
unsafe { PxShape_getSimulationFilterData(self.as_ptr()) }
}
fn set_query_filter_data(&mut self, this_layers: CollisionLayers) {
let mut data = unsafe { PxFilterData_new_1() };
data.word0 = this_layers.bits();
data.word1 = 0;
data.word2 = 0;
data.word3 = 0;
unsafe { PxShape_setQueryFilterData_mut(self.as_mut_ptr(), &data) }
}
fn get_query_filter_data(&self) -> PxFilterData {
unsafe { PxShape_getQueryFilterData(self.as_ptr()) }
}
fn get_nb_materials(&self) -> u16 {
unsafe { PxShape_getNbMaterials(self.as_ptr()) }
}
fn get_materials(&self) -> Vec<&Self::Material> {
unsafe {
let capacity = self.get_nb_materials();
let mut buffer: Vec<&Self::Material> = Vec::with_capacity(capacity as usize);
let len = PxShape_getMaterials(
self.as_ptr(),
buffer.as_mut_ptr() as *mut *mut _,
capacity as u32,
0,
);
buffer.set_len(len as usize);
buffer
}
}
fn get_materials_mut(&mut self) -> Vec<&mut Self::Material> {
unsafe {
let capacity = self.get_nb_materials();
let mut buffer: Vec<&mut Self::Material> = Vec::with_capacity(capacity as usize);
let len = PxShape_getMaterials(
self.as_ptr(),
buffer.as_mut_ptr() as *mut *mut _,
capacity as u32,
0,
);
buffer.set_len(len as usize);
buffer
}
}
fn set_flag(&mut self, flag: ShapeFlag, enable: bool) {
unsafe { PxShape_setFlag_mut(self.as_mut_ptr(), flag, enable) }
}
fn set_flags(&mut self, flags: ShapeFlags) {
unsafe { PxShape_setFlags_mut(self.as_mut_ptr(), flags) }
}
}