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 "Joint.h" |
22 | |
23 | // STD |
24 | #include <bitset> |
25 | |
26 | // Module |
27 | #include "Body.h" |
28 | #include "World.h" |
29 | #include "Physics.h" |
30 | |
31 | |
32 | namespace love |
33 | { |
34 | namespace physics |
35 | { |
36 | namespace box2d |
37 | { |
38 | |
39 | Joint::Joint(Body *body1) |
40 | : world(body1->world) |
41 | , udata(nullptr) |
42 | , body1(body1) |
43 | , body2(nullptr) |
44 | { |
45 | udata = new jointudata(); |
46 | udata->ref = nullptr; |
47 | } |
48 | |
49 | Joint::Joint(Body *body1, Body *body2) |
50 | : world(body1->world) |
51 | , udata(nullptr) |
52 | , body1(body1) |
53 | , body2(body2) |
54 | { |
55 | udata = new jointudata(); |
56 | udata->ref = nullptr; |
57 | } |
58 | |
59 | Joint::~Joint() |
60 | { |
61 | if (!udata) |
62 | return; |
63 | |
64 | if (udata->ref) |
65 | delete udata->ref; |
66 | |
67 | delete udata; |
68 | } |
69 | |
70 | Joint::Type Joint::getType() const |
71 | { |
72 | switch (joint->GetType()) |
73 | { |
74 | case e_revoluteJoint: |
75 | return JOINT_REVOLUTE; |
76 | case e_prismaticJoint: |
77 | return JOINT_PRISMATIC; |
78 | case e_distanceJoint: |
79 | return JOINT_DISTANCE; |
80 | case e_pulleyJoint: |
81 | return JOINT_PULLEY; |
82 | case e_mouseJoint: |
83 | return JOINT_MOUSE; |
84 | case e_gearJoint: |
85 | return JOINT_GEAR; |
86 | case e_frictionJoint: |
87 | return JOINT_FRICTION; |
88 | case e_weldJoint: |
89 | return JOINT_WELD; |
90 | case e_wheelJoint: |
91 | return JOINT_WHEEL; |
92 | case e_ropeJoint: |
93 | return JOINT_ROPE; |
94 | case e_motorJoint: |
95 | return JOINT_MOTOR; |
96 | default: |
97 | return JOINT_INVALID; |
98 | } |
99 | } |
100 | |
101 | Body *Joint::getBodyA() const |
102 | { |
103 | b2Body *b2body = joint->GetBodyA(); |
104 | if (b2body == nullptr) |
105 | return nullptr; |
106 | |
107 | Body *body = (Body *) world->findObject(b2body); |
108 | if (body == nullptr) |
109 | throw love::Exception("A body has escaped Memoizer!" ); |
110 | |
111 | return body; |
112 | } |
113 | |
114 | Body *Joint::getBodyB() const |
115 | { |
116 | b2Body *b2body = joint->GetBodyB(); |
117 | if (b2body == nullptr) |
118 | return nullptr; |
119 | |
120 | Body *body = (Body *) world->findObject(b2body); |
121 | if (body == nullptr) |
122 | throw love::Exception("A body has escaped Memoizer!" ); |
123 | |
124 | return body; |
125 | } |
126 | |
127 | bool Joint::isValid() const |
128 | { |
129 | return joint != nullptr; |
130 | } |
131 | |
132 | int Joint::getAnchors(lua_State *L) |
133 | { |
134 | lua_pushnumber(L, Physics::scaleUp(joint->GetAnchorA().x)); |
135 | lua_pushnumber(L, Physics::scaleUp(joint->GetAnchorA().y)); |
136 | lua_pushnumber(L, Physics::scaleUp(joint->GetAnchorB().x)); |
137 | lua_pushnumber(L, Physics::scaleUp(joint->GetAnchorB().y)); |
138 | return 4; |
139 | } |
140 | |
141 | int Joint::getReactionForce(lua_State *L) |
142 | { |
143 | float dt = (float)luaL_checknumber(L, 1); |
144 | b2Vec2 v = Physics::scaleUp(joint->GetReactionForce(dt)); |
145 | lua_pushnumber(L, v.x); |
146 | lua_pushnumber(L, v.y); |
147 | return 2; |
148 | } |
149 | |
150 | float Joint::getReactionTorque(float dt) |
151 | { |
152 | return Physics::scaleUp(Physics::scaleUp(joint->GetReactionTorque(dt))); |
153 | } |
154 | |
155 | b2Joint *Joint::createJoint(b2JointDef *def) |
156 | { |
157 | def->userData = udata; |
158 | joint = world->world->CreateJoint(def); |
159 | world->registerObject(joint, this); |
160 | // Box2D joint has a reference to this love Joint. |
161 | this->retain(); |
162 | return joint; |
163 | } |
164 | |
165 | void Joint::destroyJoint(bool implicit) |
166 | { |
167 | if (world->world->IsLocked()) |
168 | { |
169 | // Called during time step. Save reference for destruction afterwards. |
170 | this->retain(); |
171 | world->destructJoints.push_back(this); |
172 | return; |
173 | } |
174 | |
175 | if (!implicit && joint != nullptr) |
176 | world->world->DestroyJoint(joint); |
177 | world->unregisterObject(joint); |
178 | joint = NULL; |
179 | |
180 | // Remove userdata reference to avoid it sticking around after GC |
181 | if (udata && udata->ref) |
182 | udata->ref->unref(); |
183 | |
184 | // Release the reference of the Box2D joint. |
185 | this->release(); |
186 | } |
187 | |
188 | bool Joint::isActive() const |
189 | { |
190 | return joint->IsActive(); |
191 | } |
192 | |
193 | bool Joint::getCollideConnected() const |
194 | { |
195 | return joint->GetCollideConnected(); |
196 | } |
197 | |
198 | int Joint::setUserData(lua_State *L) |
199 | { |
200 | love::luax_assert_argc(L, 1, 1); |
201 | |
202 | if (udata == nullptr) |
203 | { |
204 | udata = new jointudata(); |
205 | joint->SetUserData((void *) udata); |
206 | } |
207 | |
208 | if(!udata->ref) |
209 | udata->ref = new Reference(); |
210 | |
211 | udata->ref->ref(L); |
212 | |
213 | return 0; |
214 | } |
215 | |
216 | int Joint::getUserData(lua_State *L) |
217 | { |
218 | if (udata != nullptr && udata->ref != nullptr) |
219 | udata->ref->push(L); |
220 | else |
221 | lua_pushnil(L); |
222 | |
223 | return 1; |
224 | } |
225 | |
226 | } // box2d |
227 | } // physics |
228 | } // love |
229 | |