libliquidfun_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5use std::fmt::{Debug, Formatter};
6
7use autocxx::prelude::*;
8
9use contact_listener::b2ContactListenerWrapper;
10use ray_cast::b2RayCastCallbackWrapper;
11
12include_cpp! {
13    #include "box2d/box2d.h"
14    #include "extras.hpp"
15    safety!(unsafe_ffi)
16
17    generate!("b2Body")
18    generate!("b2Contact")
19    generate!("b2ContactListener")
20    generate!("b2ContactFilter")
21    generate!("b2DestructionListener")
22    generate!("b2Filter")
23    generate!("b2Fixture")
24    generate!("b2Manifold")
25    generate!("b2QueryCallback")
26    generate!("b2RayCastCallback")
27    generate!("b2World")
28
29    generate!("b2Shape")
30    generate!("b2ChainShape")
31    generate!("b2CircleShape")
32    generate!("b2EdgeShape")
33    generate!("b2PolygonShape")
34
35    generate!("b2Joint")
36    generate!("b2DistanceJoint")
37    generate!("b2FrictionJoint")
38    generate!("b2GearJoint")
39    generate!("b2MotorJoint")
40    generate!("b2PrismaticJoint")
41    generate!("b2PulleyJoint")
42    generate!("b2RevoluteJoint")
43    generate!("b2WeldJoint")
44    generate!("b2WheelJoint")
45    generate!("b2JointUserData")
46    generate!("b2JointDef")
47    generate!("b2DistanceJointDef")
48    generate!("b2FrictionJointDef")
49    generate!("b2GearJointDef")
50    generate!("b2MotorJointDef")
51    generate!("b2PrismaticJointDef")
52    generate!("b2PulleyJointDef")
53    generate!("b2RevoluteJointDef")
54    generate!("b2WeldJointDef")
55    generate!("b2WheelJointDef")
56
57    generate!("b2ParticleContact")
58    generate!("b2ParticleGroup")
59    generate!("b2ParticleHandle")
60    generate!("b2ParticleSystem")
61    generate_pod!("b2ParticleBodyContact")
62    generate_pod!("b2ParticleDef")
63    generate_pod!("b2ParticleFlag")
64    generate_pod!("b2ParticleSystemDef")
65
66    generate_pod!("b2AABB")
67    generate_pod!("b2BodyDef")
68    generate_pod!("b2FixtureDef")
69    generate_pod!("b2MassData")
70    generate_pod!("b2Rot")
71    generate_pod!("b2Transform")
72    generate_pod!("b2Vec2")
73    generate_pod!("b2WorldManifold")
74
75    // extras.hpp
76    generate!("SetCircleRadius")
77    generate!("SetCirclePosition")
78    generate!("CreateParticleGroupDef")
79
80    generate!("CreateRevoluteJoint")
81    generate!("CreatePrismaticJoint")
82    generate!("CreateDistanceJoint")
83    generate!("CreatePulleyJoint")
84    generate!("CreateMouseJoint")
85    generate!("CreateGearJoint")
86    generate!("CreateWheelJoint")
87    generate!("CreateWeldJoint")
88    generate!("CreateFrictionJoint")
89    generate!("CreateMotorJoint")
90
91    subclass!("b2ContactListener", b2ContactListenerWrapper)
92    subclass!("b2RayCastCallback", b2RayCastCallbackWrapper)
93}
94
95mod contact_listener;
96mod ray_cast;
97pub mod box2d {
98    pub mod ffi {
99        pub use crate::{contact_listener::*, ffi::*, ray_cast::*};
100    }
101}
102
103impl PartialEq for ffi::b2Vec2 {
104    fn eq(&self, other: &Self) -> bool {
105        self.x == other.x && self.y == other.y
106    }
107}
108
109impl Debug for ffi::b2Vec2 {
110    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
111        f.debug_struct("b2Vec2")
112            .field("x", &self.x)
113            .field("y", &self.y)
114            .finish()
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use std::pin::Pin;
121
122    use super::*;
123    use crate::ffi::{
124        b2BodyDef,
125        b2BodyType::b2_dynamicBody,
126        b2CircleShape,
127        b2Shape,
128        SetCircleRadius,
129    };
130
131    #[test]
132    fn create_world() {
133        moveit! { let gravity = ffi::b2Vec2::new1(0., -9.81); }
134        let world = ffi::b2World::new(&gravity).within_box();
135
136        let world_gravity = world.GetGravity();
137        let expected_gravity = gravity.as_ref().get_ref();
138        assert_eq!(*expected_gravity, world_gravity);
139    }
140
141    #[test]
142    fn gravity_affects_position() {
143        unsafe {
144            let gravity = ffi::b2Vec2::new1(0., -10.).within_box();
145            let mut world = ffi::b2World::new(&*gravity).within_box();
146            let mut body_def = b2BodyDef::new().within_box();
147            body_def.type_ = b2_dynamicBody;
148            let body_def = &*body_def;
149            let body = world.as_mut().CreateBody(&*body_def);
150            let mut body = Pin::new_unchecked(body.as_mut().unwrap());
151
152            let mut shape = b2CircleShape::new().within_box();
153            SetCircleRadius(shape.as_mut(), 5.);
154            let shape: &b2Shape = (&*shape).as_ref();
155            body.as_mut().CreateFixture1(&*shape, 5.);
156
157            for _ in 0..10 {
158                world
159                    .as_mut()
160                    .Step(0.02, c_int::from(8), c_int::from(3), c_int::from(100));
161            }
162
163            assert!(
164                body.as_ref().GetPosition().y < 0.,
165                "Body needs to move downwards due to gravity"
166            );
167        }
168    }
169}
170
171impl Debug for ffi::b2Body {
172    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
173        f.debug_struct("b2Body")
174            .field("position", &self.GetPosition())
175            .field("angle", &self.GetAngle())
176            .field("type", &(self.GetType() as u32))
177            .field("mass", &self.GetMass())
178            .finish()
179    }
180}