1 /*
2  * map.h
3  * Copyright 2008-2010, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
4  * Copyright 2008, Roderic Morris <roderic@ccs.neu.edu>
5  * Copyright 2010, Andrew G. Crowell <overkill9999@gmail.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 "layer.h"
34 #include "object.h"
35 #include "tileset.h"
36 
37 #include <QColor>
38 #include <QList>
39 #include <QMargins>
40 #include <QSharedPointer>
41 #include <QSize>
42 #include <QVector>
43 
44 #include <memory>
45 
46 namespace Tiled {
47 
48 class MapObject;
49 class ObjectGroup;
50 class ObjectTemplate;
51 class Tile;
52 
53 /**
54  * A tile map. Consists of a stack of layers.
55  *
56  * It also keeps track of the list of referenced tilesets.
57  */
58 class TILEDSHARED_EXPORT Map : public Object
59 {
60     class LayerIteratorHelper
61     {
62     public:
63         LayerIteratorHelper(const Map &map, int layerTypes);
64 
65         LayerIterator begin() const;
66         LayerIterator end() const;
67         bool isEmpty() const;
68 
69     private:
70         const Map &mMap;
71         const int mLayerTypes;
72     };
73 
74 public:
75     QString fileName;
76     QString exportFileName;
77     QString exportFormat;
78 
79     enum Property {
80         TileWidthProperty,
81         TileHeightProperty,
82         InfiniteProperty,
83         HexSideLengthProperty,
84         StaggerAxisProperty,
85         StaggerIndexProperty,
86         OrientationProperty,
87         RenderOrderProperty,
88         BackgroundColorProperty,
89         LayerDataFormatProperty,
90         CompressionLevelProperty,
91         ChunkSizeProperty
92     };
93 
94     /**
95      * The orientation of the map determines how it should be rendered. An
96      * Orthogonal map is using rectangular tiles that are aligned on a
97      * straight grid. An Isometric map uses diamond shaped tiles that are
98      * aligned on an isometric projected grid. A Hexagonal map uses hexagon
99      * shaped tiles that fit into each other by shifting every other row.
100      */
101     enum Orientation {
102         Unknown,
103         Orthogonal,
104         Isometric,
105         Staggered,
106         Hexagonal
107     };
108 
109     /**
110      * The different formats in which the tile layer data can be stored.
111      */
112     enum LayerDataFormat {
113         XML             = 0,
114         Base64          = 1,
115         Base64Gzip      = 2,
116         Base64Zlib      = 3,
117         Base64Zstandard = 4,
118         CSV             = 5
119     };
120 
121     /**
122      * The order in which tiles are rendered on screen.
123      */
124     enum RenderOrder {
125         RightDown  = 0,
126         RightUp    = 1,
127         LeftDown   = 2,
128         LeftUp     = 3
129     };
130 
131     /**
132      * Which axis is staggered. Only used by the isometric staggered and
133      * hexagonal map renderers.
134      */
135     enum StaggerAxis {
136         StaggerX,
137         StaggerY
138     };
139 
140     /**
141      * When staggering, specifies whether the odd or the even rows/columns are
142      * shifted half a tile right/down. Only used by the isometric staggered and
143      * hexagonal map renderers.
144      */
145     enum StaggerIndex {
146         StaggerOdd  = 0,
147         StaggerEven = 1
148     };
149 
150     struct Parameters
151     {
152         Orientation orientation = Orthogonal;
153         RenderOrder renderOrder = RightDown;
154         int width = 0;
155         int height = 0;
156         int tileWidth = 0;
157         int tileHeight = 0;
158         bool infinite = false;
159         int hexSideLength = 0;
160         StaggerAxis staggerAxis = StaggerY;
161         StaggerIndex staggerIndex = StaggerOdd;
162         QColor backgroundColor;
163     };
164 
165     struct EditorSettings
166     {
167         int compressionLevel = -1;
168         QSize chunkSize = QSize(CHUNK_SIZE, CHUNK_SIZE);
169         LayerDataFormat layerDataFormat = Base64Zlib;
170     };
171 
172     Map();
173     Map(const Parameters &parameters);
174 
175     /**
176      * Constructor taking map orientation, size and tile size as parameters.
177      *
178      * @deprecated Only kept around for the Python API!
179      */
180     Map(Orientation orientation,
181         int width, int height,
182         int tileWidth, int tileHeight);
183 
184     ~Map();
185 
186     const Parameters &parameters() const;
187 
188     Orientation orientation() const;
189     void setOrientation(Orientation orientation);
190 
191     RenderOrder renderOrder() const;
192     void setRenderOrder(RenderOrder renderOrder);
193 
194     int compressionLevel() const;
195     void setCompressionLevel(int compressionLevel);
196 
197     int width() const;
198     void setWidth(int width);
199 
200     int height() const;
201     void setHeight(int height);
202 
203     QSize size() const;
204 
205     int tileWidth() const;
206     void setTileWidth(int width);
207 
208     int tileHeight() const;
209     void setTileHeight(int height);
210 
211     QSize tileSize() const;
212 
213     bool infinite() const;
214     void setInfinite(bool infinite);
215 
216     int hexSideLength() const;
217     void setHexSideLength(int hexSideLength);
218 
219     StaggerAxis staggerAxis() const;
220     void setStaggerAxis(StaggerAxis staggerAxis);
221 
222     StaggerIndex staggerIndex() const;
223     void setStaggerIndex(StaggerIndex staggerIndex);
224     void invertStaggerIndex();
225 
226     QMargins drawMargins() const;
227     void invalidateDrawMargins();
228 
229     QMargins computeLayerOffsetMargins() const;
230 
231     int layerCount() const;
232     int layerCount(Layer::TypeFlag type) const;
233 
234     int tileLayerCount() const;
235     int objectGroupCount() const;
236     int imageLayerCount() const;
237     int groupLayerCount() const;
238 
239     Layer *layerAt(int index) const;
240 
241     const QList<Layer*> &layers() const;
242 
243     LayerIteratorHelper allLayers(int layerTypes = Layer::AnyLayerType) const;
244     LayerIteratorHelper tileLayers() const;
245     LayerIteratorHelper objectGroups() const;
246 
247     void addLayer(std::unique_ptr<Layer> layer);
248     void addLayer(Layer *layer);
249 
250     int indexOfLayer(const QString &layerName,
251                      int layerTypes = Layer::AnyLayerType) const;
252 
253     Layer *findLayer(const QString &name,
254                      int layerTypes = Layer::AnyLayerType) const;
255 
256     void insertLayer(int index, Layer *layer);
257 
258     Layer *takeLayerAt(int index);
259 
260     bool addTileset(const SharedTileset &tileset);
261     void addTilesets(const QSet<SharedTileset> &tilesets);
262     void insertTileset(int index, const SharedTileset &tileset);
263 
264     int indexOfTileset(const SharedTileset &tileset) const;
265 
266     void removeTilesetAt(int index);
267 
268     bool replaceTileset(const SharedTileset &oldTileset,
269                         const SharedTileset &newTileset);
270 
271     int tilesetCount() const;
272     SharedTileset tilesetAt(int index) const;
273     const QVector<SharedTileset> &tilesets() const;
274 
275     QSet<SharedTileset> usedTilesets() const;
276 
277     QList<MapObject*> replaceObjectTemplate(const ObjectTemplate *oldObjectTemplate,
278                                             const ObjectTemplate *newObjectTemplate);
279 
280     const QColor &backgroundColor() const;
281     void setBackgroundColor(QColor color);
282 
283     QSize chunkSize() const;
284     void setChunkSize(QSize size);
285 
286     bool isTilesetUsed(const Tileset *tileset) const;
287 
288     std::unique_ptr<Map> clone() const;
289 
290     void copyLayers(const QList<Layer*> &layers,
291                     const QRegion &tileRegion,
292                     Map &targetMap) const;
293 
294     void normalizeTileLayerPositionsAndMapSize();
295 
296     bool isStaggered() const;
297 
298     LayerDataFormat layerDataFormat() const;
299     void setLayerDataFormat(LayerDataFormat format);
300 
301     void setNextLayerId(int nextId);
302     int nextLayerId() const;
303     int takeNextLayerId();
304 
305     void setNextObjectId(int nextId);
306     int nextObjectId() const;
307     int takeNextObjectId();
308     void initializeObjectIds(ObjectGroup &objectGroup);
309 
310     Layer *findLayerById(int layerId) const;
311     MapObject *findObjectById(int objectId) const;
312 
313     QRegion tileRegion() const;
314 
315 private:
316     friend class GroupLayer;    // so it can call adoptLayer
317 
318     void adoptLayer(Layer &layer);
319 
320     void recomputeDrawMargins() const;
321 
322     Parameters mParameters;
323     EditorSettings mEditorSettings;
324 
325     mutable QMargins mDrawMargins;
326     mutable bool mDrawMarginsDirty = true;
327 
328     QList<Layer*> mLayers;
329     QVector<SharedTileset> mTilesets;
330 
331     int mNextLayerId = 1;
332     int mNextObjectId = 1;
333 };
334 
335 
parameters()336 inline const Map::Parameters &Map::parameters() const
337 {
338     return mParameters;
339 }
340 
orientation()341 inline Map::Orientation Map::orientation() const
342 {
343     return mParameters.orientation;
344 }
345 
setOrientation(Map::Orientation orientation)346 inline void Map::setOrientation(Map::Orientation orientation)
347 {
348     mParameters.orientation = orientation;
349 }
350 
renderOrder()351 inline Map::RenderOrder Map::renderOrder() const
352 {
353     return mParameters.renderOrder;
354 }
355 
setRenderOrder(Map::RenderOrder renderOrder)356 inline void Map::setRenderOrder(Map::RenderOrder renderOrder)
357 {
358     mParameters.renderOrder = renderOrder;
359 }
360 
361 /**
362  * Returns the compression level used for compressed tile layer data.
363  */
compressionLevel()364 inline int Map::compressionLevel() const
365 {
366     return mEditorSettings.compressionLevel;
367 }
368 
setCompressionLevel(int compressionLevel)369 inline void Map::setCompressionLevel(int compressionLevel)
370 {
371     mEditorSettings.compressionLevel = compressionLevel;
372 }
373 
374 /**
375  * Returns the width of this map in tiles.
376  */
width()377 inline int Map::width() const
378 {
379     return mParameters.width;
380 }
381 
382 /**
383  * Sets the width of this map in tiles.
384  */
setWidth(int width)385 inline void Map::setWidth(int width)
386 {
387     mParameters.width = width;
388 }
389 
390 /**
391  * Returns the height of this map in tiles.
392  */
height()393 inline int Map::height() const
394 {
395     return mParameters.height;
396 }
397 
398 /**
399  * Sets the height of this map in tiles.
400  */
setHeight(int height)401 inline void Map::setHeight(int height)
402 {
403     mParameters.height = height;
404 }
405 
406 /**
407  * Returns the size of this map. Provided for convenience.
408  */
size()409 inline QSize Map::size() const
410 {
411     return QSize(mParameters.width, mParameters.height);
412 }
413 
414 /**
415  * Returns the tile width of this map.
416  */
tileWidth()417 inline int Map::tileWidth() const
418 {
419     return mParameters.tileWidth;
420 }
421 
422 /**
423  * Sets the width of one tile.
424  */
setTileWidth(int width)425 inline void Map::setTileWidth(int width)
426 {
427     mParameters.tileWidth = width;
428 }
429 
430 /**
431  * Returns the tile height used by this map.
432  */
tileHeight()433 inline int Map::tileHeight() const
434 {
435     return mParameters.tileHeight;
436 }
437 
438 /**
439  * Sets the height of one tile.
440  */
setTileHeight(int height)441 inline void Map::setTileHeight(int height)
442 {
443     mParameters.tileHeight = height;
444 }
445 
446 /**
447  * Returns the size of one tile. Provided for convenience.
448  */
tileSize()449 inline QSize Map::tileSize() const
450 {
451     return QSize(mParameters.tileWidth, mParameters.tileHeight);
452 }
453 
infinite()454 inline bool Map::infinite() const
455 {
456     return mParameters.infinite;
457 }
458 
setInfinite(bool infinite)459 inline void Map::setInfinite(bool infinite)
460 {
461     mParameters.infinite = infinite;
462 }
463 
hexSideLength()464 inline int Map::hexSideLength() const
465 {
466     return mParameters.hexSideLength;
467 }
468 
setHexSideLength(int hexSideLength)469 inline void Map::setHexSideLength(int hexSideLength)
470 {
471     mParameters.hexSideLength = hexSideLength;
472 }
473 
staggerAxis()474 inline Map::StaggerAxis Map::staggerAxis() const
475 {
476     return mParameters.staggerAxis;
477 }
478 
setStaggerAxis(StaggerAxis staggerAxis)479 inline void Map::setStaggerAxis(StaggerAxis staggerAxis)
480 {
481     mParameters.staggerAxis = staggerAxis;
482 }
483 
staggerIndex()484 inline Map::StaggerIndex Map::staggerIndex() const
485 {
486     return mParameters.staggerIndex;
487 }
488 
setStaggerIndex(StaggerIndex staggerIndex)489 inline void Map::setStaggerIndex(StaggerIndex staggerIndex)
490 {
491     mParameters.staggerIndex = staggerIndex;
492 }
493 
invertStaggerIndex()494 inline void Map::invertStaggerIndex()
495 {
496     mParameters.staggerIndex = static_cast<StaggerIndex>(!mParameters.staggerIndex);
497 }
498 
invalidateDrawMargins()499 inline void Map::invalidateDrawMargins()
500 {
501     mDrawMarginsDirty = true;
502 }
503 
504 /**
505  * Returns the number of layers of this map.
506  */
layerCount()507 inline int Map::layerCount() const
508 {
509     return mLayers.size();
510 }
511 
tileLayerCount()512 inline int Map::tileLayerCount() const
513 {
514     return layerCount(Layer::TileLayerType);
515 }
516 
objectGroupCount()517 inline int Map::objectGroupCount() const
518 {
519     return layerCount(Layer::ObjectGroupType);
520 }
521 
imageLayerCount()522 inline int Map::imageLayerCount() const
523 {
524     return layerCount(Layer::ImageLayerType);
525 }
526 
groupLayerCount()527 inline int Map::groupLayerCount() const
528 {
529     return layerCount(Layer::GroupLayerType);
530 }
531 
532 /**
533  * Returns the top-level layer at the specified \a index.
534  */
layerAt(int index)535 inline Layer *Map::layerAt(int index) const
536 {
537     return mLayers.at(index);
538 }
539 
540 /**
541  * Returns the list of top-level layers of this map.
542  */
layers()543 inline const QList<Layer *> &Map::layers() const
544 {
545     return mLayers;
546 }
547 
548 /**
549  * Returns a helper for iterating all tile layers of the given \a layerTypes
550  * in this map.
551  */
allLayers(int layerTypes)552 inline Map::LayerIteratorHelper Map::allLayers(int layerTypes) const
553 {
554     return LayerIteratorHelper { *this, layerTypes };
555 }
556 
557 /**
558  * Returns a helper for iterating all tile layers in this map.
559  */
tileLayers()560 inline Map::LayerIteratorHelper Map::tileLayers() const
561 {
562     return allLayers(Layer::TileLayerType);
563 }
564 
565 /**
566  * Returns a helper for iterating all object groups in this map.
567  */
objectGroups()568 inline Map::LayerIteratorHelper Map::objectGroups() const
569 {
570     return allLayers(Layer::ObjectGroupType);
571 }
572 
573 /**
574  * Adds a layer to this map.
575  */
addLayer(std::unique_ptr<Layer> layer)576 inline void Map::addLayer(std::unique_ptr<Layer> layer)
577 {
578     addLayer(layer.release());
579 }
580 
581 /**
582  * Returns the number of tilesets of this map.
583  */
tilesetCount()584 inline int Map::tilesetCount() const
585 {
586     return mTilesets.size();
587 }
588 
589 /**
590  * Returns the tileset at the given index.
591  */
tilesetAt(int index)592 inline SharedTileset Map::tilesetAt(int index) const
593 {
594     return mTilesets.at(index);
595 }
596 
597 /**
598  * Returns the tilesets that have been added to this map.
599  */
tilesets()600 inline const QVector<SharedTileset> &Map::tilesets() const
601 {
602     return mTilesets;
603 }
604 
605 /**
606  * Returns the background color of this map.
607  */
backgroundColor()608 inline const QColor &Map::backgroundColor() const
609 {
610     return mParameters.backgroundColor;
611 }
612 
setBackgroundColor(QColor color)613 inline void Map::setBackgroundColor(QColor color)
614 {
615     mParameters.backgroundColor = color;
616 }
617 
618 /**
619  * Returns the chunk size used when saving tile layers of this map.
620  */
chunkSize()621 inline QSize Map::chunkSize() const
622 {
623     return mEditorSettings.chunkSize;
624 }
625 
setChunkSize(QSize size)626 inline void Map::setChunkSize(QSize size)
627 {
628     mEditorSettings.chunkSize = size;
629 }
630 
631 /**
632  * Returns whether the map is staggered.
633  */
isStaggered()634 inline bool Map::isStaggered() const
635 {
636     return orientation() == Hexagonal || orientation() == Staggered;
637 }
638 
layerDataFormat()639 inline Map::LayerDataFormat Map::layerDataFormat() const
640 {
641     return mEditorSettings.layerDataFormat;
642 }
643 
setLayerDataFormat(Map::LayerDataFormat format)644 inline void Map::setLayerDataFormat(Map::LayerDataFormat format)
645 {
646     mEditorSettings.layerDataFormat = format;
647 }
648 
649 /**
650  * Sets the next id to be used for layers of this map.
651  */
setNextLayerId(int nextId)652 inline void Map::setNextLayerId(int nextId)
653 {
654     Q_ASSERT(nextId > 0);
655     mNextLayerId = nextId;
656 }
657 
658 /**
659  * Returns the next layer id for this map.
660  */
nextLayerId()661 inline int Map::nextLayerId() const
662 {
663     return mNextLayerId;
664 }
665 
666 /**
667  * Returns the next layer id for this map and allocates a new one.
668  */
takeNextLayerId()669 inline int Map::takeNextLayerId()
670 {
671     return mNextLayerId++;
672 }
673 
674 /**
675  * Sets the next id to be used for objects on this map.
676  */
setNextObjectId(int nextId)677 inline void Map::setNextObjectId(int nextId)
678 {
679     Q_ASSERT(nextId > 0);
680     mNextObjectId = nextId;
681 }
682 
683 /**
684  * Returns the next object id for this map.
685  */
nextObjectId()686 inline int Map::nextObjectId() const
687 {
688     return mNextObjectId;
689 }
690 
691 /**
692  * Returns the next object id for this map and allocates a new one.
693  */
takeNextObjectId()694 inline int Map::takeNextObjectId()
695 {
696     return mNextObjectId++;
697 }
698 
699 
LayerIteratorHelper(const Map & map,int layerTypes)700 inline Map::LayerIteratorHelper::LayerIteratorHelper(const Map &map, int layerTypes)
701     : mMap(map)
702     , mLayerTypes(layerTypes)
703 {}
704 
begin()705 inline LayerIterator Map::LayerIteratorHelper::begin() const
706 {
707     LayerIterator iterator(&mMap, mLayerTypes);
708     iterator.next();
709     return iterator;
710 }
711 
end()712 inline LayerIterator Map::LayerIteratorHelper::end() const
713 {
714     LayerIterator iterator(&mMap, mLayerTypes);
715     iterator.toBack();
716     return iterator;
717 }
718 
isEmpty()719 inline bool Map::LayerIteratorHelper::isEmpty() const
720 {
721     return LayerIterator(&mMap, mLayerTypes).next() == nullptr;
722 }
723 
724 
725 TILEDSHARED_EXPORT QString staggerAxisToString(Map::StaggerAxis);
726 TILEDSHARED_EXPORT Map::StaggerAxis staggerAxisFromString(const QString &);
727 
728 TILEDSHARED_EXPORT QString staggerIndexToString(Map::StaggerIndex staggerIndex);
729 TILEDSHARED_EXPORT Map::StaggerIndex staggerIndexFromString(const QString &);
730 
731 /**
732  * Helper function that converts the map orientation to a string value. Useful
733  * for map writers.
734  *
735  * @return The map orientation as a lowercase string.
736  */
737 TILEDSHARED_EXPORT QString orientationToString(Map::Orientation);
738 
739 /**
740  * Helper function that converts a string to a map orientation enumerator.
741  * Useful for map readers.
742  *
743  * @return The map orientation matching the given string, or Map::Unknown if
744  *         the string is unrecognized.
745  */
746 TILEDSHARED_EXPORT Map::Orientation orientationFromString(const QString &);
747 
748 /**
749  * Helper function that returns a string representing the compression used by
750  * the given layer data format.
751  *
752  * @return The compression as a lowercase string.
753  */
754 TILEDSHARED_EXPORT QString compressionToString(Map::LayerDataFormat);
755 
756 TILEDSHARED_EXPORT QString renderOrderToString(Map::RenderOrder renderOrder);
757 TILEDSHARED_EXPORT Map::RenderOrder renderOrderFromString(const QString &);
758 
759 typedef QSharedPointer<Map> SharedMap;
760 
761 } // namespace Tiled
762 
763 Q_DECLARE_METATYPE(Tiled::Map*)
764 Q_DECLARE_METATYPE(Tiled::Map::Orientation)
765 Q_DECLARE_METATYPE(Tiled::Map::LayerDataFormat)
766 Q_DECLARE_METATYPE(Tiled::Map::RenderOrder)
767