use std::ffi::c_void;
use num_traits::FromPrimitive;
use crate::{
AsPxBase, PxBaseRef, PxGeometry, PxGeometryHolder, PxGeometryType, PxMaterial, PxPhysicsRef,
PxRigidActorRef, PxTransform, PxUserData,
};
bitflags! {
pub struct PxShapeFlag: u8 {
const SCENE_QUERY_SHAPE = physx_sys::PxShapeFlag::eSCENE_QUERY_SHAPE as u8;
const SIMULATION_SHAPE = physx_sys::PxShapeFlag::eSIMULATION_SHAPE as u8;
const TRIGGER_SHAPE = physx_sys::PxShapeFlag::eTRIGGER_SHAPE as u8;
const VISUALIZATION = physx_sys::PxShapeFlag::eVISUALIZATION as u8;
}
}
impl Default for PxShapeFlag {
fn default() -> Self {
Self::VISUALIZATION | Self::SIMULATION_SHAPE
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PxShape(pub *mut physx_sys::PxShape, pub usize);
impl PxShape {
pub fn new(
physics: PxPhysicsRef,
geometry: &dyn PxGeometry,
materials: &[&PxMaterial],
is_exclusive: Option<bool>,
shape_flags: Option<PxShapeFlag>,
) -> Self {
let mats = materials
.iter()
.map(|x| x.0)
.collect::<Vec<*mut physx_sys::PxMaterial>>();
Self(
unsafe {
physx_sys::PxPhysics_createShape_mut_1(
physics.0,
geometry.as_geometry_ptr(),
mats.as_ptr(),
materials.len() as u16,
is_exclusive.unwrap_or(false),
physx_sys::PxShapeFlags {
mBits: shape_flags.unwrap_or_default().bits,
},
)
},
0,
)
}
pub(crate) fn from_ptr(ptr: *mut physx_sys::PxShape) -> Self {
let mut s = Self(ptr, 0);
s.acquire_reference();
s
}
pub(crate) fn acquire_reference(&mut self) {
self.1 += 1;
unsafe { physx_sys::PxShape_acquireReference_mut(self.0) }
}
pub fn get_geometry(&self) -> PxGeometryHolder {
PxGeometryHolder(unsafe { physx_sys::PxShape_getGeometry(self.0) })
}
pub fn set_geometry(&self, geometry: &dyn PxGeometry) {
unsafe { physx_sys::PxShape_setGeometry_mut(self.0, geometry.as_geometry_ptr()) }
}
pub fn get_geometry_type(&self) -> PxGeometryType {
PxGeometryType::from_i32(unsafe { physx_sys::PxShape_getGeometryType(self.0) }).unwrap()
}
pub fn get_local_pose(&self) -> PxTransform {
PxTransform(unsafe { physx_sys::PxShape_getLocalPose(self.0) })
}
pub fn set_local_pose(&self, pose: &PxTransform) {
unsafe {
physx_sys::PxShape_setLocalPose_mut(self.0, &pose.0 as *const physx_sys::PxTransform)
}
}
pub fn get_global_pose(&self, actor: PxRigidActorRef) -> PxTransform {
PxTransform(unsafe { physx_sys::PxShapeExt_getGlobalPose_mut(self.0, actor.0) })
}
pub fn get_actor(&self) -> Option<PxRigidActorRef> {
unsafe {
let p = physx_sys::PxShape_getActor(self.0);
if p.is_null() {
None
} else {
Some(PxRigidActorRef(p))
}
}
}
pub fn get_flags(&self) -> PxShapeFlag {
PxShapeFlag::from_bits(unsafe { physx_sys::PxShape_getFlags(self.0) }.mBits).unwrap()
}
pub fn set_flag(&self, flag: PxShapeFlag, value: bool) {
unsafe { physx_sys::PxShape_setFlag_mut(self.0, flag.bits as u32, value) }
}
pub fn set_flags(&self, flags: PxShapeFlag) {
unsafe {
physx_sys::PxShape_setFlags_mut(self.0, physx_sys::PxShapeFlags { mBits: flags.bits })
}
}
pub fn get_contact_offset(&self) -> f32 {
unsafe { physx_sys::PxShape_getContactOffset(self.0) }
}
pub fn set_contact_offset(&self, offset: f32) {
unsafe { physx_sys::PxShape_setContactOffset_mut(self.0, offset) }
}
pub fn get_rest_offset(&self) -> f32 {
unsafe { physx_sys::PxShape_getRestOffset(self.0) }
}
pub fn set_rest_offset(&self, offset: f32) {
unsafe { physx_sys::PxShape_setRestOffset_mut(self.0, offset) }
}
}
impl AsPxBase for PxShape {
fn as_base(&self) -> PxBaseRef {
PxBaseRef(self.0 as _)
}
}
impl PxUserData for PxShape {
fn raw_user_data_mut(&self) -> &mut *mut c_void {
unsafe { &mut (*self.0).userData }
}
fn raw_user_data(&self) -> &*mut c_void {
unsafe { &(*self.0).userData }
}
}
impl Clone for PxShape {
fn clone(&self) -> Self {
Self::from_ptr(self.0)
}
}
impl Drop for PxShape {
fn drop(&mut self) {
for _ in 0..self.1 {
unsafe {
physx_sys::PxShape_release_mut(self.0);
}
}
}
}
unsafe impl Sync for PxShape {}
unsafe impl Send for PxShape {}