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 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}