physxx 0.3.1

Wrapper around the PhysX C++ API that aims to preserve the original API as much as possible.
Documentation
use std::{ffi::c_void, ptr::null_mut};

use glam::Vec3;
use serde::{Deserialize, Serialize};

use crate::{
    to_glam_vec3, AsPxBase, PxBaseRef, PxPhysicsRef, PxRigidActorRef, PxTransform, PxUserData,
};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PxConstraintRef(pub(crate) *mut physx_sys::PxConstraint);
impl PxConstraintRef {
    pub fn get_external_reference(&self) -> PxBaseRef {
        unsafe {
            let mut type_id: u32 = 0;
            PxBaseRef(physx_sys::PxConstraint_getExternalReference_mut(
                self.0,
                &mut type_id as *mut u32,
            ) as _)
        }
    }
    pub fn get_actors(&self) -> (PxRigidActorRef, PxRigidActorRef) {
        unsafe {
            let mut actor0 = null_mut();
            let mut actor1 = null_mut();
            physx_sys::PxConstraint_getActors(self.0, &mut actor0 as _, &mut actor1 as _);
            (PxRigidActorRef(actor0), PxRigidActorRef(actor1))
        }
    }
    pub fn set_actors(&self, actor0: PxRigidActorRef, actor1: PxRigidActorRef) {
        unsafe { physx_sys::PxConstraint_setActors_mut(self.0, actor0.0, actor1.0) }
    }
    pub fn get_force(&self, linear: &mut Vec3, angular: &mut Vec3) {
        unsafe {
            let mut l = physx_sys::PxVec3_new();
            let mut a = physx_sys::PxVec3_new();
            physx_sys::PxConstraint_getForce(
                self.0,
                &mut l as *mut physx_sys::PxVec3,
                &mut a as *mut physx_sys::PxVec3,
            );
            *linear = to_glam_vec3(&l);
            *angular = to_glam_vec3(&a);
        }
    }
    pub fn release(self) {
        unsafe { physx_sys::PxConstraint_release_mut(self.0) }
    }
}
impl AsPxBase for PxConstraintRef {
    fn as_base(&self) -> PxBaseRef {
        PxBaseRef(self.0 as _)
    }
}
unsafe impl Sync for PxConstraintRef {}
unsafe impl Send for PxConstraintRef {}

bitflags! {
    pub struct PxConstraintFlags: u32 {
        const BROKEN = physx_sys::PxConstraintFlag::eBROKEN;
        const COLLISION_ENABLED = physx_sys::PxConstraintFlag::eCOLLISION_ENABLED;
        const DISABLE_PREPROCESSING = physx_sys::PxConstraintFlag::eDISABLE_PREPROCESSING;
        const DRIVE_LIMITS_ARE_FORCES = physx_sys::PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES;
        const ENABLE_EXTENDED_LIMITS = physx_sys::PxConstraintFlag::eENABLE_EXTENDED_LIMITS;
        const GPU_COMPATIBLE = physx_sys::PxConstraintFlag::eGPU_COMPATIBLE;
        const IMPROVED_SLERP = physx_sys::PxConstraintFlag::eIMPROVED_SLERP;
        const PROJECTION = physx_sys::PxConstraintFlag::ePROJECTION;
        const PROJECT_TO_ACTOR0 = physx_sys::PxConstraintFlag::ePROJECT_TO_ACTOR0;
        const PROJECT_TO_ACTOR1 = physx_sys::PxConstraintFlag::ePROJECT_TO_ACTOR1;
        const VISUALIZATION = physx_sys::PxConstraintFlag::eVISUALIZATION;
    }
}

