////////////////////////////////////////////////////////////////////// // This file is part of Remere's Map Editor ////////////////////////////////////////////////////////////////////// // Remere's Map Editor is free software: you can redistribute it and/or modify // 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. // // Remere's Map Editor is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ////////////////////////////////////////////////////////////////////// #include "main.h" #include "tile.h" #include "basemap.h" BaseMap::BaseMap() : allocator(), tilecount(0), root(*this) { //// } BaseMap::~BaseMap() { //// } void BaseMap::clear(bool del) { PositionVector pos_vec; for(MapIterator map_iter = begin(); map_iter != end(); ++map_iter) { Tile* t = (*map_iter)->get(); pos_vec.push_back(t->getPosition()); } for(PositionVector::iterator pos_iter = pos_vec.begin(); pos_iter != pos_vec.end(); ++pos_iter) { setTile(*pos_iter, nullptr, del); } } void BaseMap::clearVisible(uint32_t mask) { root.clearVisible(mask); } Tile* BaseMap::createTile(int x, int y, int z) { ASSERT(z < rme::MapLayers); QTreeNode* leaf = root.getLeafForce(x, y); TileLocation* loc = leaf->createTile(x, y, z); if(loc->get()) return loc->get(); Tile* t = allocator(loc); leaf->setTile(x, y, z, t); return t; } TileLocation* BaseMap::getTileL(int x, int y, int z) { ASSERT(z < rme::MapLayers); QTreeNode* leaf = root.getLeaf(x, y); if(leaf) { Floor* floor = leaf->getFloor(z); if(floor) return &floor->locs[(x & 3)*4 + (y & 3)]; } return nullptr; } const TileLocation* BaseMap::getTileL(int x, int y, int z) const { // Don't create static const maps! BaseMap* self = const_cast(this); return self->getTileL(x, y, z); } TileLocation* BaseMap::getTileL(const Position& pos) { return getTileL(pos.x, pos.y, pos.z); } const TileLocation* BaseMap::getTileL(const Position& pos) const { return getTileL(pos.x, pos.y, pos.z); } TileLocation* BaseMap::createTileL(int x, int y, int z) { ASSERT(z < rme::MapLayers); QTreeNode* leaf = root.getLeafForce(x, y); Floor* floor = leaf->createFloor(x, y, z); uint32_t offsetX = x & 3; uint32_t offsetY = y & 3; return &floor->locs[offsetX*4+offsetY]; } TileLocation* BaseMap::createTileL(const Position& pos) { return createTileL(pos.x, pos.y, pos.z); } void BaseMap::setTile(int x, int y, int z, Tile* new_tile, bool remove) { ASSERT(!new_tile || new_tile->getX() == x); ASSERT(!new_tile || new_tile->getY() == y); ASSERT(!new_tile || new_tile->getZ() == z); QTreeNode* leaf = root.getLeafForce(x, y); Tile* old_tile = leaf->setTile(x, y, z, new_tile); if ((remove && old_tile) || new_tile) updateUniqueIds(remove ? old_tile : nullptr, new_tile); if (remove) { delete old_tile; } } void BaseMap::setTile(const Position& position, Tile* new_tile, bool remove) { setTile(position.x, position.y, position.z, new_tile, remove); } void BaseMap::setTile(Tile* new_tile, bool remove) { ASSERT(new_tile); const Position& position = new_tile->getPosition(); setTile(position.x, position.y, position.z, new_tile, remove); } Tile* BaseMap::swapTile(int x, int y, int z, Tile* new_tile) { 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); QTreeNode* leaf = root.getLeafForce(x, y); Tile* old_tile = leaf->setTile(x, y, z, new_tile); if (old_tile || new_tile) updateUniqueIds(old_tile, new_tile); return old_tile; } Tile* BaseMap::swapTile(const Position& position, Tile* new_tile) { return swapTile(position.x, position.y, position.z, new_tile); } // Iterators MapIterator::MapIterator(BaseMap* _map) : local_i(0), local_z(0), current_tile(nullptr), map(_map) { //// } MapIterator::~MapIterator() { //// } MapIterator::MapIterator(const MapIterator& other) { for(std::vector::const_iterator it = other.nodestack.begin(); it != other.nodestack.end(); it++) { nodestack.push_back(MapIterator::NodeIndex(*it)); } local_i = other.local_i; local_z = other.local_z; map = other.map; current_tile = other.current_tile; } MapIterator BaseMap::begin() { MapIterator it(this); it.nodestack.push_back(MapIterator::NodeIndex(&root)); while(true) { MapIterator::NodeIndex& current = it.nodestack.back(); QTreeNode* node = current.node; int& index = current.index; //printf("Contemplating %p of %p (stack size %d)\n", node, this, it.nodestack.size()); bool unwind = false; for(; index < 16; ++index) { //printf("\tChecking index %d of %p\n", index, node); if(QTreeNode* child = node->child[index]) { if(child->isLeaf) { QTreeNode* leaf = child; //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"); it.current_tile = &t; return it; } } } } } else { //printf("\tAdding %p\n", child); ++index; it.nodestack.push_back(MapIterator::NodeIndex(child)); unwind = true; break; } } } if(unwind) continue; //printf("Discarding dead node %p\n", node); it.nodestack.pop_back(); if(it.nodestack.empty()) break; } return end(); } MapIterator BaseMap::end() { MapIterator it(this); it.local_i = -1; it.local_z = -1; return it; } TileLocation* MapIterator::operator*() { return current_tile; } TileLocation* MapIterator::operator->() { return current_tile; } MapIterator& MapIterator::operator++() { //printf("MapIterator::operator++"); bool increased = false; bool first = true; while(true) { MapIterator::NodeIndex& current = nodestack.back(); QTreeNode* node = current.node; int& index = current.index; //printf("Contemplating %p (stack size %d)\n", node, nodestack.size()); bool unwind = false; for(; index < rme::MapLayers; ++index) { //printf("\tChecking index %d of %p\n", index, node); if(QTreeNode* child = node->child[index]) { if(child->isLeaf) { QTreeNode* leaf = child; //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); current_tile = &t; return *this; } else { increased = true; } } else if(first) { increased = true; first = false; } } if(local_i > rme::MapMaxLayer) { //printf("\t\tReset local_x\n"); local_i = 0; } } else { //printf(":dead floor\n"); } } if(local_z == rme::MapLayers) { //printf("\t\tReset local_z\n"); local_z = 0; } } else { //printf("\tAdding %p\n", child); ++index; nodestack.push_back(MapIterator::NodeIndex(child)); unwind = true; break; } } } if(unwind) continue; //printf("Discarding dead node %p\n", node); nodestack.pop_back(); if(nodestack.size() == 0) { // Set all values to "end" //printf("END\n"); local_z = -1; local_i = -1; return *this; } } return *this; } MapIterator MapIterator::operator++(int) { MapIterator i(*this); ++*this; return i; }