1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#ifndef LOVE_PHYSICS_BOX2D_WORLD_H
22#define LOVE_PHYSICS_BOX2D_WORLD_H
23
24// LOVE
25#include "common/Object.h"
26#include "common/runtime.h"
27#include "common/Reference.h"
28
29// STD
30#include <vector>
31#include <unordered_map>
32
33// Box2D
34#include <Box2D/Box2D.h>
35
36namespace love
37{
38namespace physics
39{
40namespace box2d
41{
42
43class Contact;
44class Body;
45class Fixture;
46class Joint;
47
48/**
49 * The World is the "God" container class,
50 * which contains all Bodies and Joints. Shapes
51 * are contained in their associated Body.
52 *
53 * Bodies in different worlds can obviously not
54 * collide.
55 *
56 * The world also controls global parameters, like
57 * gravity.
58 **/
59class World : public Object, public b2ContactListener, public b2ContactFilter, public b2DestructionListener
60{
61public:
62
63 // Friends.
64 friend class Joint;
65 friend class DistanceJoint;
66 friend class MouseJoint;
67 friend class Body;
68 friend class Fixture;
69
70 static love::Type type;
71
72 class ContactCallback
73 {
74 public:
75 Reference *ref;
76 lua_State *L;
77 World *world;
78 ContactCallback(World *world);
79 ~ContactCallback();
80 void process(b2Contact *contact, const b2ContactImpulse *impulse = NULL);
81 };
82
83 class ContactFilter
84 {
85 public:
86 Reference *ref;
87 lua_State *L;
88 ContactFilter();
89 ~ContactFilter();
90 bool process(Fixture *a, Fixture *b);
91 };
92
93 class QueryCallback : public b2QueryCallback
94 {
95 public:
96 QueryCallback(World *world, lua_State *L, int idx);
97 ~QueryCallback();
98 virtual bool ReportFixture(b2Fixture *fixture);
99 private:
100 World *world;
101 lua_State *L;
102 int funcidx;
103 };
104
105 class RayCastCallback : public b2RayCastCallback
106 {
107 public:
108 RayCastCallback(World *world, lua_State *L, int idx);
109 ~RayCastCallback();
110 virtual float32 ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float32 fraction);
111 private:
112 World *world;
113 lua_State *L;
114 int funcidx;
115 };
116
117 /**
118 * Creates a new world.
119 **/
120 World();
121
122 /**
123 * Creates a new world with the given gravity
124 * and whether or not the bodies should sleep when appropriate.
125 * @param gravity The gravity of the World.
126 * @param sleep True if the bodies should be able to sleep,
127 * false otherwise.
128 **/
129 World(b2Vec2 gravity, bool sleep);
130
131 virtual ~World();
132
133 /**
134 * Updates everything in the world one timestep.
135 * This is called update() and not step() to conform
136 * with all other objects in LOVE.
137 * @param dt The timestep.
138 **/
139 void update(float dt);
140 void update(float dt, int velocityIterations, int positionIterations);
141
142 // From b2ContactListener
143 void BeginContact(b2Contact *contact);
144 void EndContact(b2Contact *contact);
145 void PreSolve(b2Contact *contact, const b2Manifold *oldManifold);
146 void PostSolve(b2Contact *contact, const b2ContactImpulse *impulse);
147
148 // From b2ContactFilter
149 bool ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB);
150
151 // From b2DestructionListener
152 void SayGoodbye(b2Fixture *fixture);
153 void SayGoodbye(b2Joint *joint);
154
155 /**
156 * Returns true if the Box2D world is alive.
157 **/
158 bool isValid() const;
159
160 /**
161 * Receives up to four Lua functions as arguments. Each function is
162 * collision callback for the four events (in order): begin, end,
163 * presolve and postsolve. The value "nil" is accepted if one or
164 * more events are uninteresting.
165 **/
166 int setCallbacks(lua_State *L);
167
168 /**
169 * Returns the functions previously set by setCallbacks.
170 **/
171 int getCallbacks(lua_State *L);
172
173 /**
174 * Updates the Lua thread/coroutine used when callbacks are executed in
175 * the update method. This should be called in the same Lua function which
176 * calls update().
177 **/
178 void setCallbacksL(lua_State *L);
179
180 /**
181 * Sets the ContactFilter callback.
182 **/
183 int setContactFilter(lua_State *L);
184
185 /**
186 * Gets the ContactFilter callback.
187 **/
188 int getContactFilter(lua_State *L);
189
190 /**
191 * Sets the current gravity of the World.
192 * @param x Gravity in the x-direction.
193 * @param y Gravity in the y-direction.
194 **/
195 void setGravity(float x, float y);
196
197 /**
198 * Gets the current gravity.
199 * @returns Gravity in the x-direction.
200 * @returns Gravity in the y-direction.
201 **/
202 int getGravity(lua_State *L);
203
204 /**
205 * Translate the world origin.
206 * @param x The new world origin's x-coordinate relative to the old origin.
207 * @param y The new world origin's y-coordinate relative to the old origin.
208 **/
209 void translateOrigin(float x, float y);
210
211 /**
212 * Sets whether this World allows sleep.
213 * @param allow True to allow, false to disallow.
214 **/
215 void setSleepingAllowed(bool allow);
216
217 /**
218 * Returns whether this World allows sleep.
219 * @return True if allowed, false if disallowed.
220 **/
221 bool isSleepingAllowed() const;
222
223 /**
224 * Returns whether this World is currently locked.
225 * If it's locked, it's in the middle of a timestep.
226 * @return Whether the World is locked.
227 **/
228 bool isLocked() const;
229
230 /**
231 * Get the current body count.
232 * @return The number of bodies.
233 **/
234 int getBodyCount() const;
235
236 /**
237 * Get the current joint count.
238 * @return The number of joints.
239 **/
240 int getJointCount() const;
241
242 /**
243 * Get the current contact count.
244 * @return The number of contacts.
245 **/
246 int getContactCount() const;
247
248 /**
249 * Get an array of all the Bodies in the World.
250 * @return An array of Bodies.
251 **/
252 int getBodies(lua_State *L) const;
253
254 /**
255 * Get an array of all the Joints in the World.
256 * @return An array of Joints.
257 **/
258 int getJoints(lua_State *L) const;
259
260 /**
261 * Get an array of all the Contacts in the World.
262 * @return An array of Contacts.
263 **/
264 int getContacts(lua_State *L);
265
266 /**
267 * Gets the ground body.
268 * @return The ground body.
269 **/
270 b2Body *getGroundBody() const;
271
272 /**
273 * Gets all fixtures that overlap a given bounding box.
274 **/
275 int queryBoundingBox(lua_State *L);
276
277 /**
278 * Raycasts the World for all Fixtures in the path of the ray.
279 **/
280 int rayCast(lua_State *L);
281
282 /**
283 * Destroy this world.
284 **/
285 void destroy();
286
287 void registerObject(void *b2object, love::Object *object);
288 void unregisterObject(void *b2object);
289 love::Object *findObject(void *b2object) const;
290
291private:
292
293 // Pointer to the Box2D world.
294 b2World *world;
295
296 // Ground body
297 b2Body *groundBody;
298
299 // The list of to be destructed bodies.
300 std::vector<Body *> destructBodies;
301 std::vector<Fixture *> destructFixtures;
302 std::vector<Joint *> destructJoints;
303 bool destructWorld;
304
305 // Contact callbacks.
306 ContactCallback begin, end, presolve, postsolve;
307 ContactFilter filter;
308
309 std::unordered_map<void *, love::Object *> box2dObjectMap;
310
311}; // World
312
313} // box2d
314} // physics
315} // love
316
317#endif // LOVE_PHYSICS_BOX2D_WORLD_H
318