mirror of
https://github.com/opentibiabr/remeres-map-editor
synced 2026-08-15 18:26:04 -04:00
371 lines
8 KiB
C++
371 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(g_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() && g_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.");
|
|
}
|
|
g_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 <= GROUND_LAYER && g_settings.getInteger(Config::COMPENSATED_SELECT)) {
|
|
++start.x; ++start.y;
|
|
++end.x; ++end.y;
|
|
}
|
|
}
|
|
result = selection.subsession;
|
|
selection.finish(Selection::SUBTHREAD);
|
|
|
|
return nullptr;
|
|
}
|