use crate::{
owner::Owner,
traits::{Class, UserData},
};
use std::marker::PhantomData;
use enumflags2::{bitflags, BitFlags};
use physx_sys::{
PxCombineMode,
PxMaterialFlags,
PxMaterial_acquireReference_mut,
PxMaterial_getDynamicFriction,
PxMaterial_getFlags,
PxMaterial_getFrictionCombineMode,
PxMaterial_getReferenceCount,
PxMaterial_getRestitution,
PxMaterial_getRestitutionCombineMode,
PxMaterial_getStaticFriction,
PxMaterial_release_mut,
PxMaterial_setDynamicFriction_mut,
PxMaterial_setFlag_mut,
PxMaterial_setFlags_mut,
PxMaterial_setFrictionCombineMode_mut,
PxMaterial_setRestitutionCombineMode_mut,
PxMaterial_setRestitution_mut,
PxMaterial_setStaticFriction_mut,
};
#[bitflags]
#[derive(Copy, Clone, Debug)]
#[repr(u16)]
pub enum MaterialFlag {
DisableFriction = 1 << 0,
DisableStrongFriction = 1 << 1,
ImprovedPatchFriction = 1 << 2,
}
pub type MaterialFlags = BitFlags<MaterialFlag>;
#[derive(Copy, Clone, Debug)]
#[repr(u32)]
pub enum CombineMode {
Average = 0,
Min = 1,
Multiply = 2,
Max = 3,
}
impl From<PxCombineMode::Enum> for CombineMode {
fn from(mode: PxCombineMode::Enum) -> Self {
match mode {
PxCombineMode::eAVERAGE => CombineMode::Average,
PxCombineMode::eMIN => CombineMode::Min,
PxCombineMode::eMULTIPLY => CombineMode::Multiply,
PxCombineMode::eMAX => CombineMode::Max,
_ => unreachable!("Invalid enum variant: {:?}.", mode),
}
}
}
#[repr(transparent)]
pub struct PxMaterial<U> {
pub(crate) obj: physx_sys::PxMaterial,
phantom_user_data: PhantomData<U>,
}
unsafe impl<U> UserData for PxMaterial<U> {
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> Drop for PxMaterial<U> {
fn drop(&mut self) {
unsafe {
PxMaterial_release_mut(self.as_mut_ptr());
}
}
}
unsafe impl<P, U> Class<P> for PxMaterial<U>
where
physx_sys::PxMaterial: Class<P>,
{
fn as_ptr(&self) -> *const P {
self.obj.as_ptr()
}
fn as_mut_ptr(&mut self) -> *mut P {
self.obj.as_mut_ptr()
}
}
unsafe impl<U: Send> Send for PxMaterial<U> {}
unsafe impl<U: Sync> Sync for PxMaterial<U> {}
impl<M> Material for PxMaterial<M> {}
pub trait Material: Class<physx_sys::PxMaterial> + UserData {
unsafe fn from_raw(
ptr: *mut physx_sys::PxMaterial,
user_data: Self::UserData,
) -> Option<Owner<Self>> {
Owner::from_raw((ptr as *mut Self).as_mut()?.init_user_data(user_data))
}
#[inline]
fn get_user_data(&self) -> &Self::UserData {
unsafe { UserData::get_user_data(self) }
}
#[inline]
fn get_user_data_mut(&mut self) -> &mut Self::UserData {
unsafe { UserData::get_user_data_mut(self) }
}
#[inline]
fn get_reference_count(&self) -> u32 {
unsafe { PxMaterial_getReferenceCount(self.as_ptr()) }
}
#[inline]
fn acquire_reference(&mut self) {
unsafe { PxMaterial_acquireReference_mut(self.as_mut_ptr()) }
}
#[inline]
fn set_dynamic_friction(&mut self, mut coefficient: f32) {
if coefficient.is_sign_negative() {
coefficient = 0.0;
}
unsafe {
PxMaterial_setDynamicFriction_mut(self.as_mut_ptr(), coefficient);
}
}
#[inline]
fn get_dynamic_friction(&self) -> f32 {
unsafe { PxMaterial_getDynamicFriction(self.as_ptr()) }
}
#[inline]
fn set_static_friction(&mut self, mut coefficient: f32) {
if coefficient.is_sign_negative() {
coefficient = 0.0;
}
unsafe {
PxMaterial_setStaticFriction_mut(self.as_mut_ptr(), coefficient);
}
}
#[inline]
fn get_static_friction(&self) -> f32 {
unsafe { PxMaterial_getStaticFriction(self.as_ptr()) }
}
#[inline]
fn set_restitution(&mut self, mut restitution: f32) {
if restitution.is_sign_negative() {
restitution = 0.0;
} else if restitution > 1.0 {
restitution = 1.0
};
unsafe {
PxMaterial_setRestitution_mut(self.as_mut_ptr(), restitution);
}
}
#[inline]
fn get_restitution(&self) -> f32 {
unsafe { PxMaterial_getRestitution(self.as_ptr()) }
}
#[inline]
fn set_flag(&mut self, flag: MaterialFlag, set: bool) {
unsafe { PxMaterial_setFlag_mut(self.as_mut_ptr(), flag as _, set) }
}
#[inline]
fn set_flags(&mut self, flags: MaterialFlags) {
unsafe {
PxMaterial_setFlags_mut(
self.as_mut_ptr(),
PxMaterialFlags {
mBits: flags.bits(),
},
);
}
}
#[inline]
fn get_flags(&self) -> MaterialFlags {
unsafe {
let PxMaterialFlags { mBits } = PxMaterial_getFlags(self.as_ptr());
BitFlags::from_bits_unchecked(mBits)
}
}
#[inline]
fn set_friction_combined_mode(&mut self, combine_mode: CombineMode) {
unsafe {
PxMaterial_setFrictionCombineMode_mut(self.as_mut_ptr(), combine_mode as _);
}
}
#[inline]
fn get_friction_combine_mode(&self) -> CombineMode {
let combine_mode = unsafe { PxMaterial_getFrictionCombineMode(self.as_ptr()) };
debug_assert!(combine_mode < PxCombineMode::eN_VALUES);
combine_mode.into()
}
#[inline]
fn set_restitution_combine_mode(&mut self, combine_mode: CombineMode) {
unsafe {
PxMaterial_setRestitutionCombineMode_mut(self.as_mut_ptr(), combine_mode as _);
}
}
#[inline]
fn get_restitution_combine_mode(&self) -> CombineMode {
let combine_mode = unsafe { PxMaterial_getRestitutionCombineMode(self.as_ptr()) };
debug_assert!(combine_mode < PxCombineMode::eN_VALUES);
combine_mode.into()
}
}