Beispiel #1
0
void Selection::finish(SessionFlags flags)
{
	erase_iterator = tiles.begin();
	if(!(flags & INTERNAL))
	{
		if(flags & SUBTHREAD)
		{
			ASSERT(subsession);
			subsession = NULL;
		}
		else
		{
			ASSERT(session);
			ASSERT(subsession);
			// We need to exit the session before we do the action, else peril awaits us!
			BatchAction* tmp = session;
			session = NULL;

			tmp->addAndCommitAction(subsession);
			editor.addBatch(tmp, 2);

			session = NULL;
			subsession = NULL;
		}
	}
	busy = false;
}
Beispiel #2
0
void ActionQueue::undo()
{
	if(current > 0)
	{
		current--;
		BatchAction* batch = actions[current];
		batch->undo();
	}
}
Beispiel #3
0
void ActionQueue::redo()
{
	if(current < actions.size())
	{
		BatchAction* batch = actions[current];
		batch->redo();
		current++;
	}
}
Beispiel #4
0
void ActionQueue::addAction(Action* action, int stacking_delay)
{
	BatchAction* batch = createBatch(action->getType());
	batch->addAndCommitAction(action);
	if(batch->size() == 0)
	{
		delete batch;
		return;
	}

	addBatch(batch, stacking_delay);
}
Beispiel #5
0
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;
	}
}
Beispiel #6
0
void ActionQueue::addBatch(BatchAction* batch, int stacking_delay)
{
	ASSERT(batch);
	ASSERT(current <= actions.size());

	if(batch->size() == 0)
	{
		delete batch;
		return;
	}
	// Commit any uncommited actions...
	batch->commit();

	// Update title
	if(editor.map.doChange())
		gui.UpdateTitle();
		
	if(batch->type == ACTION_REMOTE)
	{
		delete batch;
		return;
	}

	while(current != actions.size())
	{
		memory_size -= actions.back()->memsize();
		BatchAction* todelete = actions.back();
		actions.pop_back();
		delete todelete;
	}

	while(memory_size > size_t(1024 * 1024 * settings.getInteger(Config::UNDO_MEM_SIZE)) && actions.empty() == false)
	{
		memory_size -= actions.front()->memsize();
		delete actions.front();
		actions.pop_front();
		current--;
	}

	if(actions.size() > size_t(settings.getInteger(Config::UNDO_SIZE)) && actions.empty() == false)
	{
		memory_size -= actions.front()->memsize();
		BatchAction* todelete = actions.front();
		actions.pop_front();
		delete todelete;
		current--;
	}

	do {
		if(actions.empty() == false)
		{
			BatchAction* lastAction = actions.back();
			if(lastAction->type == batch->type && settings.getInteger(Config::GROUP_ACTIONS) && time(nullptr) - stacking_delay < lastAction->timestamp)
			{
				lastAction->merge(batch);
				lastAction->timestamp = time(nullptr);
				memory_size -= lastAction->memsize();
				memory_size += lastAction->memsize(true);
				delete batch;
				break;
			}
		}
		memory_size += batch->memsize();
		actions.push_back(batch);
		batch->timestamp = time(nullptr);
		current++;
	} while(false);
}
Beispiel #7
0
void CopyBuffer::paste(Editor& editor, const Position& toPosition)
{
	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 + toPosition;

		if(!pos.isValid())
			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 = nullptr;
		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 + toPosition;
			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();

		for(Tile* tile : borderize_tiles) {
			if(tile) {
				Tile* newTile = tile->deepCopy(editor.map);
				newTile->borderize(&map);
				
				if(tile->ground && tile->ground->isSelected()) {
					newTile->selectGround();
				}

				newTile->wallize(&map);
				action->addChange(newd Change(newTile));
			}
		}

		// Commit changes to map
		batchAction->addAndCommitAction(action);
	}

	editor.addBatch(batchAction);
}
Beispiel #8
0
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 = nullptr;
		}

		if(newtile->spawn && newtile->spawn->isSelected()) {
			copied_tile->spawn = newtile->spawn;
			newtile->spawn = nullptr;
		}

		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()));
}