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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::mem;

use crate::ffi;
use crate::handle::{Handle, HandleInner};
use crate::math::Vec3;

use super::{Compound, ConvexShape, NewtonCollision, Scene, Tree};

/// Type to add/remove collisions from a compound.
pub struct CompoundBuilder<'a, 'b> {
    pub(super) compound: &'b Compound<'a>,
}

/// Add/remove collisions from a scene collision.
pub struct SceneBuilder<'a, 'b> {
    pub(super) scene: &'b Scene<'a>,
}

/// Type to define the geometry of a tree collision.
pub struct TreeBuilder<'a, 'b> {
    pub(super) optimize: bool,
    pub(super) tree: &'b Tree<'a>,
}

impl<'a, 'b> CompoundBuilder<'a, 'b> {
    /// Adds a collision to the compound
    pub fn add<C>(&self, col: &C) -> Handle
        where C: ConvexShape
    {
        let comp = self.compound.raw;
        let sub = col.as_raw();
        unsafe {
            let handle = ffi::NewtonCompoundCollisionAddSubCollision(comp, sub);
            Handle::from_ptr(handle as _)
        }
    }

    /// Removes a collision from the compound
    pub fn remove(&self, handle: Handle) {
        let comp = self.compound.raw;
        match handle.inner() {
            HandleInner::Pointer(ptr) => unsafe {
                ffi::NewtonCompoundCollisionRemoveSubCollision(comp, ptr as _);
            },
            HandleInner::Index(idx) => unsafe {
                let ptr = ffi::NewtonCompoundCollisionGetNodeByIndex(comp, idx as _);
                if !ptr.is_null() {
                    ffi::NewtonCompoundCollisionRemoveSubCollisionByIndex(comp, idx as _);
                } else {
                    //TODO error?
                }
            },
        }
    }
}

impl<'a, 'b> SceneBuilder<'a, 'b> {
    /// Adds a collision to the scene
    pub fn add<C>(&self, col: &C) -> Handle
        where C: NewtonCollision
    {
        let comp = self.scene.raw;
        let sub = col.as_raw();
        unsafe {
            let handle = ffi::NewtonSceneCollisionAddSubCollision(comp, sub);
            Handle::from_ptr(handle as _)
        }
    }

    /// Removes a collision from the scene.
    pub fn remove(&self, handle: Handle) {
        let comp = self.scene.raw;
        match handle.inner() {
            HandleInner::Pointer(ptr) => unsafe {
                ffi::NewtonSceneCollisionRemoveSubCollision(comp, ptr as _);
            },
            HandleInner::Index(idx) => unsafe {
                let ptr = ffi::NewtonSceneCollisionGetNodeByIndex(comp, idx as _);
                if !ptr.is_null() {
                    ffi::NewtonSceneCollisionRemoveSubCollisionByIndex(comp, idx as _);
                } else {
                    //TODO error?
                }
            },
        }
    }
}

impl<'a, 'b> TreeBuilder<'a, 'b> {
    pub fn add(&self, verts: &[Vec3], attr: i32) {
        unsafe {
            let vert_ptr = verts.as_ptr() as *const f32;
            let vert_len = verts.len() as _;
            let stride = mem::size_of::<Vec3>() as _;
            ffi::NewtonTreeCollisionAddFace(self.tree.raw, vert_len, vert_ptr, stride, attr);
        }
    }

    /// Optimizes the mesh and finishes the build process.
    pub fn optimize(mut self) {
        self.optimize = true;
    }
}

impl<'a, 'b> Drop for CompoundBuilder<'a, 'b> {
    fn drop(&mut self) {
        unsafe {
            ffi::NewtonCompoundCollisionEndAddRemove(self.compound.raw);
        }
    }
}

impl<'a, 'b> Drop for SceneBuilder<'a, 'b> {
    fn drop(&mut self) {
        unsafe {
            ffi::NewtonSceneCollisionEndAddRemove(self.scene.raw);
        }
    }
}

impl<'a, 'b> Drop for TreeBuilder<'a, 'b> {
    fn drop(&mut self) {
        unsafe {
            let optimize = if self.optimize { 1 } else { 0 };
            ffi::NewtonTreeCollisionEndBuild(self.tree.raw, optimize);
        }
    }
}