1//////////////////////////////////////////////////////////////////////
2// This file is part of Remere's Map Editor
3//////////////////////////////////////////////////////////////////////
4// Remere's Map Editor is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Remere's Map Editor is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//////////////////////////////////////////////////////////////////////
17
18#include "main.h"
19
20#include "tile.h"
21#include "basemap.h"
22
23BaseMap::BaseMap() :
24 allocator(),
25 tilecount(0),
26 root(*this) {
27 ////
28}
29
30BaseMap::~BaseMap() {
31 ////
32}
33
34void BaseMap::clear(bool del) {
35 PositionVector pos_vec;
36 for (MapIterator map_iter = begin(); map_iter != end(); ++map_iter) {
37 Tile* t = (*map_iter)->get();
38 pos_vec.push_back(t->getPosition());
39 }
40 for (PositionVector::iterator pos_iter = pos_vec.begin(); pos_iter != pos_vec.end(); ++pos_iter) {
41 setTile(*pos_iter, nullptr, del);
42 }
43}
44
45void BaseMap::clearVisible(uint32_t mask) {
46 root.clearVisible(mask);
47}
48
49Tile* BaseMap::createTile(int x, int y, int z) {
50 ASSERT(z < MAP_LAYERS);
51 QTreeNode* leaf = root.getLeafForce(x, y);
52 TileLocation* loc = leaf->createTile(x, y, z);
53 if (loc->get()) {
54 return loc->get();
55 }
56 Tile* t = allocator(loc);
57 leaf->setTile(x, y, z, t);
58 return t;
59}
60
61Tile* BaseMap::getOrCreateTile(const Position& pos) {
62 if (Tile* t = getTile(pos)) {
63 return t;
64 }
65
66 Tile* newTile = createTile(pos.x, pos.y, pos.z);
67 newTile->setLocation(createTileL(pos));
68 return newTile;
69}
70
71TileLocation* BaseMap::getTileL(int x, int y, int z) {
72 ASSERT(z < MAP_LAYERS);
73 QTreeNode* leaf = root.getLeaf(x, y);
74 if (leaf) {
75 Floor* floor = leaf->getFloor(z);
76 if (floor) {
77 return &floor->locs[(x & 3) * 4 + (y & 3)];
78 }
79 }
80
81 return nullptr;
82}
83
84const TileLocation* BaseMap::getTileL(int x, int y, int z) const {
85 // Don't create static const maps!
86 BaseMap* self = const_cast<BaseMap*>(this);
87 return self->getTileL(x, y, z);
88}
89
90TileLocation* BaseMap::getTileL(const Position& pos) {
91 return getTileL(pos.x, pos.y, pos.z);
92}
93
94const TileLocation* BaseMap::getTileL(const Position& pos) const {
95 return getTileL(pos.x, pos.y, pos.z);
96}
97
98TileLocation* BaseMap::createTileL(int x, int y, int z) {
99 ASSERT(z < MAP_LAYERS);
100
101 QTreeNode* leaf = root.getLeafForce(x, y);
102 Floor* floor = leaf->createFloor(x, y, z);
103 uint32_t offsetX = x & 3;
104 uint32_t offsetY = y & 3;
105
106 return &floor->locs[offsetX * 4 + offsetY];
107}
108
109TileLocation* BaseMap::createTileL(const Position& pos) {
110 return createTileL(pos.x, pos.y, pos.z);
111}
112
113void BaseMap::setTile(int x, int y, int z, Tile* newtile, bool remove) {
114 ASSERT(!newtile || newtile->getX() == int(x));
115 ASSERT(!newtile || newtile->getY() == int(y));
116 ASSERT(!newtile || newtile->getZ() == int(z));
117
118 QTreeNode* leaf = root.getLeafForce(x, y);
119 Tile* old = leaf->setTile(x, y, z, newtile);
120 if (remove) {
121 delete old;
122 }
123}
124
125Tile* BaseMap::swapTile(int x, int y, int z, Tile* newtile) {
126 ASSERT(z < MAP_LAYERS);
127 ASSERT(!newtile || newtile->getX() == int(x));
128 ASSERT(!newtile || newtile->getY() == int(y));
129 ASSERT(!newtile || newtile->getZ() == int(z));
130
131 QTreeNode* leaf = root.getLeafForce(x, y);
132 return leaf->setTile(x, y, z, newtile);
133}
134
135// Iterators
136
137MapIterator::MapIterator(BaseMap* _map) :
138 local_i(0),
139 local_z(0),
140 current_tile(nullptr),
141 map(_map) {
142 ////
143}
144
145MapIterator::~MapIterator() {
146 ////
147}
148
149MapIterator::MapIterator(const MapIterator& other) {
150 for (std::vector<MapIterator::NodeIndex>::const_iterator it = other.nodestack.begin(); it != other.nodestack.end(); it++) {
151 nodestack.push_back(MapIterator::NodeIndex(*it));
152 }
153 local_i = other.local_i;
154 local_z = other.local_z;
155 map = other.map;
156 current_tile = other.current_tile;
157}
158
159MapIterator BaseMap::begin() {
160 MapIterator it(this);
161 it.nodestack.push_back(MapIterator::NodeIndex(&root));
162
163 while (true) {
164 MapIterator::NodeIndex& current = it.nodestack.back();
165 QTreeNode* node = current.node;
166 int& index = current.index;
167 // printf("Contemplating %p of %p (stack size %d)\n", node, this, it.nodestack.size());
168
169 bool unwind = false;
170 for (; index < MAP_LAYERS; ++index) {
171 // printf("\tChecking index %d of %p\n", index, node);
172 if (QTreeNode* child = node->child[index]) {
173 if (child->isLeaf) {
174 QTreeNode* leaf = child;
175 // printf("\t%p is leaf\n", child);
176 for (it.local_z = 0; it.local_z < MAP_LAYERS; ++it.local_z) {
177 if (Floor* floor = leaf->array[it.local_z]) {
178 for (it.local_i = 0; it.local_i < MAP_LAYERS; ++it.local_i) {
179 // printf("\tit(%d;%d;%d)\n", it.local_x, it.local_y, it.local_z);
180 TileLocation& t = floor->locs[it.local_i];
181 if (t.get()) {
182 // printf("return it\n");
183 it.current_tile = &t;
184 return it;
185 }
186 }
187 }
188 }
189 } else {
190 // printf("\tAdding %p\n", child);
191 ++index;
192 it.nodestack.push_back(MapIterator::NodeIndex(child));
193 unwind = true;
194 break;
195 }
196 }
197 }
198 if (unwind) {
199 continue;
200 }
201
202 // printf("Discarding dead node %p\n", node);
203 it.nodestack.pop_back();
204 if (it.nodestack.empty()) {
205 break;
206 }
207 }
208 return end();
209}
210
211MapIterator BaseMap::end() {
212 MapIterator it(this);
213 it.local_i = -1;
214 it.local_z = -1;
215 return it;
216}
217
218TileLocation* MapIterator::operator*() {
219 return current_tile;
220}
221
222TileLocation* MapIterator::operator->() {
223 return current_tile;
224}
225
226MapIterator& MapIterator::operator++() {
227 // printf("MapIterator::operator++");
228 bool increased = false;
229 bool first = true;
230 while (true) {
231 MapIterator::NodeIndex& current = nodestack.back();
232 QTreeNode* node = current.node;
233 int& index = current.index;
234 // printf("Contemplating %p (stack size %d)\n", node, nodestack.size());
235
236 bool unwind = false;
237 for (; index < MAP_LAYERS; ++index) {
238 // printf("\tChecking index %d of %p\n", index, node);
239 if (QTreeNode* child = node->child[index]) {
240 if (child->isLeaf) {
241 QTreeNode* leaf = child;
242 // printf("\t%p is leaf\n", child);
243 for (; local_z < MAP_LAYERS; ++local_z) {
244 // printf("\t\tIterating over Z:%d of %p", local_z, child);
245 if (Floor* floor = leaf->array[local_z]) {
246 // printf("\n");
247 for (; local_i < MAP_LAYERS; ++local_i) {
248 // printf("\t\tIterating over Y:%d of %p\n", local_y, child);
249 TileLocation& t = floor->locs[local_i];
250 if (t.get()) {
251 if (increased) {
252 // printf("Modified %p to %p\n", current_tile, t);
253 current_tile = &t;
254 return *this;
255 } else {
256 increased = true;
257 }
258 } else if (first) {
259 increased = true;
260 first = false;
261 }
262 }
263
264 if (local_i > MAP_MAX_LAYER) {
265 // printf("\t\tReset local_x\n");
266 local_i = 0;
267 }
268 } else {
269 // printf(":dead floor\n");
270 }
271 }
272 if (local_z == MAP_LAYERS) {
273 // printf("\t\tReset local_z\n");
274 local_z = 0;
275 }
276 } else {
277 // printf("\tAdding %p\n", child);
278 ++index;
279 nodestack.push_back(MapIterator::NodeIndex(child));
280 unwind = true;
281 break;
282 }
283 }
284 }
285 if (unwind) {
286 continue;
287 }
288
289 // printf("Discarding dead node %p\n", node);
290 nodestack.pop_back();
291 if (nodestack.size() == 0) {
292 // Set all values to "end"
293 // printf("END\n");
294 local_z = -1;
295 local_i = -1;
296 return *this;
297 }
298 }
299 return *this;
300}
301
302MapIterator MapIterator::operator++(int) {
303 MapIterator i(*this);
304 ++*this;
305 return i;
306}
307