pub trait AsPxJoint: Sync + Send {
    fn as_joint(&self) -> PxJointRef;
}
pub trait PxJoint: Sync + Send {
    fn set_break_force(&self, force: f32, torque: f32);
    fn get_constraint(&self) -> PxConstraintRef;
    fn get_constraint_flags(&self) -> PxConstraintFlags;
    fn set_constraint_flags(&self, flags: PxConstraintFlags);
    fn set_constraint_flag(&self, flag: PxConstraintFlags, value: bool);
    fn get_local_pose(&self, actor: u32) -> PxTransform;
    fn set_local_pose(&self, actor: u32, local_pose: &PxTransform);
    fn get_actors(&self) -> (Option<PxRigidActorRef>, Option<PxRigidActorRef>);
    fn set_actors(&self, actor0: Option<PxRigidActorRef>, actor1: Option<PxRigidActorRef>);
    fn release(self);
}
impl<T: AsPxJoint> PxJoint for T {
    fn set_break_force(&self, force: f32, torque: f32) {
        unsafe {
            physx_sys::PxJoint_setBreakForce_mut(self.as_joint().0, force, torque);
        }
    }
    fn get_constraint(&self) -> PxConstraintRef {
        PxConstraintRef(unsafe { physx_sys::PxJoint_getConstraint(self.as_joint().0) })
    }
    fn get_constraint_flags(&self) -> PxConstraintFlags {
        PxConstraintFlags::from_bits(
            unsafe { physx_sys::PxJoint_getConstraintFlags(self.as_joint().0) }.mBits as u32,
        )
        .unwrap()
    }
    fn set_constraint_flags(&self, flags: PxConstraintFlags) {
        unsafe {
            physx_sys::PxJoint_setConstraintFlags_mut(
                self.as_joint().0,
                physx_sys::PxConstraintFlags {
                    mBits: flags.bits as u16,
                },
            )
        }
    }
    fn set_constraint_flag(&self, flag: PxConstraintFlags, value: bool) {
        unsafe { physx_sys::PxJoint_setConstraintFlag_mut(self.as_joint().0, flag.bits, value) }
    }
    fn get_local_pose(&self, actor: u32) -> PxTransform {
        unsafe { PxTransform(physx_sys::PxJoint_getLocalPose(self.as_joint().0, actor)) }
    }
    fn set_local_pose(&self, actor: u32, local_pose: &PxTransform) {
        unsafe { physx_sys::PxJoint_setLocalPose_mut(self.as_joint().0, actor, &local_pose.0) }
    }
    fn get_actors(&self) -> (Option<PxRigidActorRef>, Option<PxRigidActorRef>) {
        unsafe {
            let mut actor0: *mut physx_sys::PxRigidActor = null_mut();
            let mut actor1: *mut physx_sys::PxRigidActor = null_mut();
            physx_sys::PxJoint_getActors(self.as_joint().0, &mut actor0 as _, &mut actor1 as _);
            let a0 = if actor0.is_null() {
                None
            } else {
                Some(PxRigidActorRef(actor0))
            };
            let a1 = if actor1.is_null() {
                None
            } else {
                Some(PxRigidActorRef(actor1))
            };
            (a0, a1)
        }
    }
    fn set_actors(&self, actor0: Option<PxRigidActorRef>, actor1: Option<PxRigidActorRef>) {
        unsafe {
            physx_sys::PxJoint_setActors_mut(
                self.as_joint().0,
                actor0.map(|x| x.0).unwrap_or(null_mut()),
                actor1.map(|x| x.0).unwrap_or(null_mut()),
            )
        }
    }
    fn release(self) {
        unsafe { physx_sys::PxJoint_release_mut(self.as_joint().0) }
    }
}
impl<T: AsPxJoint + 'static> PxUserData for T {
    fn raw_user_data_mut(&self) -> &mut *mut c_void {
        unsafe { &mut (*self.as_joint().0).userData }
    }
    fn raw_user_data(&self) -> &*mut c_void {
        unsafe { &(*self.as_joint().0).userData }
    }
}

#[derive(Clone, Copy, Debug)]
pub struct PxJointRef(pub *mut physx_sys::PxJoint);
impl AsPxBase for PxJointRef {
    fn as_base(&self) -> PxBaseRef {
        PxBaseRef(self.0 as _)
    }
}
impl AsPxJoint for PxJointRef {
    fn as_joint(&self) -> PxJointRef {
        PxJointRef(self.0)
    }
}
unsafe impl Sync for PxJointRef {}
unsafe impl Send for PxJointRef {}

#[derive(Debug, Clone, Copy)]
pub struct PxFixedJointRef(pub(crate) *mut physx_sys::PxFixedJoint);
impl PxFixedJointRef {
    pub fn new(
        physics: PxPhysicsRef,
        actor0: Option<PxRigidActorRef>,
        local_frame_0: &PxTransform,
        actor1: Option<PxRigidActorRef>,
        local_frame_1: &PxTransform,
    ) -> Self {
        Self(unsafe {
            physx_sys::phys_PxFixedJointCreate(
                physics.0,
                actor0.map_or(null_mut(), |v| v.0),
                &local_frame_0.0,
                actor1.map_or(null_mut(), |v| v.0),
                &local_frame_1.0,
            )
        })
    }
}
impl AsPxBase for PxFixedJointRef {
    fn as_base(&self) -> PxBaseRef {
        PxBaseRef(self.0 as _)
    }
}
impl AsPxJoint for PxFixedJointRef {
    fn as_joint(&self) -> PxJointRef {
        PxJointRef(self.0 as _)
    }
}
unsafe impl Sync for PxFixedJointRef {}
unsafe impl Send for PxFixedJointRef {}

