#![warn(clippy::all)]
use crate::{
articulation_joint_base::JointMap,
owner::Owner,
rigid_actor::RigidActor,
rigid_body::RigidBody,
shape::{Shape, ShapeFlag},
traits::{Class, UserData},
};
use std::{marker::PhantomData, ptr::drop_in_place};
use physx_sys::{
PxArticulationDriveType,
PxArticulationLink_getChildren,
PxArticulationLink_getInboundJoint,
PxArticulationLink_getInboundJointDof,
PxArticulationLink_getLinkIndex,
PxArticulationLink_getNbChildren,
PxArticulationLink_release_mut,
};
#[derive(Debug, Clone, Copy)]
pub enum ArticulationDriveType {
Acceleration,
Force,
}
impl From<ArticulationDriveType> for PxArticulationDriveType::Enum {
fn from(value: ArticulationDriveType) -> Self {
match value {
ArticulationDriveType::Acceleration => PxArticulationDriveType::eACCELERATION,
ArticulationDriveType::Force => PxArticulationDriveType::eFORCE,
}
}
}
#[repr(transparent)]
pub struct PxArticulationLink<L, Geom: Shape> {
pub(crate) obj: physx_sys::PxArticulationLink,
phantom_user_data: PhantomData<(L, Geom)>,
}
unsafe impl<L, Geom: Shape> UserData for PxArticulationLink<L, Geom> {
type UserData = L;
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<L, Geom: Shape> Drop for PxArticulationLink<L, Geom> {
fn drop(&mut self) {
unsafe {
drop_in_place(self.get_user_data_mut() as *mut _);
PxArticulationLink_release_mut(self.as_mut_ptr());
}
}
}
unsafe impl<P, L, Geom: Shape> Class<P> for PxArticulationLink<L, Geom>
where
physx_sys::PxArticulationLink: 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<L: Send, Geom: Shape + Send> Send for PxArticulationLink<L, Geom> {}
unsafe impl<L: Sync, Geom: Shape + Sync> Sync for PxArticulationLink<L, Geom> {}
impl<L, Geom: Shape> RigidActor for PxArticulationLink<L, Geom> {
type Shape = Geom;
}
impl<L, Geom: Shape> ArticulationLink for PxArticulationLink<L, Geom> {}
pub trait ArticulationLink: Class<physx_sys::PxArticulationLink> + RigidBody + UserData {
unsafe fn from_raw(
ptr: *mut physx_sys::PxArticulationLink,
user_data: Self::UserData,
) -> Option<Owner<Self>> {
Owner::from_raw((ptr as *mut Self).as_mut()?.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 enable_collision(&mut self, enable: bool) {
for shape in self.get_shapes_mut() {
shape.set_flag(ShapeFlag::SimulationShape, enable);
}
}
fn get_inbound_joint(&self) -> Option<&JointMap> {
unsafe {
(&PxArticulationLink_getInboundJoint(self.as_ptr())
as *const *mut physx_sys::PxArticulationJointBase as *const JointMap)
.as_ref()
}
}
fn get_link_index(&self) -> u32 {
unsafe { PxArticulationLink_getLinkIndex(self.as_ptr()) }
}
fn get_inbound_joint_dof(&self) -> u32 {
unsafe { PxArticulationLink_getInboundJointDof(self.as_ptr()) }
}
fn get_nb_children(&self) -> u32 {
unsafe { PxArticulationLink_getNbChildren(self.as_ptr()) }
}
fn get_children(&self) -> Vec<&Self> {
let capacity = self.get_nb_children();
let mut buffer: Vec<&Self> = Vec::with_capacity(capacity as usize);
unsafe {
let new_len = PxArticulationLink_getChildren(
self.as_ptr(),
buffer.as_mut_ptr() as *mut *mut _,
capacity,
0,
);
buffer.set_len(new_len as usize);
buffer
}
}
}