File indexing completed on 2025-02-02 07:28:26
0001 /* 0002 Copyright 2008-2010 Stefan Majewsky <majewsky@gmx.net> 0003 0004 This program is free software; you can redistribute it and/or modify 0005 it under the terms of the GNU General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or 0007 (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 GNU General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program; if not, write to the Free Software 0016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0017 */ 0018 0019 #ifndef KOLF_SHAPE_H 0020 #define KOLF_SHAPE_H 0021 0022 #include <QPainterPath> 0023 class b2Body; 0024 class b2Fixture; 0025 struct b2FixtureDef; 0026 class b2Shape; 0027 0028 class CanvasItem; 0029 0030 namespace Kolf 0031 { 0032 //All coordinates and units of Kolf's coordinate system are internally 0033 //scaled with the following factor before using them with Box2D, because 0034 //Box2D works best with lengths between 0.1 and 10 metres. 0035 static const qreal Box2DScaleFactor = 0.025; 0036 0037 /** 0038 * @class Kolf::Shape 0039 * 0040 * 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. 0041 */ 0042 class Shape 0043 { 0044 Q_DISABLE_COPY(Shape) 0045 private: 0046 enum TraitBits 0047 { 0048 CollisionDetectionFlag = 1 << 0, 0049 PhysicalSimulationFlag = 1 << 1 0050 }; 0051 public: 0052 ///Defines how a shape behaves. 0053 enum Trait 0054 { 0055 ///This shape is not represented in the physics engine in any way. It only provides an activation and interaction area for the editor interface. 0056 VirtualShape = 0, 0057 ///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. 0058 ParticipatesInCollisionDetection = CollisionDetectionFlag, 0059 ///The shape behaves like physical matter, i.e. it allows the body to move and interact with other bodies through collisions. 0060 ParticipatesInPhysicalSimulation = CollisionDetectionFlag | PhysicalSimulationFlag 0061 }; 0062 Q_DECLARE_FLAGS(Traits, Trait) 0063 ///@warning Any subclass constructor *must* call update() before it exits. 0064 Shape(); 0065 virtual ~Shape(); 0066 0067 ///Returns how this shape behaves. 0068 Kolf::Shape::Traits traits() const; 0069 ///Configures the behavior of this shape. 0070 void setTraits(Kolf::Shape::Traits traits); 0071 0072 ///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. 0073 ///@see ActivationOutlinePadding 0074 QPainterPath activationOutline() const; 0075 ///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. 0076 ///@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). 0077 QPainterPath interactionOutline() const; 0078 protected: 0079 friend class ::CanvasItem; //for the following method 0080 ///Binds this shape to the given @a item. Will fail if this shape is already bound to some item. 0081 bool attach(CanvasItem* item); 0082 0083 ///Call this method when the parameters of this geometry change (usually in setter methods of the subclass). 0084 void update(); 0085 ///Reimplement this method to provide a new b2Shape instance based on the current configuration of the shape. 0086 ///@warning Stuff will break if you return a null pointer. 0087 virtual b2Shape* createShape() = 0; 0088 ///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. 0089 virtual void createOutlines(QPainterPath& activationOutline, QPainterPath& interactionOutline) = 0; 0090 ///Use this padding as distance between the exact InteractionOutline and the fuzzy ActivationOutline. 0091 static const qreal ActivationOutlinePadding; 0092 private: 0093 ///A submethod of update(). 0094 void updateFixture(b2Shape* newShape); 0095 private: 0096 Kolf::Shape::Traits m_traits; 0097 CanvasItem* m_citem; 0098 b2Body* m_body; 0099 b2FixtureDef* m_fixtureDef; 0100 b2Fixture* m_fixture; 0101 b2Shape* m_shape; 0102 QPainterPath m_activationOutline, m_interactionOutline; 0103 }; 0104 0105 class EllipseShape : public Kolf::Shape 0106 { 0107 public: 0108 explicit EllipseShape(const QRectF& rect); 0109 0110 QRectF rect() const; 0111 void setRect(const QRectF& rect); 0112 protected: 0113 b2Shape* createShape() override; 0114 void createOutlines(QPainterPath& activationOutline, QPainterPath& interactionOutline) override; 0115 private: 0116 QRectF m_rect; 0117 }; 0118 0119 class RectShape : public Kolf::Shape 0120 { 0121 public: 0122 explicit RectShape(const QRectF& rect); 0123 0124 QRectF rect() const; 0125 void setRect(const QRectF& rect); 0126 protected: 0127 b2Shape* createShape() override; 0128 void createOutlines(QPainterPath& activationOutline, QPainterPath& interactionOutline) override; 0129 private: 0130 QRectF m_rect; 0131 }; 0132 0133 class LineShape : public Kolf::Shape 0134 { 0135 public: 0136 explicit LineShape(const QLineF& line); 0137 0138 QLineF line() const; 0139 void setLine(const QLineF& line); 0140 protected: 0141 b2Shape* createShape() override; 0142 void createOutlines(QPainterPath& activationOutline, QPainterPath& interactionOutline) override; 0143 private: 0144 QLineF m_line; 0145 }; 0146 } 0147 0148 Q_DECLARE_OPERATORS_FOR_FLAGS(Kolf::Shape::Traits) 0149 0150 #endif // KOLF_SHAPE_H