bitflags! {
    #[derive(Serialize, Deserialize)]
    pub struct PxRevoluteJointFlag: u32 {
        const DRIVE_ENABLED = physx_sys::PxRevoluteJointFlag::eDRIVE_ENABLED;
        const DRIVE_FREESPIN = physx_sys::PxRevoluteJointFlag::eDRIVE_FREESPIN;
        const LIMIT_ENABLED = physx_sys::PxRevoluteJointFlag::eLIMIT_ENABLED;
    }
}

#[derive(Debug, Clone, Copy)]
pub struct PxRevoluteJointRef(pub(crate) *mut physx_sys::PxRevoluteJoint);
impl PxRevoluteJointRef {
    pub fn new(
        physics: PxPhysicsRef,
        actor0: Option<PxRigidActorRef>,
        local_frame_0: &PxTransform,
        actor1: Option<PxRigidActorRef>,
        local_frame_1: &PxTransform,
    ) -> Self {
        Self(unsafe {
            physx_sys::phys_PxRevoluteJointCreate(
                physics.0,
                actor0.map_or(null_mut(), |v| v.0),
                &local_frame_0.0,
                actor1.map_or(null_mut(), |v| v.0),
                &local_frame_1.0,
            )
        })
    }
    pub fn set_drive_velocity(&self, velocity: f32, autoawake: bool) {
        unsafe { physx_sys::PxRevoluteJoint_setDriveVelocity_mut(self.0, velocity, autoawake) }
    }
    pub fn get_revolute_flags(&self) -> PxRevoluteJointFlag {
        PxRevoluteJointFlag::from_bits(
            unsafe { physx_sys::PxRevoluteJoint_getRevoluteJointFlags(self.0) }.mBits as u32,
        )
        .unwrap()
    }
    pub fn set_revolute_flags(&self, flags: PxRevoluteJointFlag) {
        unsafe {
            physx_sys::PxRevoluteJoint_setRevoluteJointFlags_mut(
                self.0,
                physx_sys::PxRevoluteJointFlags {
                    mBits: flags.bits() as _,
                },
            )
        }
    }
    pub fn set_revolute_flag(&self, flag: PxRevoluteJointFlag, value: bool) {
        unsafe {
            physx_sys::PxRevoluteJoint_setRevoluteJointFlag_mut(self.0, flag.bits() as _, value)
        }
    }
    pub fn get_limit(&self) -> PxJointAngularLimitPair {
        PxJointAngularLimitPair::from_physx(unsafe { physx_sys::PxRevoluteJoint_getLimit(self.0) })
    }
    pub fn set_limit(&self, limits: &PxJointAngularLimitPair) {
        unsafe { physx_sys::PxRevoluteJoint_setLimit_mut(self.0, &limits.to_physx() as _) }
    }
}
impl AsPxBase for PxRevoluteJointRef {
    fn as_base(&self) -> PxBaseRef {
        PxBaseRef(self.0 as _)
    }
}
impl AsPxJoint for PxRevoluteJointRef {
    fn as_joint(&self) -> PxJointRef {
        PxJointRef(self.0 as _)
    }
}
unsafe impl Sync for PxRevoluteJointRef {}
unsafe impl Send for PxRevoluteJointRef {}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PxJointAngularLimitPair {
    pub restitution: f32,
    pub bounce_threshold: f32,
    pub stiffness: f32,
    pub damping: f32,
    pub contact_distance: f32,
    pub upper: f32,
    pub lower: f32,
}
impl PxJointAngularLimitPair {
    pub fn new(lower_limit: f32, upper_limit: f32, contact_dist: f32) -> Self {
        Self::from_physx(unsafe {
            physx_sys::PxJointAngularLimitPair_new(lower_limit, upper_limit, contact_dist)
        })
    }
    fn from_physx(limit: physx_sys::PxJointAngularLimitPair) -> Self {
        Self {
            restitution: limit.restitution,
            bounce_threshold: limit.bounceThreshold,
            stiffness: limit.stiffness,
            damping: limit.damping,
            contact_distance: limit.contactDistance,
            upper: limit.upper,
            lower: limit.lower,
        }
    }
    fn to_physx(&self) -> physx_sys::PxJointAngularLimitPair {
        physx_sys::PxJointAngularLimitPair {
            restitution: self.restitution,
            bounceThreshold: self.bounce_threshold,
            stiffness: self.stiffness,
            damping: self.damping,
            contactDistance: self.contact_distance,
            upper: self.upper,
            lower: self.lower,
        }
    }
}