1/*
2 Copyright 2008-2010 Stefan Majewsky <majewsky@gmx.net>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#ifndef KOLF_SHAPE_H
20#define KOLF_SHAPE_H
21
22#include <QPainterPath>
23class b2Body;
24class b2Fixture;
25class b2FixtureDef;
26class b2Shape;
27
28class CanvasItem;
29
30namespace Kolf
31{
32 //All coordinates and units of Kolf's coordinate system are internally
33 //scaled with the following factor before using them with Box2D, because
34 //Box2D works best with lengths between 0.1 and 10 metres.
35 static const qreal Box2DScaleFactor = 0.025;
36
37 /**
38 * @class Kolf::Shape
39 *
40 * This class represents a part of the shape of an item. Simple objects can be represented by a single shape (e.g. boxes and spheres), while complex objects may have to be constructed with multiple shapes.
41 */
42 class Shape
43 {
44 Q_DISABLE_COPY(Shape)
45 private:
46 enum TraitBits
47 {
48 CollisionDetectionFlag = 1 << 0,
49 PhysicalSimulationFlag = 1 << 1
50 };
51 public:
52 ///Defines how a shape behaves.
53 enum Trait
54 {
55 ///This shape is not represented in the physics engine in any way. It only provides an activation and interaction area for the editor interface.
56 VirtualShape = 0,
57 ///During each step of the physical simulation, this shape is checked for intersections with other shapes, and the registered Kolf::ContactCallback methods are called as appropriate.
58 ParticipatesInCollisionDetection = CollisionDetectionFlag,
59 ///The shape behaves like physical matter, i.e. it allows the body to move and interact with other bodies through collisions.
60 ParticipatesInPhysicalSimulation = CollisionDetectionFlag | PhysicalSimulationFlag
61 };
62 Q_DECLARE_FLAGS(Traits, Trait)
63 ///@warning Any subclass constructor *must* call update() before it exits.
64 Shape();
65 virtual ~Shape();
66
67 ///Returns how this shape behaves.
68 Kolf::Shape::Traits traits() const;
69 ///Configures the behavior of this shape.
70 void setTraits(Kolf::Shape::Traits traits);
71
72 ///Returns the two-dimensional activation outline, i.e. the area of this geometry (plus some defined padding). The editor overlay is supposed to activate the editor interface of the object associated with this geometry, if a mouse click occurs inside the activation outline.
73 ///@see ActivationOutlinePadding
74 QPainterPath activationOutline() const;
75 ///Returns the two-dimensional interaction outline, i.e. the exact outline of this geometry. The editor overlay is supposed to move the object associated with this geometry, if the mouse is clicked inside the interaction outline and then dragged.
76 ///@note The interaction outline is allowed to be greater than the object's exact shape for the sake of usability (e.g. a diagonal wall cannot be precisely hit with a mouse cursor).
77 QPainterPath interactionOutline() const;
78 protected:
79 friend class ::CanvasItem; //for the following method
80 ///Binds this shape to the given @a item. Will fail if this shape is already bound to some item.
81 bool attach(CanvasItem* item);
82
83 ///Call this method when the parameters of this geometry change (usually in setter methods of the subclass).
84 void update();
85 ///Reimplement this method to provide a new b2Shape instance based on the current configuration of the shape.
86 ///@warning Stuff will break if you return a null pointer.
87 virtual b2Shape* createShape() = 0;
88 ///Reimplement this method to create the outlines of this geometry and pass them to the caller via the arguments. You will not have to call this function in subclass implementations, it's invoked by Kolf::Geometry::update.
89 virtual void createOutlines(QPainterPath& activationOutline, QPainterPath& interactionOutline) = 0;
90 ///Use this padding as distance between the exact InteractionOutline and the fuzzy ActivationOutline.
91 static const qreal ActivationOutlinePadding;
92 private:
93 ///A submethod of update().
94 void updateFixture(b2Shape* newShape);
95 private:
96 Kolf::Shape::Traits m_traits;
97 CanvasItem* m_citem;
98 b2Body* m_body;
99 b2FixtureDef* m_fixtureDef;
100 b2Fixture* m_fixture;
101 b2Shape* m_shape;
102 QPainterPath m_activationOutline, m_interactionOutline;
103 };
104
105 class EllipseShape : public Kolf::Shape
106 {
107 public:
108 EllipseShape(const QRectF& rect);
109
110 QRectF rect() const;
111 void setRect(const QRectF& rect);
112 protected:
113 virtual b2Shape* createShape();
114 virtual void createOutlines(QPainterPath& activationOutline, QPainterPath& interactionOutline);
115 private:
116 QRectF m_rect;
117 };
118
119 class RectShape : public Kolf::Shape
120 {
121 public:
122 RectShape(const QRectF& rect);
123
124 QRectF rect() const;
125 void setRect(const QRectF& rect);
126 protected:
127 virtual b2Shape* createShape();
128 virtual void createOutlines(QPainterPath& activationOutline, QPainterPath& interactionOutline);
129 private:
130 QRectF m_rect;
131 };
132
133 class LineShape : public Kolf::Shape
134 {
135 public:
136 LineShape(const QLineF& line);
137
138 QLineF line() const;
139 void setLine(const QLineF& line);
140 protected:
141 virtual b2Shape* createShape();
142 virtual void createOutlines(QPainterPath& activationOutline, QPainterPath& interactionOutline);
143 private:
144 QLineF m_line;
145 };
146}
147
148Q_DECLARE_OPERATORS_FOR_FLAGS(Kolf::Shape::Traits)
149
150#endif // KOLF_SHAPE_H
151