1 /*
2  * box2dropejoint.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 "box2dropejoint.h"
28 
29 #include "box2dworld.h"
30 
Box2DRopeJoint(QObject * parent)31 Box2DRopeJoint::Box2DRopeJoint(QObject *parent)
32     : Box2DJoint(RopeJoint, parent)
33     , m_maxLength(0.0f)
34     , m_defaultLocalAnchorA(true)
35     , m_defaultLocalAnchorB(true)
36 {
37 }
38 
setLocalAnchorA(const QPointF & localAnchorA)39 void Box2DRopeJoint::setLocalAnchorA(const QPointF &localAnchorA)
40 {
41     m_defaultLocalAnchorA = false;
42 
43     if (m_localAnchorA == localAnchorA)
44         return;
45 
46     m_localAnchorA = localAnchorA;
47     emit localAnchorAChanged();
48 }
49 
setLocalAnchorB(const QPointF & localAnchorB)50 void Box2DRopeJoint::setLocalAnchorB(const QPointF &localAnchorB)
51 {
52     m_defaultLocalAnchorB = false;
53 
54     if (m_localAnchorB == localAnchorB)
55         return;
56 
57     m_localAnchorB = localAnchorB;
58     emit localAnchorBChanged();
59 }
60 
setMaxLength(float maxLength)61 void Box2DRopeJoint::setMaxLength(float maxLength)
62 {
63     if (m_maxLength == maxLength)
64         return;
65 
66     m_maxLength = maxLength;
67     if (ropeJoint()) {
68         const float maxLengthMeters = world()->toMeters(maxLength);
69         if (maxLengthMeters < b2_linearSlop)
70             qWarning() << "RopeJoint: maxLength too small";
71 
72         ropeJoint()->SetMaxLength(maxLengthMeters);
73     }
74     emit maxLengthChanged();
75 }
76 
createJoint()77 b2Joint *Box2DRopeJoint::createJoint()
78 {
79     b2RopeJointDef jointDef;
80     initializeJointDef(jointDef);
81 
82     // Default localAnchorA to bodyA center
83     if (m_defaultLocalAnchorA)
84         jointDef.localAnchorA = jointDef.bodyA->GetLocalCenter();
85     else
86         jointDef.localAnchorA = world()->toMeters(m_localAnchorA);
87 
88     // Default localAnchorB to bodyB center
89     if (m_defaultLocalAnchorB)
90         jointDef.localAnchorB = jointDef.bodyB->GetLocalCenter();
91     else
92         jointDef.localAnchorB = world()->toMeters(m_localAnchorB);
93 
94     jointDef.maxLength = world()->toMeters(m_maxLength);
95 
96     if (jointDef.maxLength < b2_linearSlop)
97         qWarning() << "RopeJoint: maxLength too small";
98 
99     return world()->world().CreateJoint(&jointDef);
100 }
101 
getReactionForce(float32 inv_dt) const102 QPointF Box2DRopeJoint::getReactionForce(float32 inv_dt) const
103 {
104     if (ropeJoint())
105         return invertY(ropeJoint()->GetReactionForce(inv_dt));
106     return QPointF();
107 }
108 
getReactionTorque(float32 inv_dt) const109 float Box2DRopeJoint::getReactionTorque(float32 inv_dt) const
110 {
111     if (ropeJoint())
112         return ropeJoint()->GetReactionTorque(inv_dt);
113     return 0.0f;
114 }
115