1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use crate::{controller::Controller, owner::Owner, traits::Class};

use std::{marker::PhantomData, ptr::drop_in_place};

use physx_sys::{
    PxControllerManager_createController_mut, PxControllerManager_getController_mut,
    PxControllerManager_getNbControllers, PxControllerManager_purgeControllers_mut,
    PxControllerManager_release_mut,
};

#[repr(transparent)]
pub struct PxControllerManager<C>
where
    C: Controller,
{
    obj: physx_sys::PxControllerManager,
    phantom_controller_types: PhantomData<C>,
}

unsafe impl<T, C> Class<T> for PxControllerManager<C>
where
    physx_sys::PxControllerManager: Class<T>,
    C: Controller,
{
    fn as_ptr(&self) -> *const T {
        self.obj.as_ptr()
    }

    fn as_mut_ptr(&mut self) -> *mut T {
        self.obj.as_mut_ptr()
    }
}

impl<C: Controller> ControllerManager for PxControllerManager<C> {
    type Controller = C;
}

pub trait ControllerManager: Class<physx_sys::PxControllerManager> + Sized {
    type Controller: Controller;

    /// # Safety
    /// the pointee will be dropped when the Owner is dropped.  Use `into_ptr` to
    /// retrieve the pointer from the Owner without dropping it.
    unsafe fn from_raw(ptr: *mut physx_sys::PxControllerManager) -> Option<Owner<Self>> {
        Owner::from_raw(ptr as *mut Self)
    }

    /// Create a controller.
    fn create_controller(
        &mut self,
        desc: Owner<<Self::Controller as Controller>::Descriptor>,
    ) -> Option<&mut Self::Controller> {
        unsafe {
            (PxControllerManager_createController_mut(self.as_mut_ptr(), desc.into_ptr())
                as *mut Self::Controller)
                .as_mut()
        }
    }

    /// Get the number of controllers currently being managed.
    fn get_nb_controllers(&self) -> u32 {
        unsafe { PxControllerManager_getNbControllers(self.as_ptr()) }
    }

    /// Get a controller by index.  Returns `None`
    fn get_controller(&mut self, idx: u32) -> Option<&mut Self::Controller> {
        unsafe {
            if idx < self.get_nb_controllers() {
                (PxControllerManager_getController_mut(self.as_mut_ptr(), idx)
                    as *mut Self::Controller)
                    .as_mut()
            } else {
                None
            }
        }
    }

    /// Get a Vec of all the controllers being managed.
    fn get_controllers(&mut self) -> Vec<&mut Self::Controller> {
        let count = self.get_nb_controllers();
        let mut vec = Vec::with_capacity(count as usize);
        for idx in 0..count {
            vec.push(unsafe {
                &mut *(PxControllerManager_getController_mut(self.as_mut_ptr(), idx)
                    as *mut Self::Controller)
            });
        }
        vec
    }
}

unsafe impl<C: Controller + Send> Send for PxControllerManager<C> {}
unsafe impl<C: Controller + Sync> Sync for PxControllerManager<C> {}

impl<C: Controller> Drop for PxControllerManager<C> {
    fn drop(&mut self) {
        unsafe {
            for controller in self.get_controllers() {
                drop_in_place(controller as *mut _);
            }
            PxControllerManager_purgeControllers_mut(self.as_mut_ptr());
            PxControllerManager_release_mut(self.as_mut_ptr());
        }
    }
}