1 /*
2  * box2dfixture.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 Alessandro Portale <alessandro.portale@nokia.com>
6  *
7  * This file is part of the Box2D QML plugin.
8  *
9  * This software is provided 'as-is', without any express or implied warranty.
10  * In no event will the authors be held liable for any damages arising from
11  * the use of this software.
12  *
13  * Permission is granted to anyone to use this software for any purpose,
14  * including commercial applications, and to alter it and redistribute it
15  * freely, subject to the following restrictions:
16  *
17  * 1. The origin of this software must not be misrepresented; you must not
18  *    claim that you wrote the original software. If you use this software in
19  *    a product, an acknowledgment in the product documentation would be
20  *    appreciated but is not required.
21  *
22  * 2. Altered source versions must be plainly marked as such, and must not be
23  *    misrepresented as being the original software.
24  *
25  * 3. This notice may not be removed or altered from any source distribution.
26  */
27 
28 #ifndef BOX2DFIXTURE_H
29 #define BOX2DFIXTURE_H
30 
31 #include <QQuickItem>
32 #include <QFlags>
33 
34 #include <Box2D.h>
35 
36 class Box2DBody;
37 
38 class Box2DFixture : public QObject
39 {
40     Q_OBJECT
41 
42     Q_PROPERTY(float density READ density WRITE setDensity NOTIFY densityChanged)
43     Q_PROPERTY(float friction READ friction WRITE setFriction NOTIFY frictionChanged)
44     Q_PROPERTY(float restitution READ restitution WRITE setRestitution NOTIFY restitutionChanged)
45     Q_PROPERTY(bool sensor READ isSensor WRITE setSensor NOTIFY sensorChanged)
46     Q_PROPERTY(CategoryFlags categories READ categories WRITE setCategories NOTIFY categoriesChanged)
47     Q_PROPERTY(CategoryFlags collidesWith READ collidesWith WRITE setCollidesWith NOTIFY collidesWithChanged)
48     Q_PROPERTY(int groupIndex READ groupIndex WRITE setGroupIndex NOTIFY groupIndexChanged)
49 
50     Q_ENUMS(CategoryFlag)
51     Q_FLAGS(CategoryFlags)
52 
53 public:
54     explicit Box2DFixture(QObject *parent = 0);
55 
56     enum CategoryFlag {Category1 = 0x0001, Category2 = 0x0002, Category3 = 0x0004, Category4 = 0x0008,
57                        Category5 = 0x0010, Category6 = 0x0020, Category7 = 0x0040, Category8 = 0x0080,
58                        Category9 = 0x0100, Category10 = 0x0200, Category11 = 0x0400, Category12 = 0x0800,
59                        Category13 = 0x1000, Category14 = 0x2000, Category15 = 0x4000, Category16 = 0x8000,
60                        All = 0xFFFF, None=0x0000};
61 
62     Q_DECLARE_FLAGS(CategoryFlags, CategoryFlag)
63 
64     float density() const;
65     void setDensity(float density);
66 
67     float friction() const;
68     void setFriction(float friction);
69 
70     float restitution() const;
71     void setRestitution(float restitution);
72 
73     bool isSensor() const;
74     void setSensor(bool sensor);
75 
76     CategoryFlags categories() const;
77     void setCategories(CategoryFlags layers);
78 
79     CategoryFlags collidesWith() const;
80     void setCollidesWith(CategoryFlags layers);
81 
82     int groupIndex() const;
83     void setGroupIndex(int groupIndex);
84 
85     void initialize(Box2DBody *body);
86     void recreateFixture();
87 
88     Q_INVOKABLE Box2DBody *getBody() const;
89 
90 signals:
91     void densityChanged();
92     void frictionChanged();
93     void restitutionChanged();
94     void sensorChanged();
95     void categoriesChanged();
96     void collidesWithChanged();
97     void groupIndexChanged();
98 
99     void beginContact(Box2DFixture *other);
100     void endContact(Box2DFixture *other);
101 
102 protected:
103     virtual b2Shape *createShape() = 0;
104 
105     b2Fixture *mFixture;
106     b2FixtureDef mFixtureDef;
107     Box2DBody *mBody;
108 };
109 
Q_DECLARE_OPERATORS_FOR_FLAGS(Box2DFixture::CategoryFlags)110 Q_DECLARE_OPERATORS_FOR_FLAGS(Box2DFixture::CategoryFlags)
111 
112 class Box2DBox : public Box2DFixture
113 {
114     Q_OBJECT
115 
116     Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
117     Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
118     Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged)
119     Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged)
120     Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
121 
122 public:
123     explicit Box2DBox(QQuickItem *parent = 0)
124         : Box2DFixture(parent)
125         , mPosition(0, 0)
126         , mSize(0, 0)
127         , mRotation(0)
128     {}
129 
130     qreal x() const { return mPosition.x(); }
131     void setX(qreal x);
132 
133     qreal y() const { return mPosition.y(); }
134     void setY(qreal y);
135 
136     qreal width() const { return mSize.width(); }
137     void setWidth(qreal width);
138 
139     qreal height() const { return mSize.height(); }
140     void setHeight(qreal height);
141 
142     qreal rotation() const { return mRotation; }
143     void setRotation(qreal rotation);
144 
145 signals:
146     void xChanged();
147     void yChanged();
148     void widthChanged();
149     void heightChanged();
150     void rotationChanged();
151 
152 protected:
153     void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
154 
155     b2Shape *createShape();
156 
157 private:
158     QPointF mPosition;
159     QSizeF mSize;
160     qreal mRotation;
161 };
162 
163 
164 class Box2DCircle : public Box2DFixture
165 {
166     Q_OBJECT
167 
Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)168     Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
169     Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
170     Q_PROPERTY(float radius READ radius WRITE setRadius NOTIFY radiusChanged)
171 
172 public:
173     explicit Box2DCircle(QQuickItem *parent = 0)
174         : Box2DFixture(parent)
175         , mPosition(0, 0)
176         , mRadius(32)
177     { }
178 
x()179     qreal x() const { return mPosition.x(); }
180     void setX(qreal x);
181 
y()182     qreal y() const { return mPosition.y(); }
183     void setY(qreal y);
184 
position()185     QPointF position() const { return mPosition; }
186 
radius()187     float radius() const { return mRadius; }
188     void setRadius(float radius);
189 
190 signals:
191     void xChanged();
192     void yChanged();
193     void radiusChanged();
194 
195 protected:
196     b2Shape *createShape();
197 
198 private:
199     QPointF mPosition;
200     float mRadius;
201 };
202 
203 
204 class Box2DPolygon : public Box2DFixture
205 {
206     Q_OBJECT
207 
Q_PROPERTY(QVariantList vertices READ vertices WRITE setVertices NOTIFY verticesChanged)208     Q_PROPERTY(QVariantList vertices READ vertices WRITE setVertices NOTIFY verticesChanged)
209 
210 public:
211     explicit Box2DPolygon(QQuickItem *parent = 0) :
212         Box2DFixture(parent)
213     { }
214 
vertices()215     QVariantList vertices() const { return mVertices; }
216     void setVertices(const QVariantList &vertices);
217 
218 signals:
219     void verticesChanged();
220 
221 protected:
222     b2Shape *createShape();
223 
224 private:
225     QVariantList mVertices;
226 };
227 
228 
229 class Box2DChain : public Box2DFixture
230 {
231     Q_OBJECT
232 
233     Q_PROPERTY(QVariantList vertices READ vertices WRITE setVertices NOTIFY verticesChanged)
234     Q_PROPERTY(bool loop READ loop WRITE setLoop NOTIFY loopChanged)
235     Q_PROPERTY(QPointF prevVertex READ prevVertex WRITE setPrevVertex NOTIFY prevVertexChanged)
236     Q_PROPERTY(QPointF nextVertex READ nextVertex WRITE setNextVertex NOTIFY nextVertexChanged)
237 
238 public:
239     explicit Box2DChain(QQuickItem *parent = 0);
240 
vertices()241     QVariantList vertices() const { return mVertices; }
242     void setVertices(const QVariantList &vertices);
243 
loop()244     bool loop() const { return mLoop; }
245     void setLoop(bool loop);
246 
prevVertex()247     QPointF prevVertex() const { return mPrevVertex; }
248     void setPrevVertex(const QPointF &prevVertex);
249 
nextVertex()250     QPointF nextVertex() const { return mNextVertex; }
251     void setNextVertex(const QPointF &nextVertex);
252 
253 signals:
254     void verticesChanged();
255     void loopChanged();
256     void prevVertexChanged();
257     void nextVertexChanged();
258 
259 protected:
260     b2Shape *createShape();
261 
262 private:
263     QVariantList mVertices;
264     QPointF mPrevVertex;
265     QPointF mNextVertex;
266     bool mLoop;
267     bool mPrevVertexFlag;
268     bool mNextVertexFlag;
269 };
270 
271 
272 class Box2DEdge : public Box2DFixture
273 {
274     Q_OBJECT
275 
Q_PROPERTY(QVariantList vertices READ vertices WRITE setVertices NOTIFY verticesChanged)276     Q_PROPERTY(QVariantList vertices READ vertices WRITE setVertices NOTIFY verticesChanged)
277 
278 public:
279     explicit Box2DEdge(QQuickItem *parent = 0) :
280         Box2DFixture(parent)
281     { }
282 
vertices()283     QVariantList vertices() const { return mVertices; }
284     void setVertices(const QVariantList &vertices);
285 
286 signals:
287     void verticesChanged();
288 
289 protected:
290     b2Shape *createShape();
291 
292 private:
293     QVariantList mVertices;
294 };
295 
296 
297 /**
298  * Convenience function to get the Box2DFixture wrapping a b2Fixture.
299  */
toBox2DFixture(b2Fixture * fixture)300 inline Box2DFixture *toBox2DFixture(b2Fixture *fixture)
301 {
302     return static_cast<Box2DFixture*>(fixture->GetUserData());
303 }
304 
305 
306 #endif // BOX2DFIXTURE_H
307