1// Aseprite Document Library
2// Copyright (c) 2019-2021 Igara Studio S.A.
3//
4// This file is released under the terms of the MIT license.
5// Read LICENSE.txt for more information.
6
7#ifndef DOC_TILESET_H_INCLUDED
8#define DOC_TILESET_H_INCLUDED
9#pragma once
10
11#include "doc/grid.h"
12#include "doc/image_ref.h"
13#include "doc/object.h"
14#include "doc/tile.h"
15#include "doc/tileset_hash_table.h"
16
17#include <string>
18#include <vector>
19
20namespace doc {
21
22 class Remap;
23 class Sprite;
24
25 class Tileset : public Object {
26 public:
27 typedef std::vector<ImageRef> Tiles;
28 typedef Tiles::iterator iterator;
29 typedef Tiles::const_iterator const_iterator;
30
31 // Creates a new tileset with "ntiles". The first tile will be
32 // always the empty tile. So ntiles must be > 1 to contain at
33 // least one non-empty tile.
34 Tileset(Sprite* sprite,
35 const Grid& grid,
36 const tileset_index ntiles);
37
38 static Tileset* MakeCopyWithSameImages(const Tileset* tileset);
39 static Tileset* MakeCopyCopyingImages(const Tileset* tileset);
40
41 Sprite* sprite() const { return m_sprite; }
42 const Grid& grid() const { return m_grid; }
43
44 const std::string& name() const { return m_name; }
45 void setName(const std::string& name) { m_name = name; }
46
47 int baseIndex() const { return m_baseIndex; }
48 void setBaseIndex(int index) { m_baseIndex = index; }
49
50 int getMemSize() const override;
51
52 iterator begin() { return m_tiles.begin(); }
53 iterator end() { return m_tiles.end(); }
54 const_iterator begin() const { return m_tiles.begin(); }
55 const_iterator end() const { return m_tiles.end(); }
56 tile_index size() const { return tile_index(m_tiles.size()); }
57 void resize(const tile_index ntiles);
58 void remap(const Remap& remap);
59
60 ImageRef get(const tile_index ti) const {
61 if (ti >= 0 && ti < size())
62 return m_tiles[ti];
63 else
64 return ImageRef(nullptr);
65 }
66 void set(const tile_index ti,
67 const ImageRef& image);
68
69 tile_index add(const ImageRef& image);
70 void insert(const tile_index ti,
71 const ImageRef& image);
72 void erase(const tile_index ti);
73
74 // Linked with an external file
75 void setExternal(const std::string& filename,
76 const tileset_index& tsi);
77 const std::string& externalFilename() const { return m_external.filename; }
78 tileset_index externalTileset() const { return m_external.tileset; }
79
80 bool operator==(const Tileset& other) const {
81 // TODO compare the all grid members
82 return (m_grid.tileSize() == other.m_grid.tileSize() &&
83 m_tiles == other.m_tiles &&
84 m_name == other.m_name);
85 }
86
87 bool operator!=(const Tileset& other) const {
88 return !operator==(other);
89 }
90
91 // Returns a new empty tile with the tileset specs.
92 ImageRef makeEmptyTile();
93
94 // If there is a tile in the set that matches the pixels of the
95 // given "tileImage", this function returns true and the index of
96 // that tile in the "ti" parameter. Returns false if the image is
97 // not in the tileset.
98 //
99 // Warning: Use preprocess_transparent_pixels() with tileImage
100 // before calling this function.
101 bool findTileIndex(const ImageRef& tileImage,
102 tile_index& ti);
103
104 // Must be called when a tile image was modified externally, so
105 // the hash elements are re-calculated for that specific tile.
106 void notifyTileContentChange(const tile_index ti);
107
108 // Called when the mask color of the sprite is modified, so we
109 // have to regenerate the empty tile with that new mask color.
110 void notifyRegenerateEmptyTile();
111
112#ifdef _DEBUG
113 void assertValidHashTable();
114#endif
115
116 private:
117 void removeFromHash(const tile_index ti,
118 const bool adjustIndexes);
119 void hashImage(const tile_index ti,
120 const ImageRef& tileImage);
121 void rehash();
122 TilesetHashTable& hashTable();
123
124 Sprite* m_sprite;
125 Grid m_grid;
126 Tiles m_tiles;
127 TilesetHashTable m_hash;
128 std::string m_name;
129 int m_baseIndex = 1;
130 struct External {
131 std::string filename;
132 tileset_index tileset;
133 } m_external;
134 };
135
136} // namespace doc
137
138#endif
139