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#include "wrap_Body.h"
22#include "wrap_Physics.h"
23
24namespace love
25{
26namespace physics
27{
28namespace box2d
29{
30
31Body *luax_checkbody(lua_State *L, int idx)
32{
33 Body *b = luax_checktype<Body>(L, idx);
34 if (b->body == 0)
35 luaL_error(L, "Attempt to use destroyed body.");
36 return b;
37}
38
39int w_Body_getX(lua_State *L)
40{
41 Body *t = luax_checkbody(L, 1);
42 lua_pushnumber(L, t->getX());
43 return 1;
44}
45
46int w_Body_getY(lua_State *L)
47{
48 Body *t = luax_checkbody(L, 1);
49 lua_pushnumber(L, t->getY());
50 return 1;
51}
52
53int w_Body_getAngle(lua_State *L)
54{
55 Body *t = luax_checkbody(L, 1);
56 lua_pushnumber(L, t->getAngle());
57 return 1;
58}
59
60int w_Body_getPosition(lua_State *L)
61{
62 Body *t = luax_checkbody(L, 1);
63
64 float x_o, y_o;
65 t->getPosition(x_o, y_o);
66 lua_pushnumber(L, x_o);
67 lua_pushnumber(L, y_o);
68
69 return 2;
70}
71
72int w_Body_getTransform(lua_State *L)
73{
74 Body *t = luax_checkbody(L, 1);
75
76 float x_o, y_o;
77 t->getPosition(x_o, y_o);
78 lua_pushnumber(L, x_o);
79 lua_pushnumber(L, y_o);
80 lua_pushnumber(L, t->getAngle());
81
82 return 3;
83}
84
85int w_Body_getLinearVelocity(lua_State *L)
86{
87 Body *t = luax_checkbody(L, 1);
88
89 float x_o, y_o;
90 t->getLinearVelocity(x_o, y_o);
91 lua_pushnumber(L, x_o);
92 lua_pushnumber(L, y_o);
93
94 return 2;
95}
96
97int w_Body_getWorldCenter(lua_State *L)
98{
99 Body *t = luax_checkbody(L, 1);
100
101 float x_o, y_o;
102 t->getWorldCenter(x_o, y_o);
103 lua_pushnumber(L, x_o);
104 lua_pushnumber(L, y_o);
105
106 return 2;
107}
108
109int w_Body_getLocalCenter(lua_State *L)
110{
111 Body *t = luax_checkbody(L, 1);
112
113 float x_o, y_o;
114 t->getLocalCenter(x_o, y_o);
115 lua_pushnumber(L, x_o);
116 lua_pushnumber(L, y_o);
117
118 return 2;
119}
120
121int w_Body_getAngularVelocity(lua_State *L)
122{
123 Body *t = luax_checkbody(L, 1);
124 lua_pushnumber(L, t->getAngularVelocity());
125 return 1;
126}
127
128int w_Body_getMass(lua_State *L)
129{
130 Body *t = luax_checkbody(L, 1);
131 lua_pushnumber(L, t->getMass());
132 return 1;
133}
134
135int w_Body_getInertia(lua_State *L)
136{
137 Body *t = luax_checkbody(L, 1);
138 lua_pushnumber(L, t->getInertia());
139 return 1;
140}
141
142int w_Body_getMassData(lua_State *L)
143{
144 Body *t = luax_checkbody(L, 1);
145 lua_remove(L, 1);
146 return t->getMassData(L);
147}
148
149int w_Body_getAngularDamping(lua_State *L)
150{
151 Body *t = luax_checkbody(L, 1);
152 lua_pushnumber(L, t->getAngularDamping());
153 return 1;
154}
155
156int w_Body_getLinearDamping(lua_State *L)
157{
158 Body *t = luax_checkbody(L, 1);
159 lua_pushnumber(L, t->getLinearDamping());
160 return 1;
161}
162
163int w_Body_getGravityScale(lua_State *L)
164{
165 Body *t = luax_checkbody(L, 1);
166 lua_pushnumber(L, t->getGravityScale());
167 return 1;
168}
169
170int w_Body_getType(lua_State *L)
171{
172 Body *t = luax_checkbody(L, 1);
173 const char *type = "";
174 Body::getConstant(t->getType(), type);
175 lua_pushstring(L, type);
176 return 1;
177}
178
179int w_Body_applyLinearImpulse(lua_State *L)
180{
181 Body *t = luax_checkbody(L, 1);
182 float jx = (float)luaL_checknumber(L, 2);
183 float jy = (float)luaL_checknumber(L, 3);
184
185 int nargs = lua_gettop(L);
186
187 if (nargs <= 3 || (nargs == 4 && lua_type(L, 4) == LUA_TBOOLEAN))
188 {
189 bool awake = luax_optboolean(L, 4, true);
190 t->applyLinearImpulse(jx, jy, awake);
191 }
192 else if (nargs >= 5)
193 {
194 float rx = (float)luaL_checknumber(L, 4);
195 float ry = (float)luaL_checknumber(L, 5);
196 bool awake = luax_optboolean(L, 6, true);
197 t->applyLinearImpulse(jx, jy, rx, ry, awake);
198 }
199 else
200 {
201 return luaL_error(L, "Wrong number of parameters.");
202 }
203
204 return 0;
205}
206
207int w_Body_applyAngularImpulse(lua_State *L)
208{
209 Body *t = luax_checkbody(L, 1);
210 float i = (float)luaL_checknumber(L, 2);
211 bool awake = luax_optboolean(L, 3, true);
212 t->applyAngularImpulse(i, awake);
213 return 0;
214}
215
216int w_Body_applyTorque(lua_State *L)
217{
218 Body *t = luax_checkbody(L, 1);
219 float arg = (float)luaL_checknumber(L, 2);
220 bool awake = luax_optboolean(L, 3, true);
221 t->applyTorque(arg, awake);
222 return 0;
223}
224
225int w_Body_applyForce(lua_State *L)
226{
227 Body *t = luax_checkbody(L, 1);
228 float fx = (float)luaL_checknumber(L, 2);
229 float fy = (float)luaL_checknumber(L, 3);
230
231 int nargs = lua_gettop(L);
232
233 if (nargs <= 3 || (nargs == 4 && lua_type(L, 4) == LUA_TBOOLEAN))
234 {
235 bool awake = luax_optboolean(L, 4, true);
236 t->applyForce(fx, fy, awake);
237 }
238 else if (lua_gettop(L) >= 5)
239 {
240 float rx = (float)luaL_checknumber(L, 4);
241 float ry = (float)luaL_checknumber(L, 5);
242 bool awake = luax_optboolean(L, 6, true);
243 t->applyForce(fx, fy, rx, ry, awake);
244 }
245 else
246 {
247 return luaL_error(L, "Wrong number of parameters.");
248 }
249
250 return 0;
251}
252
253int w_Body_setX(lua_State *L)
254{
255 Body *t = luax_checkbody(L, 1);
256 float arg1 = (float)luaL_checknumber(L, 2);
257 luax_catchexcept(L, [&](){ t->setX(arg1); });
258 return 0;
259}
260
261int w_Body_setY(lua_State *L)
262{
263 Body *t = luax_checkbody(L, 1);
264 float arg1 = (float)luaL_checknumber(L, 2);
265 luax_catchexcept(L, [&](){ t->setY(arg1); });
266 return 0;
267}
268
269int w_Body_setTransform(lua_State *L)
270{
271 Body *t = luax_checkbody(L, 1);
272 float x = (float)luaL_checknumber(L, 2);
273 float y = (float)luaL_checknumber(L, 3);
274 float angle = (float)luaL_checknumber(L, 4);
275 luax_catchexcept(L, [&](){
276 t->setPosition(x, y);
277 t->setAngle(angle);
278 });
279 return 0;
280}
281
282int w_Body_setLinearVelocity(lua_State *L)
283{
284 Body *t = luax_checkbody(L, 1);
285 float arg1 = (float)luaL_checknumber(L, 2);
286 float arg2 = (float)luaL_checknumber(L, 3);
287 t->setLinearVelocity(arg1, arg2);
288 return 0;
289}
290
291int w_Body_setAngle(lua_State *L)
292{
293 Body *t = luax_checkbody(L, 1);
294 float arg1 = (float)luaL_checknumber(L, 2);
295 luax_catchexcept(L, [&](){ t->setAngle(arg1); });
296 return 0;
297}
298
299int w_Body_setAngularVelocity(lua_State *L)
300{
301 Body *t = luax_checkbody(L, 1);
302 float arg1 = (float)luaL_checknumber(L, 2);
303 t->setAngularVelocity(arg1);
304 return 0;
305}
306
307int w_Body_setPosition(lua_State *L)
308{
309 Body *t = luax_checkbody(L, 1);
310 float arg1 = (float)luaL_checknumber(L, 2);
311 float arg2 = (float)luaL_checknumber(L, 3);
312 luax_catchexcept(L, [&](){ t->setPosition(arg1, arg2); });
313 return 0;
314}
315
316int w_Body_resetMassData(lua_State *L)
317{
318 Body *t = luax_checkbody(L, 1);
319 luax_catchexcept(L, [&](){ t->resetMassData(); });
320 return 0;
321}
322
323int w_Body_setMassData(lua_State *L)
324{
325 Body *t = luax_checkbody(L, 1);
326 float x = (float)luaL_checknumber(L, 2);
327 float y = (float)luaL_checknumber(L, 3);
328 float m = (float)luaL_checknumber(L, 4);
329 float i = (float)luaL_checknumber(L, 5);
330 luax_catchexcept(L, [&](){ t->setMassData(x, y, m, i); });
331 return 0;
332}
333
334int w_Body_setMass(lua_State *L)
335{
336 Body *t = luax_checkbody(L, 1);
337 float m = (float)luaL_checknumber(L, 2);
338 luax_catchexcept(L, [&](){ t->setMass(m); });
339 return 0;
340}
341
342int w_Body_setInertia(lua_State *L)
343{
344 Body *t = luax_checkbody(L, 1);
345 float i = (float)luaL_checknumber(L, 2);
346 luax_catchexcept(L, [&](){ t->setInertia(i); });
347 return 0;
348}
349
350int w_Body_setAngularDamping(lua_State *L)
351{
352 Body *t = luax_checkbody(L, 1);
353 float arg1 = (float)luaL_checknumber(L, 2);
354 t->setAngularDamping(arg1);
355 return 0;
356}
357
358int w_Body_setLinearDamping(lua_State *L)
359{
360 Body *t = luax_checkbody(L, 1);
361 float arg1 = (float)luaL_checknumber(L, 2);
362 t->setLinearDamping(arg1);
363 return 0;
364}
365
366int w_Body_setGravityScale(lua_State *L)
367{
368 Body *t = luax_checkbody(L, 1);
369 float arg1 = (float)luaL_checknumber(L, 2);
370 t->setGravityScale(arg1);
371 return 0;
372}
373
374int w_Body_setType(lua_State *L)
375{
376 Body *t = luax_checkbody(L, 1);
377 const char *typeStr = luaL_checkstring(L, 2);
378 Body::Type type;
379 Body::getConstant(typeStr, type);
380 luax_catchexcept(L, [&](){ t->setType(type); });
381 return 0;
382}
383
384int w_Body_getWorldPoint(lua_State *L)
385{
386 Body *t = luax_checkbody(L, 1);
387
388 float x = (float)luaL_checknumber(L, 2);
389 float y = (float)luaL_checknumber(L, 3);
390 float x_o, y_o;
391 t->getWorldPoint(x, y, x_o, y_o);
392 lua_pushnumber(L, x_o);
393 lua_pushnumber(L, y_o);
394
395 return 2;
396}
397
398int w_Body_getWorldVector(lua_State *L)
399{
400 Body *t = luax_checkbody(L, 1);
401
402 float x = (float)luaL_checknumber(L, 2);
403 float y = (float)luaL_checknumber(L, 3);
404 float x_o, y_o;
405 t->getWorldVector(x, y, x_o, y_o);
406 lua_pushnumber(L, x_o);
407 lua_pushnumber(L, y_o);
408
409 return 2;
410}
411
412int w_Body_getWorldPoints(lua_State *L)
413{
414 Body *t = luax_checkbody(L, 1);
415 lua_remove(L, 1);
416 return t->getWorldPoints(L);
417}
418
419int w_Body_getLocalPoint(lua_State *L)
420{
421 Body *t = luax_checkbody(L, 1);
422
423 float x = (float)luaL_checknumber(L, 2);
424 float y = (float)luaL_checknumber(L, 3);
425 float x_o, y_o;
426 t->getLocalPoint(x, y, x_o, y_o);
427 lua_pushnumber(L, x_o);
428 lua_pushnumber(L, y_o);
429
430 return 2;
431}
432
433int w_Body_getLocalVector(lua_State *L)
434{
435 Body *t = luax_checkbody(L, 1);
436
437 float x = (float)luaL_checknumber(L, 2);
438 float y = (float)luaL_checknumber(L, 3);
439 float x_o, y_o;
440 t->getLocalVector(x, y, x_o, y_o);
441 lua_pushnumber(L, x_o);
442 lua_pushnumber(L, y_o);
443
444 return 2;
445}
446
447int w_Body_getLocalPoints(lua_State *L)
448{
449 Body *t = luax_checkbody(L, 1);
450 lua_remove(L, 1);
451 return t->getLocalPoints(L);
452}
453
454int w_Body_getLinearVelocityFromWorldPoint(lua_State *L)
455{
456 Body *t = luax_checkbody(L, 1);
457
458 float x = (float)luaL_checknumber(L, 2);
459 float y = (float)luaL_checknumber(L, 3);
460 float x_o, y_o;
461 t->getLinearVelocityFromWorldPoint(x, y, x_o, y_o);
462 lua_pushnumber(L, x_o);
463 lua_pushnumber(L, y_o);
464
465 return 2;
466}
467
468int w_Body_getLinearVelocityFromLocalPoint(lua_State *L)
469{
470 Body *t = luax_checkbody(L, 1);
471
472 float x = (float)luaL_checknumber(L, 2);
473 float y = (float)luaL_checknumber(L, 3);
474 float x_o, y_o;
475 t->getLinearVelocityFromLocalPoint(x, y, x_o, y_o);
476 lua_pushnumber(L, x_o);
477 lua_pushnumber(L, y_o);
478
479 return 2;
480}
481
482int w_Body_isBullet(lua_State *L)
483{
484 Body *t = luax_checkbody(L, 1);
485 luax_pushboolean(L, t->isBullet());
486 return 1;
487}
488
489int w_Body_setBullet(lua_State *L)
490{
491 Body *t = luax_checkbody(L, 1);
492 bool b = luax_checkboolean(L, 2);
493 t->setBullet(b);
494 return 0;
495}
496
497int w_Body_isActive(lua_State *L)
498{
499 Body *t = luax_checkbody(L, 1);
500 luax_pushboolean(L, t->isActive());
501 return 1;
502}
503
504int w_Body_isAwake(lua_State *L)
505{
506 Body *t = luax_checkbody(L, 1);
507 luax_pushboolean(L, t->isAwake());
508 return 1;
509}
510
511int w_Body_setSleepingAllowed(lua_State *L)
512{
513 Body *t = luax_checkbody(L, 1);
514 bool b = luax_checkboolean(L, 2);
515 t->setSleepingAllowed(b);
516 return 0;
517}
518
519int w_Body_isSleepingAllowed(lua_State *L)
520{
521 Body *t = luax_checkbody(L, 1);
522 lua_pushboolean(L, t->isSleepingAllowed());
523 return 1;
524}
525
526int w_Body_setActive(lua_State *L)
527{
528 Body *t = luax_checkbody(L, 1);
529 bool b = luax_checkboolean(L, 2);
530 luax_catchexcept(L, [&](){ t->setActive(b); });
531 return 0;
532}
533
534int w_Body_setAwake(lua_State *L)
535{
536 Body *t = luax_checkbody(L, 1);
537 bool b = luax_checkboolean(L, 2);
538 t->setAwake(b);
539 return 0;
540}
541
542int w_Body_setFixedRotation(lua_State *L)
543{
544 Body *t = luax_checkbody(L, 1);
545 bool b = luax_checkboolean(L, 2);
546 luax_catchexcept(L, [&](){ t->setFixedRotation(b); });
547 return 0;
548}
549
550int w_Body_isFixedRotation(lua_State *L)
551{
552 Body *t = luax_checkbody(L, 1);
553 bool b = t->isFixedRotation();
554 luax_pushboolean(L, b);
555 return 1;
556}
557
558int w_Body_isTouching(lua_State *L)
559{
560 Body *t = luax_checkbody(L, 1);
561 Body *other = luax_checkbody(L, 2);
562 luax_pushboolean(L, t->isTouching(other));
563 return 1;
564}
565
566int w_Body_getWorld(lua_State *L)
567{
568 Body *t = luax_checkbody(L, 1);
569 World *world = t->getWorld();
570 luax_pushtype(L, world);
571 return 1;
572}
573
574int w_Body_getFixtures(lua_State *L)
575{
576 Body *t = luax_checkbody(L, 1);
577 lua_remove(L, 1);
578 int n = 0;
579 luax_catchexcept(L, [&](){ n = t->getFixtures(L); });
580 return n;
581}
582
583int w_Body_getJoints(lua_State *L)
584{
585 Body *t = luax_checkbody(L, 1);
586 lua_remove(L, 1);
587 int n = 0;
588 luax_catchexcept(L, [&](){ n = t->getJoints(L); });
589 return n;
590}
591
592int w_Body_getContacts(lua_State *L)
593{
594 Body *t = luax_checkbody(L, 1);
595 lua_remove(L, 1);
596 int n = 0;
597 luax_catchexcept(L, [&](){ n = t->getContacts(L); });
598 return n;
599}
600
601int w_Body_destroy(lua_State *L)
602{
603 Body *t = luax_checkbody(L, 1);
604 luax_catchexcept(L, [&](){ t->destroy(); });
605 return 0;
606}
607
608int w_Body_isDestroyed(lua_State *L)
609{
610 Body *b = luax_checktype<Body>(L, 1);
611 luax_pushboolean(L, b->body == nullptr);
612 return 1;
613}
614
615int w_Body_setUserData(lua_State *L)
616{
617 Body *t = luax_checkbody(L, 1);
618 lua_remove(L, 1);
619 return t->setUserData(L);
620}
621
622int w_Body_getUserData(lua_State *L)
623{
624 Body *t = luax_checkbody(L, 1);
625 lua_remove(L, 1);
626 return t->getUserData(L);
627}
628
629int w_Body_getFixtureList(lua_State *L)
630{
631 luax_markdeprecated(L, "Body:getFixtureList", API_METHOD, DEPRECATED_RENAMED, "Body:getFixtures");
632 return w_Body_getFixtures(L);
633}
634
635int w_Body_getJointList(lua_State *L)
636{
637 luax_markdeprecated(L, "Body:getJointList", API_METHOD, DEPRECATED_RENAMED, "Body:getJoints");
638 return w_Body_getJoints(L);
639}
640
641int w_Body_getContactList(lua_State *L)
642{
643 luax_markdeprecated(L, "Body:getContactList", API_METHOD, DEPRECATED_RENAMED, "Body:getContacts");
644 return w_Body_getContacts(L);
645}
646
647static const luaL_Reg w_Body_functions[] =
648{
649 { "getX", w_Body_getX },
650 { "getY", w_Body_getY },
651 { "getAngle", w_Body_getAngle },
652 { "getPosition", w_Body_getPosition },
653 { "getTransform", w_Body_getTransform },
654 { "setTransform", w_Body_setTransform },
655 { "getLinearVelocity", w_Body_getLinearVelocity },
656 { "getWorldCenter", w_Body_getWorldCenter },
657 { "getLocalCenter", w_Body_getLocalCenter },
658 { "getAngularVelocity", w_Body_getAngularVelocity },
659 { "getMass", w_Body_getMass },
660 { "getInertia", w_Body_getInertia },
661 { "getMassData", w_Body_getMassData },
662 { "getAngularDamping", w_Body_getAngularDamping },
663 { "getLinearDamping", w_Body_getLinearDamping },
664 { "getGravityScale", w_Body_getGravityScale },
665 { "getType", w_Body_getType },
666 { "applyLinearImpulse", w_Body_applyLinearImpulse },
667 { "applyAngularImpulse", w_Body_applyAngularImpulse },
668 { "applyTorque", w_Body_applyTorque },
669 { "applyForce", w_Body_applyForce },
670 { "setX", w_Body_setX },
671 { "setY", w_Body_setY },
672 { "setLinearVelocity", w_Body_setLinearVelocity },
673 { "setAngle", w_Body_setAngle },
674 { "setAngularVelocity", w_Body_setAngularVelocity },
675 { "setPosition", w_Body_setPosition },
676 { "resetMassData", w_Body_resetMassData },
677 { "setMassData", w_Body_setMassData },
678 { "setMass", w_Body_setMass },
679 { "setInertia", w_Body_setInertia },
680 { "setAngularDamping", w_Body_setAngularDamping },
681 { "setLinearDamping", w_Body_setLinearDamping },
682 { "setGravityScale", w_Body_setGravityScale },
683 { "setType", w_Body_setType },
684 { "getWorldPoint", w_Body_getWorldPoint },
685 { "getWorldVector", w_Body_getWorldVector },
686 { "getWorldPoints", w_Body_getWorldPoints },
687 { "getLocalPoint", w_Body_getLocalPoint },
688 { "getLocalVector", w_Body_getLocalVector },
689 { "getLocalPoints", w_Body_getLocalPoints },
690 { "getLinearVelocityFromWorldPoint", w_Body_getLinearVelocityFromWorldPoint },
691 { "getLinearVelocityFromLocalPoint", w_Body_getLinearVelocityFromLocalPoint },
692 { "isBullet", w_Body_isBullet },
693 { "setBullet", w_Body_setBullet },
694 { "isActive", w_Body_isActive },
695 { "isAwake", w_Body_isAwake },
696 { "setSleepingAllowed", w_Body_setSleepingAllowed },
697 { "isSleepingAllowed", w_Body_isSleepingAllowed },
698 { "setActive", w_Body_setActive },
699 { "setAwake", w_Body_setAwake },
700 { "setFixedRotation", w_Body_setFixedRotation },
701 { "isFixedRotation", w_Body_isFixedRotation },
702 { "isTouching", w_Body_isTouching },
703 { "getWorld", w_Body_getWorld },
704 { "getFixtures", w_Body_getFixtures },
705 { "getJoints", w_Body_getJoints },
706 { "getContacts", w_Body_getContacts },
707 { "destroy", w_Body_destroy },
708 { "isDestroyed", w_Body_isDestroyed },
709 { "setUserData", w_Body_setUserData },
710 { "getUserData", w_Body_getUserData },
711
712 // Deprectaed
713 { "getFixtureList", w_Body_getFixtureList },
714 { "getJointList", w_Body_getJointList },
715 { "getContactList", w_Body_getContactList },
716
717 { 0, 0 }
718};
719
720extern "C" int luaopen_body(lua_State *L)
721{
722 return luax_register_type(L, &Body::type, w_Body_functions, nullptr);
723}
724
725} // box2d
726} // physics
727} // love
728