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

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