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
129
130
131
132
133
134
135
136
137
138
139
140
use wrap::*;
use common::math::Vec2;
use user_data::UserDataTypes;
use dynamics::world::{World, BodyHandle};
use dynamics::joints::{Joint, JointType, JointDef};

pub struct FrictionJointDef {
    pub body_a: BodyHandle,
    pub body_b: BodyHandle,
    pub collide_connected: bool,
    pub local_anchor_a: Vec2,
    pub local_anchor_b: Vec2,
    pub max_force: f32,
    pub max_torque: f32,
}

impl FrictionJointDef {
    pub fn new(body_a: BodyHandle, body_b: BodyHandle) -> FrictionJointDef {
        FrictionJointDef {
            body_a: body_a,
            body_b: body_b,
            collide_connected: false,
            local_anchor_a: Vec2 { x: 0., y: 0. },
            local_anchor_b: Vec2 { x: 0., y: 0. },
            max_force: 0.,
            max_torque: 0.,
        }
    }

    pub fn init<U: UserDataTypes>(&mut self,
                                  world: &World<U>,
                                  body_a: BodyHandle,
                                  body_b: BodyHandle,
                                  anchor: &Vec2) {
        self.try_init(world, body_a, body_b, anchor).expect("joint init filed: invalid body handle");
    }

    pub fn try_init<U: UserDataTypes>(&mut self,
                                      world: &World<U>,
                                      body_a: BodyHandle,
                                      body_b: BodyHandle,
                                      anchor: &Vec2) -> Option<()> {
        self.body_a = body_a;
        self.body_b = body_b;
        let a = world.try_body(body_a)?;
        let b = world.try_body(body_b)?;
        self.local_anchor_a = a.local_point(anchor);
        self.local_anchor_b = b.local_point(anchor);
        Some(())
    }
}

impl JointDef for FrictionJointDef {
    fn joint_type() -> JointType
        where Self: Sized
    {
        JointType::Friction
    }

    unsafe fn create<U: UserDataTypes>(&self, world: &mut World<U>) -> *mut ffi::Joint {
        self.try_create(world).expect("joint create failed: invalid body handle")
    }

    unsafe fn try_create<U: UserDataTypes>(&self, world: &mut World<U>) -> Option<*mut ffi::Joint> {
        Some(ffi::World_create_friction_joint(world.mut_ptr(),
                                              world.try_body_mut(self.body_a)?.mut_ptr(),
                                              world.try_body_mut(self.body_b)?.mut_ptr(),
                                              self.collide_connected,
                                              self.local_anchor_a,
                                              self.local_anchor_b,
                                              self.max_force,
                                              self.max_torque))
    }
}

wrap_joint! {
    ffi::FrictionJoint => FrictionJoint (JointType::Friction)
    < ffi::FrictionJoint_as_joint
    > ffi::Joint_as_friction_joint
}

impl FrictionJoint {
    pub fn local_anchor_a<'a>(&'a self) -> &'a Vec2 {
        unsafe {
            &*ffi::FrictionJoint_get_local_anchor_a(self.ptr()) // Comes from a C++ &
        }
    }

    pub fn local_anchor_b<'a>(&'a self) -> &'a Vec2 {
        unsafe {
            &*ffi::FrictionJoint_get_local_anchor_b(self.ptr()) // Comes from a C++ &
        }
    }

    pub fn max_force(&self) -> f32 {
        unsafe { ffi::FrictionJoint_get_max_force(self.ptr()) }
    }

    pub fn max_torque(&self) -> f32 {
        unsafe { ffi::FrictionJoint_get_max_torque(self.ptr()) }
    }

    pub fn set_max_force(&mut self, force: f32) {
        unsafe { ffi::FrictionJoint_set_max_force(self.mut_ptr(), force) }
    }

    pub fn set_max_torque(&mut self, torque: f32) {
        unsafe { ffi::FrictionJoint_set_max_torque(self.mut_ptr(), torque) }
    }
}

#[doc(hidden)]
pub mod ffi {
    pub use dynamics::world::ffi::World;
    pub use dynamics::body::ffi::Body;
    pub use dynamics::joints::ffi::Joint;
    use common::math::Vec2;

    pub enum FrictionJoint {}

    extern "C" {
        pub fn World_create_friction_joint(world: *mut World,
                                           body_a: *mut Body,
                                           body_b: *mut Body,
                                           collide_connected: bool,
                                           local_anchor_a: Vec2,
                                           local_anchor_b: Vec2,
                                           max_force: f32,
                                           max_torque: f32)
                                           -> *mut Joint;
        pub fn FrictionJoint_as_joint(slf: *mut FrictionJoint) -> *mut Joint;
        pub fn Joint_as_friction_joint(slf: *mut Joint) -> *mut FrictionJoint;
        pub fn FrictionJoint_get_local_anchor_a(slf: *const FrictionJoint) -> *const Vec2;
        pub fn FrictionJoint_get_local_anchor_b(slf: *const FrictionJoint) -> *const Vec2;
        pub fn FrictionJoint_set_max_force(slf: *mut FrictionJoint, force: f32);
        pub fn FrictionJoint_get_max_force(slf: *const FrictionJoint) -> f32;
        pub fn FrictionJoint_set_max_torque(slf: *mut FrictionJoint, torque: f32);
        pub fn FrictionJoint_get_max_torque(slf: *const FrictionJoint) -> f32;
    }
}