#![warn(clippy::all)]
use crate::{
geometry::Geometry,
math::PxTransform,
owner::Owner,
physics::Physics,
rigid_actor::RigidActor,
rigid_body::RigidBody,
shape::Shape,
traits::{Class, PxFlags, UserData},
};
use enumflags2::{bitflags, BitFlags};
use std::{marker::PhantomData, ptr::drop_in_place};
use physx_sys::{
phys_PxCreateDynamic, PxRigidActor_release_mut, PxRigidDynamicLockFlag,
PxRigidDynamicLockFlags, PxRigidDynamic_getContactReportThreshold,
PxRigidDynamic_getKinematicTarget, PxRigidDynamic_getRigidDynamicLockFlags,
PxRigidDynamic_getSleepThreshold, PxRigidDynamic_getSolverIterationCounts,
PxRigidDynamic_getStabilizationThreshold, PxRigidDynamic_getWakeCounter,
PxRigidDynamic_isSleeping, PxRigidDynamic_putToSleep_mut,
PxRigidDynamic_setContactReportThreshold_mut, PxRigidDynamic_setKinematicTarget_mut,
PxRigidDynamic_setRigidDynamicLockFlag_mut, PxRigidDynamic_setRigidDynamicLockFlags_mut,
PxRigidDynamic_setSleepThreshold_mut, PxRigidDynamic_setSolverIterationCounts_mut,
PxRigidDynamic_setStabilizationThreshold_mut, PxRigidDynamic_setWakeCounter_mut,
PxRigidDynamic_wakeUp_mut,
};
pub type RigidDynamicLockFlags = BitFlags<RigidDynamicLockFlag>;
impl PxFlags for RigidDynamicLockFlags {
type Target = PxRigidDynamicLockFlags;
fn into_px(self) -> Self::Target {
PxRigidDynamicLockFlags { mBits: self.bits() }
}
fn from_px(flags: Self::Target) -> Self {
unsafe { BitFlags::from_bits_unchecked(flags.mBits) }
}
}
#[bitflags]
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum RigidDynamicLockFlag {
LockLinearX = 1 << 0,
LockLinearY = 1 << 1,
LockLinearZ = 1 << 2,
LockAngularX = 1 << 3,
LockAngularY = 1 << 4,
LockAngularZ = 1 << 5,
}
impl From<RigidDynamicLockFlag> for PxRigidDynamicLockFlag::Enum {
fn from(value: RigidDynamicLockFlag) -> Self {
match value {
RigidDynamicLockFlag::LockLinearX => PxRigidDynamicLockFlag::eLOCK_LINEAR_X,
RigidDynamicLockFlag::LockLinearY => PxRigidDynamicLockFlag::eLOCK_LINEAR_Y,
RigidDynamicLockFlag::LockLinearZ => PxRigidDynamicLockFlag::eLOCK_LINEAR_Z,
RigidDynamicLockFlag::LockAngularX => PxRigidDynamicLockFlag::eLOCK_ANGULAR_X,
RigidDynamicLockFlag::LockAngularY => PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y,
RigidDynamicLockFlag::LockAngularZ => PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z,
}
}
}
impl From<PxRigidDynamicLockFlag::Enum> for RigidDynamicLockFlag {
fn from(flag: PxRigidDynamicLockFlag::Enum) -> Self {
match flag {
PxRigidDynamicLockFlag::eLOCK_LINEAR_X => RigidDynamicLockFlag::LockLinearX,
PxRigidDynamicLockFlag::eLOCK_LINEAR_Y => RigidDynamicLockFlag::LockLinearY,
PxRigidDynamicLockFlag::eLOCK_LINEAR_Z => RigidDynamicLockFlag::LockLinearZ,
PxRigidDynamicLockFlag::eLOCK_ANGULAR_X => RigidDynamicLockFlag::LockAngularX,
PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y => RigidDynamicLockFlag::LockAngularY,
PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z => RigidDynamicLockFlag::LockAngularZ,
_ => unreachable!("Invalid enum variant."),
}
}
}
#[repr(transparent)]
pub struct PxRigidDynamic<D, Geom: Shape> {
pub(crate) obj: physx_sys::PxRigidDynamic,
phantom_user_data: PhantomData<(D, Geom)>,
}
unsafe impl<U, Geom: Shape> UserData for PxRigidDynamic<U, Geom> {
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<D, Geom: Shape> Drop for PxRigidDynamic<D, Geom> {
fn drop(&mut self) {
unsafe {
drop_in_place(self.get_user_data_mut() as *mut _);
PxRigidActor_release_mut(self.as_mut_ptr());
}
}
}
unsafe impl<P, D, Geom: Shape> Class<P> for PxRigidDynamic<D, Geom>
where
physx_sys::PxRigidDynamic: 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<D: Send, Geom: Shape + Send> Send for PxRigidDynamic<D, Geom> {}
unsafe impl<D: Sync, Geom: Shape + Sync> Sync for PxRigidDynamic<D, Geom> {}
impl<D, Geom: Shape> RigidActor for PxRigidDynamic<D, Geom> {
type Shape = Geom;
}
impl<D, Geom: Shape> RigidDynamic for PxRigidDynamic<D, Geom> {}
pub trait RigidDynamic: Class<physx_sys::PxRigidDynamic> + RigidBody + UserData {
fn new(
physics: &mut impl Physics,
transform: PxTransform,
geometry: &impl Geometry,
material: &mut <Self::Shape as Shape>::Material,
density: f32,
shape_transform: PxTransform,
user_data: Self::UserData,
) -> Option<Owner<Self>> {
unsafe {
RigidDynamic::from_raw(
phys_PxCreateDynamic(
physics.as_mut_ptr(),
transform.as_ptr(),
geometry.as_ptr(),
material.as_mut_ptr(),
density,
shape_transform.as_ptr(),
),
user_data,
)
}
}
unsafe fn from_raw(
ptr: *mut physx_sys::PxRigidDynamic,
user_data: Self::UserData,
) -> Option<Owner<Self>> {
let actor = (ptr as *mut Self).as_mut();
Owner::from_raw(actor?.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 get_contact_report_threshold(&self) -> f32 {
unsafe { PxRigidDynamic_getContactReportThreshold(self.as_ptr()) }
}
fn get_kinematic_target(&self) -> Option<PxTransform> {
let mut transform = PxTransform::default();
unsafe {
if PxRigidDynamic_getKinematicTarget(self.as_ptr(), transform.as_mut_ptr()) {
Some(transform)
} else {
None
}
}
}
fn get_rigid_dynamic_lock_flags(&self) -> RigidDynamicLockFlags {
unsafe {
RigidDynamicLockFlags::from_px(PxRigidDynamic_getRigidDynamicLockFlags(self.as_ptr()))
}
}
fn get_sleep_threshold(&self) -> f32 {
unsafe { PxRigidDynamic_getSleepThreshold(self.as_ptr()) }
}
fn get_solver_iteration_counts(&self) -> (u32, u32) {
let mut pos_iters = 0;
let mut vel_iters = 0;
unsafe {
PxRigidDynamic_getSolverIterationCounts(self.as_ptr(), &mut vel_iters, &mut pos_iters);
}
(pos_iters, vel_iters)
}
fn get_stabilization_threshold(&self) -> f32 {
unsafe { PxRigidDynamic_getStabilizationThreshold(self.as_ptr()) }
}
fn get_wake_counter(&self) -> f32 {
unsafe { PxRigidDynamic_getWakeCounter(self.as_ptr()) }
}
fn is_sleeping(&self) -> bool {
unsafe { PxRigidDynamic_isSleeping(self.as_ptr()) }
}
fn put_to_sleep(&mut self) {
unsafe { PxRigidDynamic_putToSleep_mut(self.as_mut_ptr()) }
}
fn set_contact_report_threshold(&mut self, threshold: f32) {
unsafe { PxRigidDynamic_setContactReportThreshold_mut(self.as_mut_ptr(), threshold) }
}
fn set_kinematic_target(&mut self, target: &PxTransform) {
unsafe { PxRigidDynamic_setKinematicTarget_mut(self.as_mut_ptr(), target.as_ptr()) }
}
fn set_rigid_dynamic_lock_flag(&mut self, flag: RigidDynamicLockFlag, value: bool) {
unsafe { PxRigidDynamic_setRigidDynamicLockFlag_mut(self.as_mut_ptr(), flag.into(), value) }
}
fn set_rigid_dynamic_lock_flags(&mut self, flags: RigidDynamicLockFlags) {
unsafe { PxRigidDynamic_setRigidDynamicLockFlags_mut(self.as_mut_ptr(), flags.into_px()) }
}
fn set_sleep_threshold(&mut self, mut threshold: f32) {
if threshold.is_sign_negative() {
threshold = 0.0
};
unsafe { PxRigidDynamic_setSleepThreshold_mut(self.as_mut_ptr(), threshold) }
}
fn set_solver_iteration_counts(
&mut self,
min_position_iterations: u32,
min_velocity_iterations: u32,
) {
unsafe {
PxRigidDynamic_setSolverIterationCounts_mut(
self.as_mut_ptr(),
min_position_iterations,
min_velocity_iterations,
)
}
}
fn set_stabilization_threshold(&mut self, threshold: f32) {
unsafe { PxRigidDynamic_setStabilizationThreshold_mut(self.as_mut_ptr(), threshold) }
}
fn set_wake_counter(&mut self, wake_counter: f32) {
unsafe { PxRigidDynamic_setWakeCounter_mut(self.as_mut_ptr(), wake_counter) }
}
fn wake_up(&mut self) {
unsafe { PxRigidDynamic_wakeUp_mut(self.as_mut_ptr()) }
}
}