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