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

0001 /*
0002  * box2djoint.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 "box2djoint.h"
0027 #include "box2dworld.h"
0028 #include "box2dbody.h"
0029 
0030 #include <QDebug>
0031 
0032 Box2DJoint::Box2DJoint(JointType jointType, QObject *parent) :
0033     QObject(parent),
0034     mJointType(jointType),
0035     mCollideConnected(false),
0036     mComponentComplete(false),
0037     mInitializePending(false),
0038     mBodyA(0),
0039     mBodyB(0),
0040     mWorld(0),
0041     mJoint(0)
0042 {
0043 }
0044 
0045 Box2DJoint::~Box2DJoint()
0046 {
0047     if (mJoint)
0048         mWorld->world().DestroyJoint(mJoint);
0049 }
0050 
0051 void Box2DJoint::setCollideConnected(bool collideConnected)
0052 {
0053     if (mCollideConnected == collideConnected)
0054         return;
0055 
0056     mCollideConnected = collideConnected;
0057 
0058     emit collideConnectedChanged();
0059 }
0060 
0061 void Box2DJoint::setBodyA(Box2DBody *bodyA)
0062 {
0063     if (mBodyA == bodyA)
0064         return;
0065 
0066     mBodyA = bodyA;
0067 
0068     if (!bodyA || bodyA->body())
0069         initialize();
0070     else
0071         connect(bodyA, SIGNAL(bodyCreated()), this, SLOT(bodyACreated()));
0072 
0073     emit bodyAChanged();
0074 }
0075 
0076 void Box2DJoint::setBodyB(Box2DBody *bodyB)
0077 {
0078     if (mBodyB == bodyB)
0079         return;
0080 
0081     mBodyB = bodyB;
0082 
0083     if (!bodyB || bodyB->body())
0084         initialize();
0085     else
0086         connect(bodyB, SIGNAL(bodyCreated()), this, SLOT(bodyBCreated()));
0087 
0088     emit bodyBChanged();
0089 }
0090 
0091 void Box2DJoint::initialize()
0092 {
0093     // Delay initialization until the component is complete
0094     if (!mComponentComplete) {
0095         mInitializePending = true;
0096         return;
0097     }
0098     mInitializePending = false;
0099 
0100     // Destroy any previously created joint
0101     if (mJoint) {
0102         mWorld->world().DestroyJoint(mJoint);
0103         mJoint = 0;
0104         mWorld = 0;
0105     }
0106 
0107     if (!mBodyA || !mBodyB)
0108         return;
0109     if (!mBodyA->body() || !mBodyB->body())
0110         return;
0111 
0112     if (mBodyA->world() != mBodyB->world()) {
0113         qWarning() << "Joint: bodyA and bodyB are not from the same world";
0114         return;
0115     }
0116 
0117     if (mBodyA == mBodyB) {
0118         qWarning() << "Joint: bodyA and bodyB cannot be the same body";
0119         return;
0120     }
0121 
0122     mWorld = mBodyA->world();
0123     mJoint = createJoint();
0124     if (mJoint)
0125         emit created();
0126 }
0127 
0128 void Box2DJoint::componentComplete()
0129 {
0130     mComponentComplete = true;
0131     if (mInitializePending)
0132         initialize();
0133 }
0134 
0135 void Box2DJoint::initializeJointDef(b2JointDef &def)
0136 {
0137     def.userData = this;
0138     def.bodyA = bodyA()->body();
0139     def.bodyB = bodyB()->body();
0140     def.collideConnected = mCollideConnected;
0141 }
0142 
0143 void Box2DJoint::bodyACreated()
0144 {
0145     disconnect(mBodyA, SIGNAL(bodyCreated()), this, SLOT(bodyACreated()));
0146     initialize();
0147 }
0148 
0149 void Box2DJoint::bodyBCreated()
0150 {
0151     disconnect(mBodyB, SIGNAL(bodyCreated()), this, SLOT(bodyBCreated()));
0152     initialize();
0153 }