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
106
107
108
109
use crate::{controller::Controller, owner::Owner, traits::Class};

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

#[rustfmt::skip]
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>> {
        unsafe { 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());
        }
    }
}