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