File indexing completed on 2024-04-14 14:08:24

0001 /*
0002  * box2drevolutejoint.cpp
0003  * Copyright (c) 2011 Joonas Erkinheimo <joonas.erkinheimo@nokia.com>
0004  * Copyright (c) 2011 Markus Kivioja <markus.kivioja@digia.com>
0005  *
0006  * This file is part of the Box2D QML plugin.
0007  *
0008  * This software is provided 'as-is', without any express or implied warranty.
0009  * In no event will the authors be held liable for any damages arising from
0010  * the use of this software.
0011  *
0012  * Permission is granted to anyone to use this software for any purpose,
0013  * including commercial applications, and to alter it and redistribute it
0014  * freely, subject to the following restrictions:
0015  *
0016  * 1. The origin of this software must not be misrepresented; you must not
0017  *    claim that you wrote the original software. If you use this software in
0018  *    a product, an acknowledgment in the product documentation would be
0019  *    appreciated but is not required.
0020  *
0021  * 2. Altered source versions must be plainly marked as such, and must not be
0022  *    misrepresented as being the original software.
0023  *
0024  * 3. This notice may not be removed or altered from any source distribution.
0025  */
0026 
0027 #include "box2drevolutejoint.h"
0028 
0029 #include "box2dworld.h"
0030 #include "box2dbody.h"
0031 
0032 Box2DRevoluteJoint::Box2DRevoluteJoint(QObject *parent)
0033     : Box2DJoint(RevoluteJoint, parent)
0034     , m_referenceAngle(0.0f)
0035     , m_enableLimit(false)
0036     , m_lowerAngle(0.0f)
0037     , m_upperAngle(0.0f)
0038     , m_enableMotor(false)
0039     , m_motorSpeed(0.0f)
0040     , m_maxMotorTorque(0.0f)
0041     , m_defaultLocalAnchorA(true)
0042     , m_defaultLocalAnchorB(true)
0043     , m_defaultReferenceAngle(true)
0044 {
0045 }
0046 
0047 void Box2DRevoluteJoint::setLocalAnchorA(const QPointF &localAnchorA)
0048 {
0049     m_defaultLocalAnchorA = false;
0050 
0051     if (m_localAnchorA == localAnchorA)
0052         return;
0053 
0054     m_localAnchorA = localAnchorA;
0055     emit localAnchorAChanged();
0056 }
0057 
0058 void Box2DRevoluteJoint::setLocalAnchorB(const QPointF &localAnchorB)
0059 {
0060     m_defaultLocalAnchorB = false;
0061 
0062     if (m_localAnchorB == localAnchorB)
0063         return;
0064 
0065     m_localAnchorB = localAnchorB;
0066     emit localAnchorBChanged();
0067 }
0068 
0069 void Box2DRevoluteJoint::setReferenceAngle(float referenceAngle)
0070 {
0071     m_defaultReferenceAngle = false;
0072 
0073     if (m_referenceAngle == referenceAngle)
0074         return;
0075 
0076     m_referenceAngle = referenceAngle;
0077     emit referenceAngleChanged();
0078 }
0079 
0080 void Box2DRevoluteJoint::setEnableLimit(bool enableLimit)
0081 {
0082     if (m_enableLimit == enableLimit)
0083         return;
0084 
0085     m_enableLimit = enableLimit;
0086     if (revoluteJoint())
0087         revoluteJoint()->EnableLimit(enableLimit);
0088     emit enableLimitChanged();
0089 }
0090 
0091 void Box2DRevoluteJoint::setLowerAngle(float lowerAngle)
0092 {
0093     if (m_lowerAngle == lowerAngle)
0094         return;
0095 
0096     m_lowerAngle = lowerAngle;
0097     if (revoluteJoint())
0098         revoluteJoint()->SetLimits(toRadians(lowerAngle),
0099                                    m_upperAngle);
0100     emit lowerAngleChanged();
0101 }
0102 
0103 void Box2DRevoluteJoint::setUpperAngle(float upperAngle)
0104 {
0105     if (m_upperAngle == upperAngle)
0106         return;
0107 
0108     m_upperAngle = upperAngle;
0109     if (revoluteJoint())
0110         revoluteJoint()->SetLimits(m_lowerAngle,
0111                                    toRadians(upperAngle));
0112     emit upperAngleChanged();
0113 }
0114 
0115 void Box2DRevoluteJoint::setEnableMotor(bool enableMotor)
0116 {
0117     if (m_enableMotor == enableMotor)
0118         return;
0119 
0120     m_enableMotor = enableMotor;
0121     if (revoluteJoint())
0122         revoluteJoint()->EnableMotor(enableMotor);
0123     emit enableMotorChanged();
0124 }
0125 
0126 void Box2DRevoluteJoint::setMotorSpeed(float motorSpeed)
0127 {
0128     if (m_motorSpeed == motorSpeed)
0129         return;
0130 
0131     m_motorSpeed = motorSpeed;
0132     if (revoluteJoint())
0133         revoluteJoint()->SetMotorSpeed(toRadians(motorSpeed));
0134     emit motorSpeedChanged();
0135 }
0136 
0137 void Box2DRevoluteJoint::setMaxMotorTorque(float maxMotorTorque)
0138 {
0139     if (m_maxMotorTorque == maxMotorTorque)
0140         return;
0141 
0142     m_maxMotorTorque = maxMotorTorque;
0143     if (revoluteJoint())
0144         revoluteJoint()->SetMaxMotorTorque(maxMotorTorque);
0145     emit maxMotorTorqueChanged();
0146 }
0147 
0148 b2Joint *Box2DRevoluteJoint::createJoint()
0149 {
0150     b2RevoluteJointDef jointDef;
0151     initializeJointDef(jointDef);
0152 
0153     // Default localAnchorA to bodyA center
0154     if (m_defaultLocalAnchorA)
0155         jointDef.localAnchorA = jointDef.bodyA->GetLocalCenter();
0156     else
0157         jointDef.localAnchorA = world()->toMeters(m_localAnchorA);
0158 
0159     // Default localAnchorB to the same world position as localAnchorA
0160     if (m_defaultLocalAnchorB) {
0161         b2Vec2 anchorA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
0162         jointDef.localAnchorB = jointDef.bodyB->GetLocalPoint(anchorA);
0163     } else {
0164         jointDef.localAnchorB = world()->toMeters(m_localAnchorB);
0165     }
0166 
0167     if (m_defaultReferenceAngle) {
0168         float32 angleA = jointDef.bodyA->GetAngle();
0169         float32 angleB = jointDef.bodyB->GetAngle();
0170         jointDef.referenceAngle = angleB - angleA;
0171     } else {
0172         jointDef.referenceAngle = toRadians(m_referenceAngle);
0173     }
0174 
0175     jointDef.enableLimit = m_enableLimit;
0176     jointDef.lowerAngle = toRadians(m_lowerAngle);
0177     jointDef.upperAngle = toRadians(m_upperAngle);
0178     jointDef.enableMotor = m_enableMotor;
0179     jointDef.motorSpeed = toRadians(m_motorSpeed);
0180     jointDef.maxMotorTorque = m_maxMotorTorque;
0181 
0182     return world()->world().CreateJoint(&jointDef);
0183 }
0184 
0185 float Box2DRevoluteJoint::getJointAngle() const
0186 {
0187     if (revoluteJoint())
0188         return toDegrees(revoluteJoint()->GetJointAngle());
0189     return 0.0;
0190 }
0191 
0192 float Box2DRevoluteJoint::getJointSpeed() const
0193 {
0194     if (revoluteJoint())
0195         return revoluteJoint()->GetJointSpeed();
0196     return 0.0;
0197 }