1 /*
2  * mapobject.h
3  * Copyright 2008-2013, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
4  * Copyright 2008, Roderic Morris <roderic@ccs.neu.edu>
5  * Copyright 2009, Jeff Bland <jeff@teamphobic.com>
6  *
7  * This file is part of libtiled.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  *    1. Redistributions of source code must retain the above copyright notice,
13  *       this list of conditions and the following disclaimer.
14  *
15  *    2. Redistributions in binary form must reproduce the above copyright
16  *       notice, this list of conditions and the following disclaimer in the
17  *       documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22  * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #pragma once
32 
33 #include "object.h"
34 #include "tiled.h"
35 #include "tilelayer.h"
36 
37 #include <QFont>
38 #include <QPolygonF>
39 #include <QRectF>
40 #include <QSizeF>
41 #include <QString>
42 #include <QTextOption>
43 
44 namespace Tiled {
45 
46 class MapRenderer;
47 class ObjectGroup;
48 class ObjectTemplate;
49 class Tile;
50 
51 struct TILEDSHARED_EXPORT TextData
52 {
53     TextData();
54 
55     QString text;
56     QFont font;
57     QColor color = Qt::black;
58     Qt::Alignment alignment = Qt::AlignTop | Qt::AlignLeft;
59     bool wordWrap = true;
60 
61     int flags() const;
62     QTextOption textOption() const;
63     QSizeF textSize() const;
64 };
65 
66 /**
67  * An object on a map. Objects are positioned and scaled using floating point
68  * values, ensuring they are not limited to the tile grid. They are suitable
69  * for adding any kind of annotation to your maps, as well as free placement of
70  * images.
71  *
72  * Common usages of objects include defining portals, monsters spawn areas,
73  * ambient effects, scripted areas, etc.
74  */
75 class TILEDSHARED_EXPORT MapObject : public Object
76 {
77 public:
78     /**
79      * Enumerates the different object shapes. Rectangle is the default shape.
80      * When a polygon is set, the shape determines whether it should be
81      * interpreted as a filled polygon or a line.
82      *
83      * Text objects contain arbitrary text, contained withih their rectangle
84      * (in screen coordinates).
85      */
86     enum Shape {
87         Rectangle,
88         Polygon,
89         Polyline,
90         Ellipse,
91         Text,
92         Point,
93     };
94 
95     /**
96      * Can be used to get/set property values using QVariant.
97      */
98     enum Property {
99         NameProperty            = 1 << 0,
100         TypeProperty            = 1 << 1,
101         VisibleProperty         = 1 << 2,
102         TextProperty            = 1 << 3,
103         TextFontProperty        = 1 << 4,
104         TextAlignmentProperty   = 1 << 5,
105         TextWordWrapProperty    = 1 << 6,
106         TextColorProperty       = 1 << 7,
107         PositionProperty        = 1 << 8,
108         SizeProperty            = 1 << 9,
109         RotationProperty        = 1 << 10,
110         CellProperty            = 1 << 11,
111         ShapeProperty           = 1 << 12,
112         TemplateProperty        = 1 << 13,
113         CustomProperties        = 1 << 14,
114         AllProperties           = 0xFF
115     };
116 
117     Q_DECLARE_FLAGS(ChangedProperties, Property)
118 
119     explicit MapObject(const QString &name = QString(),
120                        const QString &type = QString(),
121                        const QPointF &pos = QPointF(),
122                        const QSizeF &size = QSizeF(0, 0));
123 
124     int id() const;
125     void setId(int id);
126     void resetId();
127 
128     int index() const;
129 
130     const QString &name() const;
131     void setName(const QString &name);
132 
133     const QString &type() const;
134     void setType(const QString &type);
135 
136     const QString &effectiveType() const;
137 
138     const QPointF &position() const;
139     void setPosition(const QPointF &pos);
140 
141     qreal x() const;
142     void setX(qreal x);
143 
144     qreal y() const;
145     void setY(qreal y);
146 
147     const QSizeF &size() const;
148     void setSize(const QSizeF &size);
149     void setSize(qreal width, qreal height);
150 
151     qreal width() const;
152     void setWidth(qreal width);
153 
154     qreal height() const;
155     void setHeight(qreal height);
156 
157     void setBounds(const QRectF &bounds);
158 
159     const TextData &textData() const;
160     void setTextData(const TextData &textData);
161 
162     const QPolygonF &polygon() const;
163     void setPolygon(const QPolygonF &polygon);
164 
165     Shape shape() const;
166     void setShape(Shape shape);
167 
168     bool hasDimensions() const;
169     bool canRotate() const;
170     bool isTileObject() const;
171 
172     QRectF bounds() const;
173     QRectF boundsUseTile() const;
174     QRectF screenBounds(const MapRenderer &renderer) const;
175 
176     const Cell &cell() const;
177     void setCell(const Cell &cell);
178 
179     const ObjectTemplate *objectTemplate() const;
180     void setObjectTemplate(const ObjectTemplate *objectTemplate);
181 
182     ObjectGroup *objectGroup() const;
183     void setObjectGroup(ObjectGroup *objectGroup);
184 
185     Map *map() const;
186 
187     qreal rotation() const;
188     void setRotation(qreal rotation);
189 
190     Alignment alignment(const Map *map = nullptr) const;
191 
192     bool isVisible() const;
193     void setVisible(bool visible);
194 
195     QColor effectiveColor() const;
196 
197     QVariant mapObjectProperty(Property property) const;
198     void setMapObjectProperty(Property property, const QVariant &value);
199 
200     void setChangedProperties(ChangedProperties changedProperties);
201     MapObject::ChangedProperties changedProperties() const;
202 
203     void setPropertyChanged(Property property, bool state = true);
204     bool propertyChanged(Property property) const;
205 
206     void flip(FlipDirection direction, const QPointF &origin);
207 
208     MapObject *clone() const;
209     void copyPropertiesFrom(const MapObject *object);
210 
211     const MapObject *templateObject() const;
212 
213     void syncWithTemplate();
214     void detachFromTemplate();
215 
216     bool isTemplateInstance() const;
217 
218     bool isTemplateBase() const;
219     void markAsTemplateBase();
220 
221 private:
222     void flipRectObject(const QTransform &flipTransform);
223     void flipPolygonObject(const QTransform &flipTransform);
224     void flipTileObject(const QTransform &flipTransform);
225 
226     int mId;
227     Shape mShape;
228     QString mName;
229     QString mType;
230     QPointF mPos;
231     QSizeF mSize;
232     TextData mTextData;
233     QPolygonF mPolygon;
234     Cell mCell;
235     const ObjectTemplate *mObjectTemplate;
236     ObjectGroup *mObjectGroup;
237     qreal mRotation;
238     bool mVisible;
239     bool mTemplateBase;
240     ChangedProperties mChangedProperties;
241 };
242 
243 /**
244  * Returns the id of this object. Each object gets an id assigned that is
245  * unique for the map the object is on.
246  */
id()247 inline int MapObject::id() const
248 { return mId; }
249 
250 /**
251  * Sets the id of this object.
252  */
setId(int id)253 inline void MapObject::setId(int id)
254 { mId = id; }
255 
256 /**
257  * Sets the id back to 0. Mostly used when a new id should be assigned
258  * after the object has been cloned.
259  */
resetId()260 inline void MapObject::resetId()
261 { setId(0); }
262 
263 /**
264  * Returns the name of this object. The name is usually just used for
265  * identification of the object in the editor.
266  */
name()267 inline const QString &MapObject::name() const
268 { return mName; }
269 
270 /**
271  * Sets the name of this object.
272  */
setName(const QString & name)273 inline void MapObject::setName(const QString &name)
274 { mName = name; }
275 
276 /**
277  * Returns the type of this object. The type usually says something about
278  * how the object is meant to be interpreted by the engine.
279  */
type()280 inline const QString &MapObject::type() const
281 { return mType; }
282 
283 /**
284  * Sets the type of this object.
285  */
setType(const QString & type)286 inline void MapObject::setType(const QString &type)
287 { mType = type; }
288 
289 /**
290  * Returns the position of this object.
291  */
position()292 inline const QPointF &MapObject::position() const
293 { return mPos; }
294 
295 /**
296  * Sets the position of this object.
297  */
setPosition(const QPointF & pos)298 inline void MapObject::setPosition(const QPointF &pos)
299 { mPos = pos; }
300 
301 /**
302  * Returns the x position of this object.
303  */
x()304 inline qreal MapObject::x() const
305 { return mPos.x(); }
306 
307 /**
308  * Sets the x position of this object.
309  */
setX(qreal x)310 inline void MapObject::setX(qreal x)
311 { mPos.setX(x); }
312 
313 /**
314  * Returns the y position of this object.
315  */
y()316 inline qreal MapObject::y() const
317 { return mPos.y(); }
318 
319 /**
320  * Sets the x position of this object.
321  */
setY(qreal y)322 inline void MapObject::setY(qreal y)
323 { mPos.setY(y); }
324 
325 /**
326  * Returns the size of this object.
327  */
size()328 inline const QSizeF &MapObject::size() const
329 { return mSize; }
330 
331 /**
332  * Sets the size of this object.
333  */
setSize(const QSizeF & size)334 inline void MapObject::setSize(const QSizeF &size)
335 { mSize = size; }
336 
setSize(qreal width,qreal height)337 inline void MapObject::setSize(qreal width, qreal height)
338 { setSize(QSizeF(width, height)); }
339 
340 /**
341  * Returns the width of this object.
342  */
width()343 inline qreal MapObject::width() const
344 { return mSize.width(); }
345 
346 /**
347  * Sets the width of this object.
348  */
setWidth(qreal width)349 inline void MapObject::setWidth(qreal width)
350 { mSize.setWidth(width); }
351 
352 /**
353  * Returns the height of this object.
354  */
height()355 inline qreal MapObject::height() const
356 { return mSize.height(); }
357 
358 /**
359  * Sets the height of this object.
360  */
setHeight(qreal height)361 inline void MapObject::setHeight(qreal height)
362 { mSize.setHeight(height); }
363 
364 /**
365  * Sets the position and size of this object.
366  */
setBounds(const QRectF & bounds)367 inline void MapObject::setBounds(const QRectF &bounds)
368 {
369     mPos = bounds.topLeft();
370     mSize = bounds.size();
371 }
372 
373 /**
374  * Returns the text associated with this object, when it is a text object.
375  */
textData()376 inline const TextData &MapObject::textData() const
377 { return mTextData; }
378 
379 /**
380  * Returns the polygon associated with this object. Returns an empty
381  * polygon when no polygon is associated with this object.
382  */
polygon()383 inline const QPolygonF &MapObject::polygon() const
384 { return mPolygon; }
385 
386 /**
387  * Sets the polygon associated with this object. The polygon is only used
388  * when the object shape is set to either Polygon or Polyline.
389  *
390  * \sa setShape()
391  */
setPolygon(const QPolygonF & polygon)392 inline void MapObject::setPolygon(const QPolygonF &polygon)
393 { mPolygon = polygon; }
394 
395 /**
396  * Returns the shape of the object.
397  */
shape()398 inline MapObject::Shape MapObject::shape() const
399 { return mShape; }
400 
401 /**
402  * Sets the shape of the object.
403  */
setShape(MapObject::Shape shape)404 inline void MapObject::setShape(MapObject::Shape shape)
405 { mShape = shape; }
406 
407 /**
408  * Returns true if this object has a width and height.
409  */
hasDimensions()410 inline bool MapObject::hasDimensions() const
411 {
412     switch (mShape) {
413         case Polygon:
414         case Polyline:
415         case Point:
416             return false;
417         default:
418             return true;
419     }
420 }
421 
422 /**
423  * Returns true if this object can be rotated.
424  */
canRotate()425 inline bool MapObject::canRotate() const
426 { return mShape != Point; }
427 
isTileObject()428 inline bool MapObject::isTileObject() const
429 { return !mCell.isEmpty(); }
430 
431 /**
432  * Shortcut to getting a QRectF from position() and size().
433  */
bounds()434 inline QRectF MapObject::bounds() const
435 { return QRectF(mPos, mSize); }
436 
437 /**
438  * Returns the tile associated with this object.
439  */
cell()440 inline const Cell &MapObject::cell() const
441 { return mCell; }
442 
443 /**
444  * Sets the tile that is associated with this object. The object will
445  * display as the tile image.
446  *
447  * \warning The object shape is ignored for tile objects!
448  */
setCell(const Cell & cell)449 inline void MapObject::setCell(const Cell &cell)
450 { mCell = cell; }
451 
objectTemplate()452 inline const ObjectTemplate *MapObject::objectTemplate() const
453 { return mObjectTemplate; }
454 
setObjectTemplate(const ObjectTemplate * objectTemplate)455 inline void MapObject::setObjectTemplate(const ObjectTemplate *objectTemplate)
456 { mObjectTemplate = objectTemplate; }
457 
458 /**
459  * Returns the object group this object belongs to.
460  */
objectGroup()461 inline ObjectGroup *MapObject::objectGroup() const
462 { return mObjectGroup; }
463 
464 /**
465  * Sets the object group this object belongs to. Should only be called
466  * from the ObjectGroup class.
467  */
setObjectGroup(ObjectGroup * objectGroup)468 inline void MapObject::setObjectGroup(ObjectGroup *objectGroup)
469 { mObjectGroup = objectGroup; }
470 
471 /**
472  * Returns the rotation of the object in degrees clockwise.
473  */
rotation()474 inline qreal MapObject::rotation() const
475 { return mRotation; }
476 
477 /**
478  * Sets the rotation of the object in degrees clockwise.
479  */
setRotation(qreal rotation)480 inline void MapObject::setRotation(qreal rotation)
481 { mRotation = rotation; }
482 
isVisible()483 inline bool MapObject::isVisible() const
484 { return mVisible; }
485 
setVisible(bool visible)486 inline void MapObject::setVisible(bool visible)
487 { mVisible = visible; }
488 
setChangedProperties(ChangedProperties changedProperties)489 inline void MapObject::setChangedProperties(ChangedProperties changedProperties)
490 { mChangedProperties = changedProperties; }
491 
changedProperties()492 inline MapObject::ChangedProperties MapObject::changedProperties() const
493 { return mChangedProperties; }
494 
setPropertyChanged(Property property,bool state)495 inline void MapObject::setPropertyChanged(Property property, bool state)
496 {
497 #if QT_VERSION >= 0x050700
498     mChangedProperties.setFlag(property, state);
499 #else
500     if (state)
501         mChangedProperties |= property;
502     else
503         mChangedProperties &= ~property;
504 #endif
505 }
506 
propertyChanged(Property property)507 inline bool MapObject::propertyChanged(Property property) const
508 { return mChangedProperties.testFlag(property); }
509 
isTemplateInstance()510 inline bool MapObject::isTemplateInstance() const
511 { return mObjectTemplate != nullptr; }
512 
isTemplateBase()513 inline bool MapObject::isTemplateBase() const
514 { return mTemplateBase; }
515 
markAsTemplateBase()516 inline void MapObject::markAsTemplateBase()
517 { mTemplateBase = true; }
518 
519 } // namespace Tiled
520 
521 Q_DECLARE_METATYPE(Tiled::MapObject::Shape)
522 Q_DECLARE_METATYPE(Tiled::MapObject*)
523 Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::MapObject::ChangedProperties);
524