#![warn(clippy::all)]
use crate::{
articulation::Articulation,
articulation_joint_base::ArticulationJointBase,
articulation_link::ArticulationLink,
articulation_reduced_coordinate::ArticulationReducedCoordinate,
base::Base,
base::ConcreteType,
math::PxBounds3,
math::PxTransform,
traits::{Class, UserData},
};
use std::{marker::PhantomData, ptr::null_mut};
use physx_sys::{
PxArticulationBase_createArticulationJoint_mut,
PxArticulationBase_createLink_mut,
PxArticulationBase_getLinks,
PxArticulationBase_getNbLinks,
PxArticulationBase_getSleepThreshold,
PxArticulationBase_getSolverIterationCounts,
PxArticulationBase_getStabilizationThreshold,
PxArticulationBase_getWakeCounter,
PxArticulationBase_getWorldBounds,
PxArticulationBase_isSleeping,
PxArticulationBase_putToSleep_mut,
PxArticulationBase_releaseArticulationJoint_mut,
PxArticulationBase_setSleepThreshold_mut,
PxArticulationBase_setSolverIterationCounts_mut,
PxArticulationBase_setStabilizationThreshold_mut,
PxArticulationBase_setWakeCounter_mut,
PxArticulationBase_wakeUp_mut,
};
pub trait ArticulationBase: Class<physx_sys::PxArticulationBase> + Base {
type ArticulationLink: ArticulationLink;
fn set_solver_iteration_counts(&mut self, min_position_iters: u32, min_velocity_iters: u32) {
unsafe {
PxArticulationBase_setSolverIterationCounts_mut(
self.as_mut_ptr(),
min_position_iters,
min_velocity_iters,
);
}
}
fn get_solver_iteration_counts(&self) -> (u32, u32) {
unsafe {
let mut min_position_iters: u32 = 0;
let mut min_velocity_iters: u32 = 0;
PxArticulationBase_getSolverIterationCounts(
self.as_ptr(),
&mut min_position_iters as *mut u32,
&mut min_velocity_iters as *mut u32,
);
(min_position_iters, min_velocity_iters)
}
}
fn is_sleeping(&self) -> bool {
unsafe { PxArticulationBase_isSleeping(self.as_ptr()) }
}
fn set_sleep_threshold(&mut self, threshold: f32) {
unsafe {
PxArticulationBase_setSleepThreshold_mut(self.as_mut_ptr(), threshold);
}
}
fn get_sleep_threshold(&self) -> f32 {
unsafe { PxArticulationBase_getSleepThreshold(self.as_ptr()) }
}
fn set_stabilization_threshold(&mut self, threshold: f32) {
unsafe {
PxArticulationBase_setStabilizationThreshold_mut(self.as_mut_ptr(), threshold);
}
}
fn get_stabilization_threshold(&self) -> f32 {
unsafe { PxArticulationBase_getStabilizationThreshold(self.as_ptr()) }
}
fn set_wake_counter(&mut self, threshold: f32) {
unsafe {
PxArticulationBase_setWakeCounter_mut(self.as_mut_ptr(), threshold);
}
}
fn get_wake_counter(&self) -> f32 {
unsafe { PxArticulationBase_getWakeCounter(self.as_ptr()) }
}
fn wake_up(&mut self) {
unsafe {
PxArticulationBase_wakeUp_mut(self.as_mut_ptr());
}
}
fn put_to_sleep(&mut self) {
unsafe {
PxArticulationBase_putToSleep_mut(self.as_mut_ptr());
}
}
fn get_nb_links(&self) -> usize {
unsafe { PxArticulationBase_getNbLinks(self.as_ptr()) as usize }
}
fn root_link(&self) -> Option<&Self::ArticulationLink> {
unsafe {
let mut root: *mut Self::ArticulationLink = null_mut();
PxArticulationBase_getLinks(
self.as_ptr(),
&mut root as *mut *mut Self::ArticulationLink
as *mut *mut physx_sys::PxArticulationLink,
1,
0,
);
root.as_ref()
}
}
fn root_link_mut(&mut self) -> Option<&mut Self::ArticulationLink> {
unsafe {
let mut root: *mut Self::ArticulationLink = null_mut();
PxArticulationBase_getLinks(
self.as_ptr(),
&mut root as *mut *mut Self::ArticulationLink
as *mut *mut physx_sys::PxArticulationLink,
1,
0,
);
root.as_mut()
}
}
fn get_links(&self) -> Vec<&Self::ArticulationLink> {
unsafe {
let capacity = PxArticulationBase_getNbLinks(self.as_ptr());
let mut buffer: Vec<&Self::ArticulationLink> = Vec::with_capacity(capacity as usize);
let len = PxArticulationBase_getLinks(
self.as_ptr(),
buffer.as_mut_ptr() as *mut *mut _,
capacity,
0,
);
buffer.set_len(len as usize);
buffer
}
}
fn get_links_mut(&mut self) -> Vec<&mut Self::ArticulationLink> {
unsafe {
let capacity = PxArticulationBase_getNbLinks(self.as_ptr());
let mut buffer: Vec<&mut Self::ArticulationLink> =
Vec::with_capacity(capacity as usize);
let len = PxArticulationBase_getLinks(
self.as_ptr(),
buffer.as_mut_ptr() as *mut *mut _,
capacity,
0,
);
buffer.set_len(len as usize);
buffer
}
}
fn get_world_bounds(&self, inflation: f32) -> PxBounds3 {
unsafe { PxArticulationBase_getWorldBounds(self.as_ptr(), inflation).into() }
}
fn create_link(
&mut self,
parent: Option<&mut Self::ArticulationLink>,
pose: &PxTransform,
user_data: <Self::ArticulationLink as UserData>::UserData,
) -> Option<&mut Self::ArticulationLink> {
unsafe {
(PxArticulationBase_createLink_mut(
self.as_mut_ptr(),
parent
.map(|parent| parent.as_mut_ptr())
.unwrap_or(null_mut()),
pose.as_ptr(),
) as *mut Self::ArticulationLink)
.as_mut()
.map(|link| UserData::init_user_data(link, user_data))
}
}
fn create_articulation_joint<J: ArticulationJointBase>(
&mut self,
parent: &mut Self::ArticulationLink,
parent_frame: &PxTransform,
child: &mut Self::ArticulationLink,
child_frame: &PxTransform,
) -> Option<&mut J> {
unsafe {
(PxArticulationBase_createArticulationJoint_mut(
self.as_mut_ptr(),
parent.as_mut_ptr(),
parent_frame.as_ptr(),
child.as_mut_ptr(),
child_frame.as_ptr(),
) as *mut J)
.as_mut()
}
}
unsafe fn release_articulation_joint(&mut self, joint: &mut impl ArticulationJointBase) {
PxArticulationBase_releaseArticulationJoint_mut(self.as_mut_ptr(), joint.as_mut_ptr())
}
}
#[repr(transparent)]
pub struct ArticulationMap<T, C>
where
T: Articulation,
C: ArticulationReducedCoordinate,
{
obj: physx_sys::PxArticulationBase,
phantom_user_data: PhantomData<(*const T, *const C)>,
}
unsafe impl<S, T, C> Class<S> for ArticulationMap<T, C>
where
physx_sys::PxArticulationBase: Class<S>,
T: Articulation,
C: ArticulationReducedCoordinate,
{
fn as_ptr(&self) -> *const S {
self.obj.as_ptr()
}
fn as_mut_ptr(&mut self) -> *mut S {
self.obj.as_mut_ptr()
}
}
impl<T, C> ArticulationBase for ArticulationMap<T, C>
where
T: Articulation,
C: ArticulationReducedCoordinate,
{
type ArticulationLink = T::ArticulationLink;
}
impl<T, C> ArticulationMap<T, C>
where
T: Articulation,
C: ArticulationReducedCoordinate,
{
pub unsafe fn cast_map<'a, Ret, ArtFn, ArcFn>(
&'a mut self,
mut art_fn: ArtFn,
mut arc_fn: ArcFn,
) -> Ret
where
ArtFn: FnMut(&'a mut T) -> Ret,
ArcFn: FnMut(&'a mut C) -> Ret,
{
match self.get_concrete_type() {
ConcreteType::Articulation => {
art_fn(
&mut *(self as *mut _ as *mut T),
)
}
ConcreteType::ArticulationReducedCoordinate => arc_fn(&mut *(self as *mut _ as *mut C)),
_ => panic!(
"get_concrete_type for {:?} returned an invalid ConcreteType: {:?}",
self.get_concrete_type_name(),
self.get_concrete_type()
),
}
}
pub fn try_cast_map<'a, Ret, ArtFn, ArcFn>(
&'a mut self,
mut art_fn: ArtFn,
mut arc_fn: ArcFn,
) -> Option<Ret>
where
ArtFn: FnMut(&'a mut T) -> Ret,
ArcFn: FnMut(&'a mut C) -> Ret,
{
match self.get_concrete_type() {
ConcreteType::Articulation => Some(art_fn(unsafe { &mut *(self as *mut _ as *mut T) })),
ConcreteType::ArticulationReducedCoordinate => {
Some(arc_fn(unsafe { &mut *(self as *mut _ as *mut C) }))
}
_ => None,
}
}
pub fn as_articulation(&mut self) -> Option<&mut T> {
match self.get_concrete_type() {
ConcreteType::Articulation => Some(unsafe { &mut *(self as *mut _ as *mut T) }),
_ => None,
}
}
pub fn as_articulation_reduced_coordinate(&mut self) -> Option<&mut T> {
match self.get_concrete_type() {
ConcreteType::ArticulationReducedCoordinate => {
Some(unsafe { &mut *(self as *mut _ as *mut T) })
}
_ => None,
}
}
}