1 /*
2 * box2drevolutejoint.cpp
3 * Copyright (c) 2011 Joonas Erkinheimo <joonas.erkinheimo@nokia.com>
4 * Copyright (c) 2011 Markus Kivioja <markus.kivioja@digia.com>
5 *
6 * This file is part of the Box2D QML plugin.
7 *
8 * This software is provided 'as-is', without any express or implied warranty.
9 * In no event will the authors be held liable for any damages arising from
10 * the use of this software.
11 *
12 * Permission is granted to anyone to use this software for any purpose,
13 * including commercial applications, and to alter it and redistribute it
14 * freely, subject to the following restrictions:
15 *
16 * 1. The origin of this software must not be misrepresented; you must not
17 * claim that you wrote the original software. If you use this software in
18 * a product, an acknowledgment in the product documentation would be
19 * appreciated but is not required.
20 *
21 * 2. Altered source versions must be plainly marked as such, and must not be
22 * misrepresented as being the original software.
23 *
24 * 3. This notice may not be removed or altered from any source distribution.
25 */
26
27 #include "box2drevolutejoint.h"
28
29 #include "box2dworld.h"
30 #include "box2dbody.h"
31
Box2DRevoluteJoint(QObject * parent)32 Box2DRevoluteJoint::Box2DRevoluteJoint(QObject *parent)
33 : Box2DJoint(RevoluteJoint, parent)
34 , m_referenceAngle(0.0f)
35 , m_enableLimit(false)
36 , m_lowerAngle(0.0f)
37 , m_upperAngle(0.0f)
38 , m_enableMotor(false)
39 , m_motorSpeed(0.0f)
40 , m_maxMotorTorque(0.0f)
41 , m_defaultLocalAnchorA(true)
42 , m_defaultLocalAnchorB(true)
43 , m_defaultReferenceAngle(true)
44 {
45 }
46
setLocalAnchorA(const QPointF & localAnchorA)47 void Box2DRevoluteJoint::setLocalAnchorA(const QPointF &localAnchorA)
48 {
49 m_defaultLocalAnchorA = false;
50
51 if (m_localAnchorA == localAnchorA)
52 return;
53
54 m_localAnchorA = localAnchorA;
55 emit localAnchorAChanged();
56 }
57
setLocalAnchorB(const QPointF & localAnchorB)58 void Box2DRevoluteJoint::setLocalAnchorB(const QPointF &localAnchorB)
59 {
60 m_defaultLocalAnchorB = false;
61
62 if (m_localAnchorB == localAnchorB)
63 return;
64
65 m_localAnchorB = localAnchorB;
66 emit localAnchorBChanged();
67 }
68
setReferenceAngle(float referenceAngle)69 void Box2DRevoluteJoint::setReferenceAngle(float referenceAngle)
70 {
71 m_defaultReferenceAngle = false;
72
73 if (m_referenceAngle == referenceAngle)
74 return;
75
76 m_referenceAngle = referenceAngle;
77 emit referenceAngleChanged();
78 }
79
setEnableLimit(bool enableLimit)80 void Box2DRevoluteJoint::setEnableLimit(bool enableLimit)
81 {
82 if (m_enableLimit == enableLimit)
83 return;
84
85 m_enableLimit = enableLimit;
86 if (revoluteJoint())
87 revoluteJoint()->EnableLimit(enableLimit);
88 emit enableLimitChanged();
89 }
90
setLowerAngle(float lowerAngle)91 void Box2DRevoluteJoint::setLowerAngle(float lowerAngle)
92 {
93 if (m_lowerAngle == lowerAngle)
94 return;
95
96 m_lowerAngle = lowerAngle;
97 if (revoluteJoint())
98 revoluteJoint()->SetLimits(toRadians(lowerAngle),
99 toRadians(m_upperAngle));
100 emit lowerAngleChanged();
101 }
102
setUpperAngle(float upperAngle)103 void Box2DRevoluteJoint::setUpperAngle(float upperAngle)
104 {
105 if (m_upperAngle == upperAngle)
106 return;
107
108 m_upperAngle = upperAngle;
109 if (revoluteJoint())
110 revoluteJoint()->SetLimits(toRadians(m_lowerAngle),
111 toRadians(upperAngle));
112 emit upperAngleChanged();
113 }
114
setEnableMotor(bool enableMotor)115 void Box2DRevoluteJoint::setEnableMotor(bool enableMotor)
116 {
117 if (m_enableMotor == enableMotor)
118 return;
119
120 m_enableMotor = enableMotor;
121 if (revoluteJoint())
122 revoluteJoint()->EnableMotor(enableMotor);
123 emit enableMotorChanged();
124 }
125
setMotorSpeed(float motorSpeed)126 void Box2DRevoluteJoint::setMotorSpeed(float motorSpeed)
127 {
128 if (m_motorSpeed == motorSpeed)
129 return;
130
131 m_motorSpeed = motorSpeed;
132 if (revoluteJoint())
133 revoluteJoint()->SetMotorSpeed(toRadians(motorSpeed));
134 emit motorSpeedChanged();
135 }
136
setMaxMotorTorque(float maxMotorTorque)137 void Box2DRevoluteJoint::setMaxMotorTorque(float maxMotorTorque)
138 {
139 if (m_maxMotorTorque == maxMotorTorque)
140 return;
141
142 m_maxMotorTorque = maxMotorTorque;
143 if (revoluteJoint())
144 revoluteJoint()->SetMaxMotorTorque(maxMotorTorque);
145 emit maxMotorTorqueChanged();
146 }
147
createJoint()148 b2Joint *Box2DRevoluteJoint::createJoint()
149 {
150 b2RevoluteJointDef jointDef;
151 initializeJointDef(jointDef);
152
153 // Default localAnchorA to bodyA center
154 if (m_defaultLocalAnchorA)
155 jointDef.localAnchorA = jointDef.bodyA->GetLocalCenter();
156 else
157 jointDef.localAnchorA = world()->toMeters(m_localAnchorA);
158
159 // Default localAnchorB to the same world position as localAnchorA
160 if (m_defaultLocalAnchorB) {
161 b2Vec2 anchorA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
162 jointDef.localAnchorB = jointDef.bodyB->GetLocalPoint(anchorA);
163 } else {
164 jointDef.localAnchorB = world()->toMeters(m_localAnchorB);
165 }
166
167 if (m_defaultReferenceAngle) {
168 float32 angleA = jointDef.bodyA->GetAngle();
169 float32 angleB = jointDef.bodyB->GetAngle();
170 jointDef.referenceAngle = angleB - angleA;
171 } else {
172 jointDef.referenceAngle = toRadians(m_referenceAngle);
173 }
174
175 jointDef.enableLimit = m_enableLimit;
176 jointDef.lowerAngle = toRadians(m_lowerAngle);
177 jointDef.upperAngle = toRadians(m_upperAngle);
178 jointDef.enableMotor = m_enableMotor;
179 jointDef.motorSpeed = toRadians(m_motorSpeed);
180 jointDef.maxMotorTorque = m_maxMotorTorque;
181
182 return world()->world().CreateJoint(&jointDef);
183 }
184
getJointAngle() const185 float Box2DRevoluteJoint::getJointAngle() const
186 {
187 if (revoluteJoint())
188 return toDegrees(revoluteJoint()->GetJointAngle());
189 return 0.0;
190 }
191
getJointSpeed() const192 float Box2DRevoluteJoint::getJointSpeed() const
193 {
194 if (revoluteJoint())
195 return revoluteJoint()->GetJointSpeed();
196 return 0.0;
197 }
198