mirror of
https://github.com/opentibiabr/remeres-map-editor
synced 2026-08-15 18:26:04 -04:00
Clean git repository since the old svn / git mess was pretty much unrecoverable unfortunetly. I would have liked to keep the history for posterity, but that proved to be a futile quest.
353 lines
9.7 KiB
C++
353 lines
9.7 KiB
C++
//////////////////////////////////////////////////////////////////////
|
|
// This file is part of Remere's Map Editor
|
|
//////////////////////////////////////////////////////////////////////
|
|
// This program 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.
|
|
//
|
|
// This program 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 <http://www.gnu.org/licenses/>.
|
|
//////////////////////////////////////////////////////////////////////
|
|
// $URL: http://svn.rebarp.se/svn/RME/trunk/source/copybuffer.hpp $
|
|
// $Id: copybuffer.hpp 313 2010-02-26 20:09:26Z admin $
|
|
|
|
#include "main.h"
|
|
|
|
#include "copybuffer.h"
|
|
#include "editor.h"
|
|
#include "gui.h"
|
|
#include "creature.h"
|
|
|
|
CopyBuffer::CopyBuffer() :
|
|
tiles(newd BaseMap())
|
|
{
|
|
;
|
|
}
|
|
|
|
size_t CopyBuffer::GetTileCount()
|
|
{
|
|
return tiles ? (size_t)tiles->size() : 0;
|
|
}
|
|
|
|
BaseMap& CopyBuffer::getBufferMap()
|
|
{
|
|
ASSERT(tiles);
|
|
return *tiles;
|
|
}
|
|
|
|
CopyBuffer::~CopyBuffer()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
Position CopyBuffer::getPosition() const
|
|
{
|
|
ASSERT(tiles);
|
|
return copyPos;
|
|
}
|
|
|
|
void CopyBuffer::clear() {
|
|
delete tiles;
|
|
tiles = NULL;
|
|
}
|
|
|
|
void CopyBuffer::copy(Editor& editor, int floor)
|
|
{
|
|
if(editor.selection.size() == 0)
|
|
{
|
|
gui.SetStatusText(wxT("No tiles to copy."));
|
|
return;
|
|
}
|
|
|
|
clear();
|
|
tiles = newd BaseMap();
|
|
|
|
int tile_count = 0;
|
|
int item_count = 0;
|
|
copyPos = Position(0xFFFF, 0xFFFF, floor);
|
|
|
|
for(TileVector::iterator it = editor.selection.begin(); it != editor.selection.end(); ++it)
|
|
{
|
|
++tile_count;
|
|
|
|
Tile* tile = *it;
|
|
TileLocation* newlocation = tiles->createTileL(tile->getPosition());
|
|
Tile* copied_tile = tiles->allocator(newlocation);
|
|
|
|
if(tile->ground && tile->ground->isSelected())
|
|
{
|
|
copied_tile->house_id = tile->house_id;
|
|
copied_tile->setMapFlags(tile->getMapFlags());
|
|
}
|
|
|
|
ItemVector tile_selection = tile->getSelectedItems();
|
|
for(ItemVector::iterator iit = tile_selection.begin();
|
|
iit != tile_selection.end();
|
|
++iit)
|
|
{
|
|
++item_count;
|
|
// Copy items to copybuffer
|
|
copied_tile->addItem((*iit)->deepCopy());
|
|
}
|
|
|
|
if(tile->creature && tile->creature->isSelected())
|
|
{
|
|
copied_tile->creature = tile->creature->deepCopy();
|
|
}
|
|
if(tile->spawn && tile->spawn->isSelected())
|
|
{
|
|
copied_tile->spawn = tile->spawn->deepCopy();
|
|
}
|
|
|
|
tiles->setTile(copied_tile);
|
|
|
|
if(copied_tile->getX() < copyPos.x)
|
|
copyPos.x = copied_tile->getX();
|
|
|
|
if(copied_tile->getY() < copyPos.y)
|
|
copyPos.y = copied_tile->getY();
|
|
}
|
|
|
|
std::ostringstream ss;
|
|
ss << "Copied " << tile_count << " tile" << (tile_count > 1 ? "s" : "") << " (" << item_count << " item" << (item_count > 1? "s" : "") << ")";
|
|
gui.SetStatusText(wxstr(ss.str()));
|
|
}
|
|
|
|
void CopyBuffer::cut(Editor& editor, int floor)
|
|
{
|
|
if(editor.selection.size() == 0)
|
|
{
|
|
gui.SetStatusText(wxT("No tiles to cut."));
|
|
return;
|
|
}
|
|
|
|
clear();
|
|
tiles = newd BaseMap();
|
|
|
|
int tile_count = 0;
|
|
int item_count = 0;
|
|
copyPos = Position(0xFFFF, 0xFFFF, floor);
|
|
|
|
BatchAction* batch = editor.actionQueue->createBatch(ACTION_CUT_TILES);
|
|
Action* action = editor.actionQueue->createAction(batch);
|
|
|
|
PositionList tilestoborder;
|
|
|
|
for(TileVector::iterator it = editor.selection.begin(); it != editor.selection.end(); ++it)
|
|
{
|
|
tile_count++;
|
|
|
|
Tile* tile = *it;
|
|
Tile* newtile = tile->deepCopy(editor.map);
|
|
Tile* copied_tile = tiles->allocator(tile->getLocation());
|
|
|
|
if(tile->ground && tile->ground->isSelected()) {
|
|
copied_tile->house_id = newtile->house_id;
|
|
newtile->house_id = 0;
|
|
copied_tile->setMapFlags(tile->getMapFlags());
|
|
newtile->setMapFlags(TILESTATE_NONE);
|
|
}
|
|
|
|
ItemVector tile_selection = newtile->popSelectedItems();
|
|
for(ItemVector::iterator iit = tile_selection.begin();
|
|
iit != tile_selection.end();
|
|
++iit)
|
|
{
|
|
item_count++;
|
|
// Add items to copybuffer
|
|
copied_tile->addItem(*iit);
|
|
}
|
|
|
|
if(newtile->creature && newtile->creature->isSelected())
|
|
{
|
|
copied_tile->creature = newtile->creature;
|
|
newtile->creature = NULL;
|
|
}
|
|
|
|
if(newtile->spawn && newtile->spawn->isSelected())
|
|
{
|
|
copied_tile->spawn = newtile->spawn;
|
|
newtile->spawn = NULL;
|
|
}
|
|
|
|
tiles->setTile(copied_tile->getPosition(), copied_tile);
|
|
|
|
if(copied_tile->getX() < copyPos.x)
|
|
{
|
|
copyPos.x = copied_tile->getX();
|
|
}
|
|
|
|
if(copied_tile->getY() < copyPos.y)
|
|
{
|
|
copyPos.y = copied_tile->getY();
|
|
}
|
|
|
|
if(settings.getInteger(Config::USE_AUTOMAGIC))
|
|
{
|
|
for(int y = -1; y <= 1; y++)
|
|
for(int x = -1; x <= 1; x++)
|
|
tilestoborder.push_back(Position(tile->getX() + x, tile->getY() + y, tile->getZ()));
|
|
}
|
|
action->addChange(newd Change(newtile));
|
|
}
|
|
|
|
batch->addAndCommitAction(action);
|
|
|
|
// Remove duplicates
|
|
tilestoborder.sort();
|
|
tilestoborder.unique();
|
|
|
|
if(settings.getInteger(Config::USE_AUTOMAGIC))
|
|
{
|
|
action = editor.actionQueue->createAction(batch);
|
|
for(PositionList::iterator it = tilestoborder.begin(); it != tilestoborder.end(); ++it)
|
|
{
|
|
TileLocation* location = editor.map.createTileL(*it);
|
|
if(location->get())
|
|
{
|
|
Tile* new_tile = location->get()->deepCopy(editor.map);
|
|
new_tile->borderize(&editor.map);
|
|
new_tile->wallize(&editor.map);
|
|
action->addChange(newd Change(new_tile));
|
|
}
|
|
else
|
|
{
|
|
Tile* new_tile = editor.map.allocator(location);
|
|
new_tile->borderize(&editor.map);
|
|
if(new_tile->size())
|
|
{
|
|
action->addChange(newd Change(new_tile));
|
|
}
|
|
else
|
|
{
|
|
delete new_tile;
|
|
}
|
|
}
|
|
}
|
|
|
|
batch->addAndCommitAction(action);
|
|
}
|
|
|
|
editor.addBatch(batch);
|
|
std::stringstream ss;
|
|
ss << "Cut out " << tile_count << " tile" << (tile_count > 1 ? "s" : "") << " (" << item_count << " item" << (item_count > 1? "s" : "") << ")";
|
|
gui.SetStatusText(wxstr(ss.str()));
|
|
}
|
|
|
|
void CopyBuffer::paste(Editor& editor, Position topos)
|
|
{
|
|
if(!tiles)
|
|
return;
|
|
|
|
BatchAction* batchAction = editor.actionQueue->createBatch(ACTION_PASTE_TILES);
|
|
|
|
Action* action = editor.actionQueue->createAction(batchAction);
|
|
for(MapIterator it = tiles->begin();
|
|
it != tiles->end();
|
|
++it)
|
|
{
|
|
Tile* buffer_tile = (*it)->get();
|
|
Position pos = buffer_tile->getPosition() - copyPos + topos;
|
|
|
|
if(pos.isValid() == false)
|
|
continue;
|
|
|
|
TileLocation* location = editor.map.createTileL(pos);
|
|
Tile* copy_tile = buffer_tile->deepCopy(editor.map);
|
|
Tile* old_dest_tile = location->get();
|
|
Tile* new_dest_tile = NULL;
|
|
copy_tile->setLocation(location);
|
|
|
|
if(settings.getInteger(Config::MERGE_PASTE) || !copy_tile->ground)
|
|
{
|
|
if(old_dest_tile)
|
|
new_dest_tile = old_dest_tile->deepCopy(editor.map);
|
|
else
|
|
new_dest_tile = editor.map.allocator(location);
|
|
new_dest_tile->merge(copy_tile);
|
|
delete copy_tile;
|
|
}
|
|
else
|
|
{
|
|
// If the copied tile has ground, replace target tile
|
|
new_dest_tile = copy_tile;
|
|
}
|
|
|
|
// Add all surrounding tiles to the map, so they get borders
|
|
editor.map.createTile(pos.x-1, pos.y-1, pos.z);
|
|
editor.map.createTile(pos.x , pos.y-1, pos.z);
|
|
editor.map.createTile(pos.x+1, pos.y-1, pos.z);
|
|
editor.map.createTile(pos.x-1, pos.y , pos.z);
|
|
editor.map.createTile(pos.x+1, pos.y , pos.z);
|
|
editor.map.createTile(pos.x-1, pos.y+1, pos.z);
|
|
editor.map.createTile(pos.x , pos.y+1, pos.z);
|
|
editor.map.createTile(pos.x+1, pos.y+1, pos.z);
|
|
|
|
action->addChange(newd Change(new_dest_tile));
|
|
}
|
|
batchAction->addAndCommitAction(action);
|
|
|
|
if(settings.getInteger(Config::USE_AUTOMAGIC) && settings.getInteger(Config::BORDERIZE_PASTE))
|
|
{
|
|
action = editor.actionQueue->createAction(batchAction);
|
|
TileList borderize_tiles;
|
|
Map& map = editor.map;
|
|
|
|
// Go through all modified (selected) tiles (might be slow)
|
|
for(MapIterator it = tiles->begin();
|
|
it != tiles->end();
|
|
++it)
|
|
{
|
|
bool add_me = false; // If this tile is touched
|
|
Position pos = (*it)->getPosition() - copyPos + topos;
|
|
if(pos.z < 0 || pos.z >= MAP_HEIGHT) {
|
|
continue;
|
|
}
|
|
// Go through all neighbours
|
|
Tile* t;
|
|
t = map.getTile(pos.x-1, pos.y-1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;}
|
|
t = map.getTile(pos.x , pos.y-1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;}
|
|
t = map.getTile(pos.x+1, pos.y-1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;}
|
|
t = map.getTile(pos.x-1, pos.y , pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;}
|
|
t = map.getTile(pos.x+1, pos.y , pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;}
|
|
t = map.getTile(pos.x-1, pos.y+1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;}
|
|
t = map.getTile(pos.x , pos.y+1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;}
|
|
t = map.getTile(pos.x+1, pos.y+1, pos.z); if(t && !t->isSelected()) {borderize_tiles.push_back(t); add_me = true;}
|
|
if(add_me) borderize_tiles.push_back(map.getTile(pos));
|
|
}
|
|
// Remove duplicates
|
|
borderize_tiles.sort();
|
|
borderize_tiles.unique();
|
|
// Do le borders!
|
|
for(TileList::iterator it = borderize_tiles.begin(); it != borderize_tiles.end(); it++)
|
|
{
|
|
Tile* tile = *it;
|
|
if(tile)
|
|
{
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
new_tile->borderize(&map);
|
|
if(tile->ground && tile->ground->isSelected())
|
|
new_tile->selectGround();
|
|
|
|
new_tile->wallize(&map);
|
|
action->addChange(newd Change(new_tile));
|
|
}
|
|
}
|
|
// Commit changes to map
|
|
batchAction->addAndCommitAction(action);
|
|
}
|
|
|
|
editor.addBatch(batchAction);
|
|
}
|
|
|
|
bool CopyBuffer::canPaste() const
|
|
{
|
|
return tiles && tiles->size() != 0;
|
|
}
|
|
|