mirror of
https://github.com/opentibiabr/remeres-map-editor
synced 2026-08-15 18:26:04 -04:00
Removed libxml2 to use pugixml. Fixed a bug with the progress bar. Changed some things in most xml files that pugixml did not like. Updated the Visual Studio project. Any NULL symbol has been changed to nullptr. This most probably broke the CMake that was recently added. And probably some other things.
398 lines
8 KiB
C++
398 lines
8 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/selection.hpp $
|
|
// $Id: selection.hpp 310 2010-02-26 18:03:48Z admin $
|
|
|
|
#include "main.h"
|
|
|
|
#include "selection.h"
|
|
#include "tile.h"
|
|
#include "creature.h"
|
|
#include "item.h"
|
|
#include "editor.h"
|
|
#include "gui.h"
|
|
|
|
Selection::Selection(Editor& editor) :
|
|
busy(false),
|
|
editor(editor),
|
|
session(nullptr),
|
|
subsession(nullptr)
|
|
{
|
|
}
|
|
|
|
Selection::~Selection()
|
|
{
|
|
delete subsession;
|
|
delete session;
|
|
}
|
|
|
|
Position Selection::minPosition() const
|
|
{
|
|
Position minPos(0x10000, 0x10000, 0x10);
|
|
for (TileVector::const_iterator tile = tiles.begin(); tile != tiles.end(); ++tile)
|
|
{
|
|
Position pos((*tile)->getPosition());
|
|
if (minPos.x > pos.x)
|
|
minPos.x = pos.x;
|
|
if (minPos.y > pos.y)
|
|
minPos.y = pos.y;
|
|
if (minPos.z > pos.z)
|
|
minPos.z = pos.z;
|
|
}
|
|
return minPos;
|
|
}
|
|
|
|
Position Selection::maxPosition() const
|
|
{
|
|
Position maxPos(0, 0, 0);
|
|
for (TileVector::const_iterator tile = tiles.begin(); tile != tiles.end(); ++tile)
|
|
{
|
|
Position pos((*tile)->getPosition());
|
|
if (maxPos.x < pos.x)
|
|
maxPos.x = pos.x;
|
|
if (maxPos.y < pos.y)
|
|
maxPos.y = pos.y;
|
|
if (maxPos.z < pos.z)
|
|
maxPos.z = pos.z;
|
|
}
|
|
return maxPos;
|
|
}
|
|
|
|
void Selection::add(Tile* tile, Item* item)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(item);
|
|
|
|
if(item->isSelected()) return;
|
|
|
|
// Make a copy of the tile with the item selected
|
|
item->select();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
item->deselect();
|
|
|
|
if(settings.getInteger(Config::BORDER_IS_GROUND))
|
|
if(item->isBorder())
|
|
new_tile->selectGround();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::add(Tile* tile, Spawn* spawn)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(spawn);
|
|
|
|
if(spawn->isSelected()) return;
|
|
|
|
// Make a copy of the tile with the item selected
|
|
spawn->select();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
spawn->deselect();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::add(Tile* tile, Creature* creature)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(creature);
|
|
|
|
if(creature->isSelected()) return;
|
|
|
|
// Make a copy of the tile with the item selected
|
|
creature->select();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
creature->deselect();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::add(Tile* tile)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
new_tile->select();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile, Item* item)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(item);
|
|
|
|
bool tmp = item->isSelected();
|
|
item->deselect();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
if(tmp) item->select();
|
|
if(item->isBorder() && settings.getInteger(Config::BORDER_IS_GROUND)) new_tile->deselectGround();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile, Spawn* spawn)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(spawn);
|
|
|
|
bool tmp = spawn->isSelected();
|
|
spawn->deselect();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
if(tmp) spawn->select();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile, Creature* creature)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(creature);
|
|
|
|
bool tmp = creature->isSelected();
|
|
creature->deselect();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
if(tmp) creature->select();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile)
|
|
{
|
|
ASSERT(subsession);
|
|
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
new_tile->deselect();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::addInternal(Tile* tile)
|
|
{
|
|
ASSERT(tile);
|
|
|
|
tiles.push_back(tile);
|
|
erase_iterator = tiles.begin();
|
|
}
|
|
|
|
void Selection::removeInternal(Tile* tile)
|
|
{
|
|
ASSERT(tile);
|
|
#ifdef __DEBUG_MODE__
|
|
TileVector::iterator erase_begin = erase_iterator;
|
|
#endif
|
|
if(tiles.size() == 0)
|
|
return;
|
|
|
|
TileVector::iterator end_iter = tiles.end();
|
|
do {
|
|
if(erase_iterator == end_iter)
|
|
{
|
|
erase_iterator = tiles.begin();
|
|
}
|
|
if(*erase_iterator == tile)
|
|
{
|
|
// Swap & pop trick
|
|
if(*erase_iterator == tiles.back())
|
|
{
|
|
tiles.pop_back();
|
|
erase_iterator = tiles.begin();
|
|
}
|
|
else
|
|
{
|
|
std::swap(*erase_iterator, tiles.back());
|
|
tiles.pop_back();
|
|
erase_iterator = tiles.begin() + (erase_iterator - tiles.begin());
|
|
}
|
|
return;
|
|
}
|
|
++erase_iterator;
|
|
#ifdef __DEBUG_MODE__
|
|
ASSERT(/* This shouldn't happend*/ erase_iterator != erase_begin);
|
|
#endif
|
|
} while(true);
|
|
}
|
|
|
|
void Selection::clear()
|
|
{
|
|
if(session)
|
|
{
|
|
for(TileVector::iterator it = tiles.begin(); it != tiles.end(); it++)
|
|
{
|
|
Tile* new_tile = (*it)->deepCopy(editor.map);
|
|
new_tile->deselect();
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(TileVector::iterator it = tiles.begin(); it != tiles.end(); it++)
|
|
{
|
|
(*it)->deselect();
|
|
}
|
|
tiles.clear();
|
|
}
|
|
}
|
|
|
|
void Selection::start(SessionFlags flags)
|
|
{
|
|
if(!(flags & INTERNAL))
|
|
{
|
|
if(flags & SUBTHREAD)
|
|
{
|
|
;
|
|
}
|
|
else
|
|
{
|
|
session = editor.actionQueue->createBatch(ACTION_SELECT);
|
|
}
|
|
subsession = editor.actionQueue->createAction(ACTION_SELECT);
|
|
}
|
|
erase_iterator = tiles.begin();
|
|
busy = true;
|
|
}
|
|
|
|
void Selection::commit()
|
|
{
|
|
erase_iterator = tiles.begin();
|
|
if(session)
|
|
{
|
|
ASSERT(subsession);
|
|
// We need to step out of the session before we do the action, else peril awaits us!
|
|
BatchAction* tmp = session;
|
|
session = nullptr;
|
|
|
|
// Do the action
|
|
tmp->addAndCommitAction(subsession);
|
|
|
|
// Create a newd action for subsequent selects
|
|
subsession = editor.actionQueue->createAction(ACTION_SELECT);
|
|
session = tmp;
|
|
}
|
|
}
|
|
|
|
void Selection::finish(SessionFlags flags)
|
|
{
|
|
erase_iterator = tiles.begin();
|
|
if(!(flags & INTERNAL))
|
|
{
|
|
if(flags & SUBTHREAD)
|
|
{
|
|
ASSERT(subsession);
|
|
subsession = nullptr;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(session);
|
|
ASSERT(subsession);
|
|
// We need to exit the session before we do the action, else peril awaits us!
|
|
BatchAction* tmp = session;
|
|
session = nullptr;
|
|
|
|
tmp->addAndCommitAction(subsession);
|
|
editor.addBatch(tmp, 2);
|
|
|
|
session = nullptr;
|
|
subsession = nullptr;
|
|
}
|
|
}
|
|
busy = false;
|
|
}
|
|
|
|
void Selection::updateSelectionCount()
|
|
{
|
|
if(size() > 0)
|
|
{
|
|
wxString ss;
|
|
if(size() == 1)
|
|
{
|
|
ss << wxT("One tile selected.");
|
|
}
|
|
else
|
|
{
|
|
ss << size() << wxT(" tiles selected.");
|
|
}
|
|
gui.SetStatusText(ss);
|
|
}
|
|
}
|
|
|
|
void Selection::join(SelectionThread* thread)
|
|
{
|
|
thread->Wait();
|
|
|
|
ASSERT(session);
|
|
session->addAction(thread->result);
|
|
thread->selection.subsession = nullptr;
|
|
|
|
delete thread;
|
|
}
|
|
|
|
SelectionThread::SelectionThread(Editor& editor, Position start, Position end) :
|
|
wxThread(wxTHREAD_JOINABLE),
|
|
editor(editor),
|
|
start(start),
|
|
end(end),
|
|
selection(editor),
|
|
result(nullptr)
|
|
{
|
|
|
|
}
|
|
|
|
SelectionThread::~SelectionThread()
|
|
{
|
|
}
|
|
|
|
void SelectionThread::Execute()
|
|
{
|
|
Create();
|
|
Run();
|
|
}
|
|
|
|
wxThread::ExitCode SelectionThread::Entry()
|
|
{
|
|
selection.start(Selection::SUBTHREAD);
|
|
for(int z = start.z; z >= end.z; --z)
|
|
{
|
|
for(int x = start.x; x <= end.x; ++x)
|
|
{
|
|
for(int y = start.y; y <= end.y; ++y)
|
|
{
|
|
Tile* tile = editor.map.getTile(x, y, z);
|
|
if(!tile)
|
|
continue;
|
|
|
|
selection.add(tile);
|
|
}
|
|
}
|
|
if(z <= 7 && settings.getInteger(Config::COMPENSATED_SELECT))
|
|
{
|
|
++start.x; ++start.y;
|
|
++end.x; ++end.y;
|
|
}
|
|
}
|
|
result = selection.subsession;
|
|
selection.finish(Selection::SUBTHREAD);
|
|
|
|
return nullptr;
|
|
}
|