1 /*
2  * box2dbody.h
3  * Copyright (c) 2010-2011 Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
4  * Copyright (c) 2011 Daker Fernandes Pinheiro <daker.pinheiro@openbossa.org>
5  * Copyright (c) 2011 Tan Miaoqing <miaoqing.tan@nokia.com>
6  * Copyright (c) 2011 Antonio Aloisio <antonio.aloisio@nokia.com>
7  * Copyright (c) 2011 Joonas Erkinheimo <joonas.erkinheimo@nokia.com>
8  * Copyright (c) 2011 Antti Krats <antti.krats@digia.com>
9  *
10  * This file is part of the Box2D QML plugin.
11  *
12  * This software is provided 'as-is', without any express or implied warranty.
13  * In no event will the authors be held liable for any damages arising from
14  * the use of this software.
15  *
16  * Permission is granted to anyone to use this software for any purpose,
17  * including commercial applications, and to alter it and redistribute it
18  * freely, subject to the following restrictions:
19  *
20  * 1. The origin of this software must not be misrepresented; you must not
21  *    claim that you wrote the original software. If you use this software in
22  *    a product, an acknowledgment in the product documentation would be
23  *    appreciated but is not required.
24  *
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  *
28  * 3. This notice may not be removed or altered from any source distribution.
29  */
30 
31 #ifndef BOX2DBODY_H
32 #define BOX2DBODY_H
33 
34 #include <QQuickItem>
35 #include <Box2D.h>
36 
37 class Box2DFixture;
38 class Box2DWorld;
39 
40 /**
41  * The Box2D body, build up from a list of shapes.
42  */
43 class Box2DBody : public QObject, public QQmlParserStatus
44 {
45     Q_OBJECT
46 
47     Q_ENUMS(BodyType)
48     Q_PROPERTY(Box2DWorld *world READ world WRITE setWorld NOTIFY worldChanged)
49     Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
50     Q_PROPERTY(float linearDamping READ linearDamping WRITE setLinearDamping NOTIFY linearDampingChanged)
51     Q_PROPERTY(float angularDamping READ angularDamping WRITE setAngularDamping NOTIFY angularDampingChanged)
52     Q_PROPERTY(BodyType bodyType READ bodyType WRITE setBodyType NOTIFY bodyTypeChanged)
53     Q_PROPERTY(bool bullet READ isBullet WRITE setBullet NOTIFY bulletChanged)
54     Q_PROPERTY(bool sleepingAllowed READ sleepingAllowed WRITE setSleepingAllowed NOTIFY sleepingAllowedChanged)
55     Q_PROPERTY(bool fixedRotation READ fixedRotation WRITE setFixedRotation NOTIFY fixedRotationChanged)
56     Q_PROPERTY(bool active READ isActive WRITE setActive)
57     Q_PROPERTY(bool awake READ isAwake WRITE setAwake)
58     Q_PROPERTY(QPointF linearVelocity READ linearVelocity WRITE setLinearVelocity NOTIFY linearVelocityChanged)
59     Q_PROPERTY(float angularVelocity READ angularVelocity WRITE setAngularVelocity NOTIFY angularVelocityChanged)
60     Q_PROPERTY(QQmlListProperty<Box2DFixture> fixtures READ fixtures)
61     Q_PROPERTY(float gravityScale READ gravityScale WRITE setGravityScale NOTIFY gravityScaleChanged)
62 
63     Q_INTERFACES(QQmlParserStatus)
64     Q_CLASSINFO("DefaultProperty", "fixtures")
65 
66 public:
67     enum BodyType {
68         Static = 0,
69         Kinematic,
70         Dynamic
71     };
72 
73     explicit Box2DBody(QObject *parent = 0);
74     ~Box2DBody();
75 
76     Box2DWorld *world() const;
77     void setWorld(Box2DWorld *world);
78 
79     QQuickItem *target() const;
80     void setTarget(QQuickItem *target);
81 
82     float linearDamping() const;
83     void setLinearDamping(float linearDamping);
84 
85     float angularDamping() const;
86     void setAngularDamping(float angularDamping);
87 
88     BodyType bodyType() const;
89     void setBodyType(BodyType bodyType);
90 
91     bool isBullet() const;
92     void setBullet(bool bullet);
93 
94     bool sleepingAllowed() const;
95     void setSleepingAllowed(bool sleepingAllowed);
96 
97     bool fixedRotation() const;
98     void setFixedRotation(bool fixedRotation);
99 
100     bool isActive() const;
101     void setActive(bool active);
102 
103     bool isAwake() const;
104     void setAwake(bool awake);
105 
106     QPointF linearVelocity() const;
107     void setLinearVelocity(const QPointF &velocity);
108 
109     float angularVelocity() const;
110     void setAngularVelocity(float velocity);
111 
112     float gravityScale() const;
113     void setGravityScale(float gravityScale);
114 
115     QQmlListProperty<Box2DFixture> fixtures();
116 
117     void synchronize();
118     void nullifyBody();
119 
120     Q_INVOKABLE void applyForce(const QPointF &force, const QPointF &point);
121     Q_INVOKABLE void applyForceToCenter(const QPointF &force);
122     Q_INVOKABLE void applyTorque(qreal torque);
123     Q_INVOKABLE void applyLinearImpulse(const QPointF &impulse, const QPointF &point);
124     Q_INVOKABLE void applyAngularImpulse(qreal impulse);
125     Q_INVOKABLE QPointF getWorldCenter() const;
126     Q_INVOKABLE QPointF getLocalCenter() const;
127     Q_INVOKABLE float getMass() const;
128     Q_INVOKABLE void resetMassData();
129     Q_INVOKABLE float getInertia() const;
130     Q_INVOKABLE QPointF toWorldPoint(const QPointF &localPoint) const;
131     Q_INVOKABLE QPointF toWorldVector(const QPointF &localVector) const;
132     Q_INVOKABLE QPointF toLocalPoint(const QPointF &worldPoint) const;
133     Q_INVOKABLE QPointF toLocalVector(const QPointF &worldVector) const;
134     Q_INVOKABLE QPointF getLinearVelocityFromWorldPoint(const QPointF &point) const;
135     Q_INVOKABLE QPointF getLinearVelocityFromLocalPoint(const QPointF &point) const;
136     Q_INVOKABLE void addFixture(Box2DFixture *fixture);
137 
138     void classBegin();
139     void componentComplete();
140 
141     b2Body *body() const;
142 
143     bool transformDirty() const;
144     void updateTransform();
145 
146 signals:
147     void worldChanged();
148     void targetChanged();
149     void linearDampingChanged();
150     void angularDampingChanged();
151     void bodyTypeChanged();
152     void bulletChanged();
153     void sleepingAllowedChanged();
154     void fixedRotationChanged();
155     void linearVelocityChanged();
156     void angularVelocityChanged();
157     void bodyCreated();
158     void gravityScaleChanged();
159     void positionChanged();
160 
161 private slots:
162     void markTransformDirty();
163     void onWorldPixelsPerMeterChanged();
164 
165 private:
166     void createBody();
167 
168     Box2DWorld *mWorld;
169     QQuickItem *mTarget;
170     b2Body *mBody;
171     b2BodyDef mBodyDef;
172     bool mComponentComplete;
173     bool mTransformDirty;
174     bool mCreatePending;
175     QList<Box2DFixture*> mFixtures;
176 
177     static void append_fixture(QQmlListProperty<Box2DFixture> *list,
178                                Box2DFixture *fixture);
179     static int count_fixture(QQmlListProperty<Box2DFixture> *list);
180     static Box2DFixture *at_fixture(QQmlListProperty<Box2DFixture> *list, int index);
181     QPointF originOffset() const;
182 };
183 
target()184 inline QQuickItem *Box2DBody::target() const
185 {
186     return mTarget;
187 }
188 
linearDamping()189 inline float Box2DBody::linearDamping() const
190 {
191     return mBodyDef.linearDamping;
192 }
193 
angularDamping()194 inline float Box2DBody::angularDamping() const
195 {
196     return mBodyDef.angularDamping;
197 }
198 
bodyType()199 inline Box2DBody::BodyType Box2DBody::bodyType() const
200 {
201     return static_cast<Box2DBody::BodyType>(mBodyDef.type);
202 }
203 
isBullet()204 inline bool Box2DBody::isBullet() const
205 {
206     return mBodyDef.bullet;
207 }
208 
sleepingAllowed()209 inline bool Box2DBody::sleepingAllowed() const
210 {
211     return mBodyDef.allowSleep;
212 }
213 
fixedRotation()214 inline bool Box2DBody::fixedRotation() const
215 {
216     return mBodyDef.fixedRotation;
217 }
218 
isActive()219 inline bool Box2DBody::isActive() const
220 {
221     return mBodyDef.active;
222 }
223 
gravityScale()224 inline float Box2DBody::gravityScale() const
225 {
226     return mBodyDef.gravityScale;
227 }
228 
nullifyBody()229 inline void Box2DBody::nullifyBody()
230 {
231     mBody = 0;
232 }
233 
body()234 inline b2Body *Box2DBody::body() const
235 {
236     return mBody;
237 }
238 
world()239 inline Box2DWorld *Box2DBody::world() const
240 {
241     return mWorld;
242 }
243 
transformDirty()244 inline bool Box2DBody::transformDirty() const
245 {
246     return mTransformDirty;
247 }
248 
249 
250 /**
251  * Convenience function to get the Box2DBody wrapping a b2Body.
252  */
toBox2DBody(b2Body * body)253 inline Box2DBody *toBox2DBody(b2Body *body)
254 {
255     return static_cast<Box2DBody*>(body->GetUserData());
256 }
257 
258 #endif // BOX2DBODY_H
259