2012-06-29 16:44:26 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
// This file is part of Remere's Map Editor
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
2020-07-30 11:42:28 -03:00
|
|
|
// Remere's Map Editor is free software: you can redistribute it and/or modify
|
2012-06-29 16:44:26 +02:00
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
2016-09-29 19:24:45 -03:00
|
|
|
//
|
2020-07-30 11:42:28 -03:00
|
|
|
// Remere's Map Editor is distributed in the hope that it will be useful,
|
2012-06-29 16:44:26 +02:00
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2020-07-30 11:42:28 -03:00
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2012-06-29 16:44:26 +02:00
|
|
|
// GNU General Public License for more details.
|
2016-09-29 19:24:45 -03:00
|
|
|
//
|
2012-06-29 16:44:26 +02:00
|
|
|
// You should have received a copy of the GNU General Public License
|
2020-07-30 11:42:28 -03:00
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2012-06-29 16:44:26 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
|
|
#include "tile.h"
|
|
|
|
|
#include "basemap.h"
|
|
|
|
|
|
|
|
|
|
BaseMap::BaseMap() :
|
2016-11-22 16:57:49 +01:00
|
|
|
allocator(),
|
2012-06-29 16:44:26 +02:00
|
|
|
tilecount(0),
|
2023-10-09 19:12:16 -07:00
|
|
|
root(*this) {
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
BaseMap::~BaseMap() {
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
void BaseMap::clear(bool del) {
|
2012-06-29 16:44:26 +02:00
|
|
|
PositionVector pos_vec;
|
2023-10-09 19:12:16 -07:00
|
|
|
for (MapIterator map_iter = begin(); map_iter != end(); ++map_iter) {
|
2012-06-29 16:44:26 +02:00
|
|
|
Tile* t = (*map_iter)->get();
|
|
|
|
|
pos_vec.push_back(t->getPosition());
|
|
|
|
|
}
|
2023-10-09 19:12:16 -07:00
|
|
|
for (PositionVector::iterator pos_iter = pos_vec.begin(); pos_iter != pos_vec.end(); ++pos_iter) {
|
2014-01-22 20:16:17 +01:00
|
|
|
setTile(*pos_iter, nullptr, del);
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
void BaseMap::clearVisible(uint32_t mask) {
|
2012-06-29 16:44:26 +02:00
|
|
|
root.clearVisible(mask);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
Tile* BaseMap::createTile(int x, int y, int z) {
|
2023-10-09 23:02:37 -03:00
|
|
|
ASSERT(z < rme::MapLayers);
|
2012-06-29 16:44:26 +02:00
|
|
|
QTreeNode* leaf = root.getLeafForce(x, y);
|
|
|
|
|
TileLocation* loc = leaf->createTile(x, y, z);
|
2023-10-09 19:12:16 -07:00
|
|
|
if (loc->get()) {
|
2012-06-29 16:44:26 +02:00
|
|
|
return loc->get();
|
2023-10-09 19:12:16 -07:00
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
Tile* t = allocator(loc);
|
|
|
|
|
leaf->setTile(x, y, z, t);
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
TileLocation* BaseMap::getTileL(int x, int y, int z) {
|
2023-10-09 23:02:37 -03:00
|
|
|
ASSERT(z < rme::MapLayers);
|
2012-06-29 16:44:26 +02:00
|
|
|
QTreeNode* leaf = root.getLeaf(x, y);
|
2023-10-09 19:12:16 -07:00
|
|
|
if (leaf) {
|
2012-06-29 16:44:26 +02:00
|
|
|
Floor* floor = leaf->getFloor(z);
|
2023-10-09 19:12:16 -07:00
|
|
|
if (floor) {
|
|
|
|
|
return &floor->locs[(x & 3) * 4 + (y & 3)];
|
|
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
2014-01-22 20:16:17 +01:00
|
|
|
return nullptr;
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
const TileLocation* BaseMap::getTileL(int x, int y, int z) const {
|
2012-06-29 16:44:26 +02:00
|
|
|
// Don't create static const maps!
|
|
|
|
|
BaseMap* self = const_cast<BaseMap*>(this);
|
|
|
|
|
return self->getTileL(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
TileLocation* BaseMap::getTileL(const Position &pos) {
|
2012-06-29 16:44:26 +02:00
|
|
|
return getTileL(pos.x, pos.y, pos.z);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
const TileLocation* BaseMap::getTileL(const Position &pos) const {
|
2012-06-29 16:44:26 +02:00
|
|
|
return getTileL(pos.x, pos.y, pos.z);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
TileLocation* BaseMap::createTileL(int x, int y, int z) {
|
2023-10-09 23:02:37 -03:00
|
|
|
ASSERT(z < rme::MapLayers);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
QTreeNode* leaf = root.getLeafForce(x, y);
|
|
|
|
|
Floor* floor = leaf->createFloor(x, y, z);
|
|
|
|
|
uint32_t offsetX = x & 3;
|
|
|
|
|
uint32_t offsetY = y & 3;
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
return &floor->locs[offsetX * 4 + offsetY];
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
TileLocation* BaseMap::createTileL(const Position &pos) {
|
2012-06-29 16:44:26 +02:00
|
|
|
return createTileL(pos.x, pos.y, pos.z);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
void BaseMap::setTile(int x, int y, int z, Tile* new_tile, bool remove) {
|
2023-10-09 23:02:37 -03:00
|
|
|
ASSERT(!new_tile || new_tile->getX() == x);
|
|
|
|
|
ASSERT(!new_tile || new_tile->getY() == y);
|
|
|
|
|
ASSERT(!new_tile || new_tile->getZ() == z);
|
2016-09-29 19:24:45 -03:00
|
|
|
|
2012-06-29 16:44:26 +02:00
|
|
|
QTreeNode* leaf = root.getLeafForce(x, y);
|
2023-10-09 23:02:37 -03:00
|
|
|
Tile* old_tile = leaf->setTile(x, y, z, new_tile);
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
if ((remove && old_tile) || new_tile) {
|
2023-10-09 23:02:37 -03:00
|
|
|
updateUniqueIds(remove ? old_tile : nullptr, new_tile);
|
2023-10-09 19:12:16 -07:00
|
|
|
}
|
2023-10-09 23:02:37 -03:00
|
|
|
|
|
|
|
|
if (remove) {
|
|
|
|
|
delete old_tile;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
void BaseMap::setTile(const Position &position, Tile* new_tile, bool remove) {
|
2023-10-09 23:02:37 -03:00
|
|
|
setTile(position.x, position.y, position.z, new_tile, remove);
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
void BaseMap::setTile(Tile* new_tile, bool remove) {
|
2023-10-09 23:02:37 -03:00
|
|
|
ASSERT(new_tile);
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
const Position &position = new_tile->getPosition();
|
2023-10-09 23:02:37 -03:00
|
|
|
setTile(position.x, position.y, position.z, new_tile, remove);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
Tile* BaseMap::swapTile(int x, int y, int z, Tile* new_tile) {
|
2023-10-09 23:02:37 -03:00
|
|
|
ASSERT(z < rme::MapLayers);
|
|
|
|
|
ASSERT(!new_tile || new_tile->getX() == x);
|
|
|
|
|
ASSERT(!new_tile || new_tile->getY() == y);
|
|
|
|
|
ASSERT(!new_tile || new_tile->getZ() == z);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
QTreeNode* leaf = root.getLeafForce(x, y);
|
2023-10-09 23:02:37 -03:00
|
|
|
Tile* old_tile = leaf->setTile(x, y, z, new_tile);
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
if (old_tile || new_tile) {
|
2023-10-09 23:02:37 -03:00
|
|
|
updateUniqueIds(old_tile, new_tile);
|
2023-10-09 19:12:16 -07:00
|
|
|
}
|
2023-10-09 23:02:37 -03:00
|
|
|
|
|
|
|
|
return old_tile;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
Tile* BaseMap::swapTile(const Position &position, Tile* new_tile) {
|
2023-10-09 23:02:37 -03:00
|
|
|
return swapTile(position.x, position.y, position.z, new_tile);
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Iterators
|
|
|
|
|
|
|
|
|
|
MapIterator::MapIterator(BaseMap* _map) :
|
|
|
|
|
local_i(0),
|
|
|
|
|
local_z(0),
|
2014-01-22 20:16:17 +01:00
|
|
|
current_tile(nullptr),
|
2023-10-09 19:12:16 -07:00
|
|
|
map(_map) {
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
MapIterator::~MapIterator() {
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
MapIterator::MapIterator(const MapIterator &other) {
|
|
|
|
|
for (std::vector<MapIterator::NodeIndex>::const_iterator it = other.nodestack.begin(); it != other.nodestack.end(); it++) {
|
2012-06-29 16:44:26 +02:00
|
|
|
nodestack.push_back(MapIterator::NodeIndex(*it));
|
|
|
|
|
}
|
|
|
|
|
local_i = other.local_i;
|
|
|
|
|
local_z = other.local_z;
|
|
|
|
|
map = other.map;
|
|
|
|
|
current_tile = other.current_tile;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
MapIterator BaseMap::begin() {
|
2012-06-29 16:44:26 +02:00
|
|
|
MapIterator it(this);
|
|
|
|
|
it.nodestack.push_back(MapIterator::NodeIndex(&root));
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
while (true) {
|
|
|
|
|
MapIterator::NodeIndex ¤t = it.nodestack.back();
|
2012-06-29 16:44:26 +02:00
|
|
|
QTreeNode* node = current.node;
|
2023-10-09 19:12:16 -07:00
|
|
|
int &index = current.index;
|
|
|
|
|
// printf("Contemplating %p of %p (stack size %d)\n", node, this, it.nodestack.size());
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
bool unwind = false;
|
2023-10-09 19:12:16 -07:00
|
|
|
for (; index < 16; ++index) {
|
|
|
|
|
// printf("\tChecking index %d of %p\n", index, node);
|
|
|
|
|
if (QTreeNode* child = node->child[index]) {
|
|
|
|
|
if (child->isLeaf) {
|
2012-06-29 16:44:26 +02:00
|
|
|
QTreeNode* leaf = child;
|
2023-10-09 19:12:16 -07:00
|
|
|
// printf("\t%p is leaf\n", child);
|
|
|
|
|
for (it.local_z = 0; it.local_z < rme::MapLayers; ++it.local_z) {
|
|
|
|
|
if (Floor* floor = leaf->array[it.local_z]) {
|
|
|
|
|
for (it.local_i = 0; it.local_i < 16; ++it.local_i) {
|
|
|
|
|
// printf("\tit(%d;%d;%d)\n", it.local_x, it.local_y, it.local_z);
|
|
|
|
|
TileLocation &t = floor->locs[it.local_i];
|
|
|
|
|
if (t.get()) {
|
|
|
|
|
// printf("return it\n");
|
2012-06-29 16:44:26 +02:00
|
|
|
it.current_tile = &t;
|
|
|
|
|
return it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-10-09 19:12:16 -07:00
|
|
|
// printf("\tAdding %p\n", child);
|
2012-06-29 16:44:26 +02:00
|
|
|
++index;
|
|
|
|
|
it.nodestack.push_back(MapIterator::NodeIndex(child));
|
|
|
|
|
unwind = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-09 19:12:16 -07:00
|
|
|
if (unwind) {
|
2012-06-29 16:44:26 +02:00
|
|
|
continue;
|
2023-10-09 19:12:16 -07:00
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
// printf("Discarding dead node %p\n", node);
|
2012-06-29 16:44:26 +02:00
|
|
|
it.nodestack.pop_back();
|
2023-10-09 19:12:16 -07:00
|
|
|
if (it.nodestack.empty()) {
|
2012-06-29 16:44:26 +02:00
|
|
|
break;
|
2023-10-09 19:12:16 -07:00
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
return end();
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
MapIterator BaseMap::end() {
|
2012-06-29 16:44:26 +02:00
|
|
|
MapIterator it(this);
|
|
|
|
|
it.local_i = -1;
|
|
|
|
|
it.local_z = -1;
|
|
|
|
|
return it;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
TileLocation* MapIterator::operator*() {
|
2012-06-29 16:44:26 +02:00
|
|
|
return current_tile;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
TileLocation* MapIterator::operator->() {
|
2012-06-29 16:44:26 +02:00
|
|
|
return current_tile;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
MapIterator &MapIterator::operator++() {
|
|
|
|
|
// printf("MapIterator::operator++");
|
2012-06-29 16:44:26 +02:00
|
|
|
bool increased = false;
|
|
|
|
|
bool first = true;
|
2023-10-09 19:12:16 -07:00
|
|
|
while (true) {
|
|
|
|
|
MapIterator::NodeIndex ¤t = nodestack.back();
|
2012-06-29 16:44:26 +02:00
|
|
|
QTreeNode* node = current.node;
|
2023-10-09 19:12:16 -07:00
|
|
|
int &index = current.index;
|
|
|
|
|
// printf("Contemplating %p (stack size %d)\n", node, nodestack.size());
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
bool unwind = false;
|
2023-10-09 19:12:16 -07:00
|
|
|
for (; index < rme::MapLayers; ++index) {
|
|
|
|
|
// printf("\tChecking index %d of %p\n", index, node);
|
|
|
|
|
if (QTreeNode* child = node->child[index]) {
|
|
|
|
|
if (child->isLeaf) {
|
2012-06-29 16:44:26 +02:00
|
|
|
QTreeNode* leaf = child;
|
2023-10-09 19:12:16 -07:00
|
|
|
// printf("\t%p is leaf\n", child);
|
|
|
|
|
for (; local_z < rme::MapLayers; ++local_z) {
|
|
|
|
|
// printf("\t\tIterating over Z:%d of %p", local_z, child);
|
|
|
|
|
if (Floor* floor = leaf->array[local_z]) {
|
|
|
|
|
// printf("\n");
|
|
|
|
|
for (; local_i < rme::MapLayers; ++local_i) {
|
|
|
|
|
// printf("\t\tIterating over Y:%d of %p\n", local_y, child);
|
|
|
|
|
TileLocation &t = floor->locs[local_i];
|
|
|
|
|
if (t.get()) {
|
|
|
|
|
if (increased) {
|
|
|
|
|
// printf("Modified %p to %p\n", current_tile, t);
|
2012-06-29 16:44:26 +02:00
|
|
|
current_tile = &t;
|
|
|
|
|
return *this;
|
|
|
|
|
} else {
|
|
|
|
|
increased = true;
|
|
|
|
|
}
|
2023-10-09 19:12:16 -07:00
|
|
|
} else if (first) {
|
2012-06-29 16:44:26 +02:00
|
|
|
increased = true;
|
|
|
|
|
first = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-09-29 19:24:45 -03:00
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
if (local_i > rme::MapMaxLayer) {
|
|
|
|
|
// printf("\t\tReset local_x\n");
|
2012-06-29 16:44:26 +02:00
|
|
|
local_i = 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-10-09 19:12:16 -07:00
|
|
|
// printf(":dead floor\n");
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
2023-10-09 19:12:16 -07:00
|
|
|
}
|
|
|
|
|
if (local_z == rme::MapLayers) {
|
|
|
|
|
// printf("\t\tReset local_z\n");
|
|
|
|
|
local_z = 0;
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
2023-10-09 19:12:16 -07:00
|
|
|
// printf("\tAdding %p\n", child);
|
2012-06-29 16:44:26 +02:00
|
|
|
++index;
|
|
|
|
|
nodestack.push_back(MapIterator::NodeIndex(child));
|
|
|
|
|
unwind = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-09 19:12:16 -07:00
|
|
|
if (unwind) {
|
2012-06-29 16:44:26 +02:00
|
|
|
continue;
|
2023-10-09 19:12:16 -07:00
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
// printf("Discarding dead node %p\n", node);
|
2012-06-29 16:44:26 +02:00
|
|
|
nodestack.pop_back();
|
2023-10-09 19:12:16 -07:00
|
|
|
if (nodestack.size() == 0) {
|
2012-06-29 16:44:26 +02:00
|
|
|
// Set all values to "end"
|
2023-10-09 19:12:16 -07:00
|
|
|
// printf("END\n");
|
2012-06-29 16:44:26 +02:00
|
|
|
local_z = -1;
|
|
|
|
|
local_i = -1;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-09 19:12:16 -07:00
|
|
|
MapIterator MapIterator::operator++(int) {
|
2012-06-29 16:44:26 +02:00
|
|
|
MapIterator i(*this);
|
|
|
|
|
++*this;
|
|
|
|
|
return i;
|
|
|
|
|
}
|