Merge pull request #55 from huderlem/resize
Map resizing and improved floodfill
This commit is contained in:
commit
52679eb53f
7 changed files with 350 additions and 90 deletions
182
editor.cpp
182
editor.cpp
|
@ -26,13 +26,15 @@ void Editor::save() {
|
||||||
|
|
||||||
void Editor::undo() {
|
void Editor::undo() {
|
||||||
if (current_view) {
|
if (current_view) {
|
||||||
((MapPixmapItem*)current_view)->undo();
|
map->undo();
|
||||||
|
map_item->draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::redo() {
|
void Editor::redo() {
|
||||||
if (current_view) {
|
if (current_view) {
|
||||||
((MapPixmapItem*)current_view)->redo();
|
map->redo();
|
||||||
|
map_item->draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +60,7 @@ void Editor::setEditingMap() {
|
||||||
void Editor::setEditingCollision() {
|
void Editor::setEditingCollision() {
|
||||||
current_view = collision_item;
|
current_view = collision_item;
|
||||||
if (collision_item) {
|
if (collision_item) {
|
||||||
|
displayMapConnections();
|
||||||
collision_item->draw();
|
collision_item->draw();
|
||||||
collision_item->setVisible(true);
|
collision_item->setVisible(true);
|
||||||
setConnectionsVisibility(true);
|
setConnectionsVisibility(true);
|
||||||
|
@ -318,8 +321,8 @@ void Editor::setMap(QString map_name) {
|
||||||
}
|
}
|
||||||
if (project) {
|
if (project) {
|
||||||
map = project->loadMap(map_name);
|
map = project->loadMap(map_name);
|
||||||
displayMap();
|
|
||||||
selected_events->clear();
|
selected_events->clear();
|
||||||
|
displayMap();
|
||||||
updateSelectedEvents();
|
updateSelectedEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -879,9 +882,6 @@ void MetatilesPixmapItem::updateSelection(QPointF pos, Qt::MouseButton button) {
|
||||||
map->paint_tile_index = baseTileY * 8 + baseTileX;
|
map->paint_tile_index = baseTileY * 8 + baseTileX;
|
||||||
map->paint_tile_width = abs(map->paint_metatile_initial_x - x) + 1;
|
map->paint_tile_width = abs(map->paint_metatile_initial_x - x) + 1;
|
||||||
map->paint_tile_height = abs(map->paint_metatile_initial_y - y) + 1;
|
map->paint_tile_height = abs(map->paint_metatile_initial_y - y) + 1;
|
||||||
map->smart_paths_enabled = button == Qt::RightButton
|
|
||||||
&& map->paint_tile_width == 3
|
|
||||||
&& map->paint_tile_height == 3;
|
|
||||||
emit map->paintTileChanged(map);
|
emit map->paintTileChanged(map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1029,7 +1029,7 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
|
||||||
int x = (int)(pos.x()) / 16;
|
int x = (int)(pos.x()) / 16;
|
||||||
int y = (int)(pos.y()) / 16;
|
int y = (int)(pos.y()) / 16;
|
||||||
|
|
||||||
if (map->smart_paths_enabled) {
|
if (map->smart_paths_enabled && map->paint_tile_width == 3 && map->paint_tile_height == 3) {
|
||||||
paintSmartPath(x, y);
|
paintSmartPath(x, y);
|
||||||
} else {
|
} else {
|
||||||
paintNormal(x, y);
|
paintNormal(x, y);
|
||||||
|
@ -1157,11 +1157,163 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
|
||||||
QPointF pos = event->pos();
|
QPointF pos = event->pos();
|
||||||
int x = (int)(pos.x()) / 16;
|
int x = (int)(pos.x()) / 16;
|
||||||
int y = (int)(pos.y()) / 16;
|
int y = (int)(pos.y()) / 16;
|
||||||
map->floodFill(x, y, map->getSelectedBlockIndex(map->paint_tile_index));
|
Block *block = map->getBlock(x, y);
|
||||||
|
int tile = map->getSelectedBlockIndex(map->paint_tile_index);
|
||||||
|
if (block && block->tile != tile) {
|
||||||
|
if (map->smart_paths_enabled && map->paint_tile_width == 3 && map->paint_tile_height == 3)
|
||||||
|
this->_floodFillSmartPath(x, y);
|
||||||
|
else
|
||||||
|
this->_floodFill(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||||
|
map->commit();
|
||||||
|
}
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapPixmapItem::_floodFill(int initialX, int initialY) {
|
||||||
|
QList<QPoint> todo;
|
||||||
|
todo.append(QPoint(initialX, initialY));
|
||||||
|
while (todo.length()) {
|
||||||
|
QPoint point = todo.takeAt(0);
|
||||||
|
int x = point.x();
|
||||||
|
int y = point.y();
|
||||||
|
|
||||||
|
Block *block = map->getBlock(x, y);
|
||||||
|
if (block == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xDiff = x - initialX;
|
||||||
|
int yDiff = y - initialY;
|
||||||
|
int i = xDiff % map->paint_tile_width;
|
||||||
|
int j = yDiff % map->paint_tile_height;
|
||||||
|
if (i < 0) i = map->paint_tile_width + i;
|
||||||
|
if (j < 0) j = map->paint_tile_height + j;
|
||||||
|
int tile = map->getSelectedBlockIndex(map->paint_tile_index + i + (j * 8));
|
||||||
|
uint old_tile = block->tile;
|
||||||
|
if (old_tile == tile) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
block->tile = tile;
|
||||||
|
map->_setBlock(x, y, *block);
|
||||||
|
if ((block = map->getBlock(x + 1, y)) && block->tile == old_tile) {
|
||||||
|
todo.append(QPoint(x + 1, y));
|
||||||
|
}
|
||||||
|
if ((block = map->getBlock(x - 1, y)) && block->tile == old_tile) {
|
||||||
|
todo.append(QPoint(x - 1, y));
|
||||||
|
}
|
||||||
|
if ((block = map->getBlock(x, y + 1)) && block->tile == old_tile) {
|
||||||
|
todo.append(QPoint(x, y + 1));
|
||||||
|
}
|
||||||
|
if ((block = map->getBlock(x, y - 1)) && block->tile == old_tile) {
|
||||||
|
todo.append(QPoint(x, y - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapPixmapItem::_floodFillSmartPath(int initialX, int initialY) {
|
||||||
|
// Smart path should never be enabled without a 3x3 block selection.
|
||||||
|
if (map->paint_tile_width != 3 || map->paint_tile_height != 3) return;
|
||||||
|
|
||||||
|
// Shift to the middle tile of the smart path selection.
|
||||||
|
int openTile = map->paint_tile_index + 8 + 1;
|
||||||
|
|
||||||
|
// Flood fill the region with the open tile.
|
||||||
|
QList<QPoint> todo;
|
||||||
|
todo.append(QPoint(initialX, initialY));
|
||||||
|
while (todo.length()) {
|
||||||
|
QPoint point = todo.takeAt(0);
|
||||||
|
int x = point.x();
|
||||||
|
int y = point.y();
|
||||||
|
|
||||||
|
Block *block = map->getBlock(x, y);
|
||||||
|
if (block == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tile = map->getSelectedBlockIndex(openTile);
|
||||||
|
uint old_tile = block->tile;
|
||||||
|
if (old_tile == tile) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
block->tile = tile;
|
||||||
|
map->_setBlock(x, y, *block);
|
||||||
|
if ((block = map->getBlock(x + 1, y)) && block->tile == old_tile) {
|
||||||
|
todo.append(QPoint(x + 1, y));
|
||||||
|
}
|
||||||
|
if ((block = map->getBlock(x - 1, y)) && block->tile == old_tile) {
|
||||||
|
todo.append(QPoint(x - 1, y));
|
||||||
|
}
|
||||||
|
if ((block = map->getBlock(x, y + 1)) && block->tile == old_tile) {
|
||||||
|
todo.append(QPoint(x, y + 1));
|
||||||
|
}
|
||||||
|
if ((block = map->getBlock(x, y - 1)) && block->tile == old_tile) {
|
||||||
|
todo.append(QPoint(x, y - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go back and resolve the flood-filled edge tiles.
|
||||||
|
// Mark tiles as visited while we go.
|
||||||
|
bool visited[map->getWidth() * map->getHeight()];
|
||||||
|
for (int i = 0; i < sizeof visited; i++)
|
||||||
|
visited[i] = false;
|
||||||
|
|
||||||
|
todo.append(QPoint(initialX, initialY));
|
||||||
|
while (todo.length()) {
|
||||||
|
QPoint point = todo.takeAt(0);
|
||||||
|
int x = point.x();
|
||||||
|
int y = point.y();
|
||||||
|
visited[x + y * map->getWidth()] = true;
|
||||||
|
|
||||||
|
Block *block = map->getBlock(x, y);
|
||||||
|
if (block == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = 0;
|
||||||
|
Block *top = map->getBlock(x, y - 1);
|
||||||
|
Block *right = map->getBlock(x + 1, y);
|
||||||
|
Block *bottom = map->getBlock(x, y + 1);
|
||||||
|
Block *left = map->getBlock(x - 1, y);
|
||||||
|
|
||||||
|
// Get marching squares value, to determine which tile to use.
|
||||||
|
if (top && IS_SMART_PATH_TILE(top))
|
||||||
|
id += 1;
|
||||||
|
if (right && IS_SMART_PATH_TILE(right))
|
||||||
|
id += 2;
|
||||||
|
if (bottom && IS_SMART_PATH_TILE(bottom))
|
||||||
|
id += 4;
|
||||||
|
if (left && IS_SMART_PATH_TILE(left))
|
||||||
|
id += 8;
|
||||||
|
|
||||||
|
block->tile = map->getSelectedBlockIndex(map->paint_tile_index + smartPathTable[id]);
|
||||||
|
map->_setBlock(x, y, *block);
|
||||||
|
|
||||||
|
// Visit neighbors if they are smart-path tiles, and don't revisit any.
|
||||||
|
if (!visited[x + 1 + y * map->getWidth()] && (block = map->getBlock(x + 1, y)) && IS_SMART_PATH_TILE(block)) {
|
||||||
|
todo.append(QPoint(x + 1, y));
|
||||||
|
visited[x + 1 + y * map->getWidth()] = true;
|
||||||
|
}
|
||||||
|
if (!visited[x - 1 + y * map->getWidth()] && (block = map->getBlock(x - 1, y)) && IS_SMART_PATH_TILE(block)) {
|
||||||
|
todo.append(QPoint(x - 1, y));
|
||||||
|
visited[x - 1 + y * map->getWidth()] = true;
|
||||||
|
}
|
||||||
|
if (!visited[x + (y + 1) * map->getWidth()] && (block = map->getBlock(x, y + 1)) && IS_SMART_PATH_TILE(block)) {
|
||||||
|
todo.append(QPoint(x, y + 1));
|
||||||
|
visited[x + (y + 1) * map->getWidth()] = true;
|
||||||
|
}
|
||||||
|
if (!visited[x + (y - 1) * map->getWidth()] && (block = map->getBlock(x, y - 1)) && IS_SMART_PATH_TILE(block)) {
|
||||||
|
todo.append(QPoint(x, y - 1));
|
||||||
|
visited[x + (y - 1) * map->getWidth()] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
|
void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
|
||||||
QPointF pos = event->pos();
|
QPointF pos = event->pos();
|
||||||
int x = (int)(pos.x()) / 16;
|
int x = (int)(pos.x()) / 16;
|
||||||
|
@ -1215,20 +1367,6 @@ void MapPixmapItem::draw(bool ignoreCache) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapPixmapItem::undo() {
|
|
||||||
if (map) {
|
|
||||||
map->undo();
|
|
||||||
draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapPixmapItem::redo() {
|
|
||||||
if (map) {
|
|
||||||
map->redo();
|
|
||||||
draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapPixmapItem::updateCurHoveredTile(QPointF pos) {
|
void MapPixmapItem::updateCurHoveredTile(QPointF pos) {
|
||||||
int x = ((int)pos.x()) / 16;
|
int x = ((int)pos.x()) / 16;
|
||||||
int y = ((int)pos.y()) / 16;
|
int y = ((int)pos.y()) / 16;
|
||||||
|
|
4
editor.h
4
editor.h
|
@ -250,10 +250,10 @@ public:
|
||||||
QList<QPoint> selection;
|
QList<QPoint> selection;
|
||||||
virtual void paint(QGraphicsSceneMouseEvent*);
|
virtual void paint(QGraphicsSceneMouseEvent*);
|
||||||
virtual void floodFill(QGraphicsSceneMouseEvent*);
|
virtual void floodFill(QGraphicsSceneMouseEvent*);
|
||||||
|
void _floodFill(int x, int y);
|
||||||
|
void _floodFillSmartPath(int initialX, int initialY);
|
||||||
virtual void pick(QGraphicsSceneMouseEvent*);
|
virtual void pick(QGraphicsSceneMouseEvent*);
|
||||||
virtual void select(QGraphicsSceneMouseEvent*);
|
virtual void select(QGraphicsSceneMouseEvent*);
|
||||||
virtual void undo();
|
|
||||||
virtual void redo();
|
|
||||||
virtual void draw(bool ignoreCache = false);
|
virtual void draw(bool ignoreCache = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include <QSpacerItem>
|
#include <QSpacerItem>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) :
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
|
@ -147,7 +149,22 @@ void MainWindow::setMap(QString map_name) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editor->setMap(map_name);
|
editor->setMap(map_name);
|
||||||
|
redrawMapScene();
|
||||||
|
displayMapProperties();
|
||||||
|
|
||||||
|
setWindowTitle(map_name + " - " + editor->project->getProjectTitle() + " - pretmap");
|
||||||
|
|
||||||
|
connect(editor->map, SIGNAL(mapChanged(Map*)), this, SLOT(onMapChanged(Map *)));
|
||||||
|
connect(editor->map, SIGNAL(mapNeedsRedrawing(Map*)), this, SLOT(onMapNeedsRedrawing(Map *)));
|
||||||
|
connect(editor->map, SIGNAL(statusBarMessage(QString)), this, SLOT(setStatusBarMessage(QString)));
|
||||||
|
|
||||||
|
setRecentMap(map_name);
|
||||||
|
updateMapList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::redrawMapScene()
|
||||||
|
{
|
||||||
|
editor->displayMap();
|
||||||
on_tabWidget_currentChanged(ui->tabWidget->currentIndex());
|
on_tabWidget_currentChanged(ui->tabWidget->currentIndex());
|
||||||
|
|
||||||
ui->graphicsView_Map->setScene(editor->scene);
|
ui->graphicsView_Map->setScene(editor->scene);
|
||||||
|
@ -177,16 +194,6 @@ void MainWindow::setMap(QString map_name) {
|
||||||
ui->graphicsView_Elevation->setScene(editor->scene_elevation_metatiles);
|
ui->graphicsView_Elevation->setScene(editor->scene_elevation_metatiles);
|
||||||
//ui->graphicsView_Elevation->setSceneRect(editor->scene_elevation_metatiles->sceneRect());
|
//ui->graphicsView_Elevation->setSceneRect(editor->scene_elevation_metatiles->sceneRect());
|
||||||
ui->graphicsView_Elevation->setFixedSize(editor->elevation_metatiles_item->pixmap().width() + 2, editor->elevation_metatiles_item->pixmap().height() + 2);
|
ui->graphicsView_Elevation->setFixedSize(editor->elevation_metatiles_item->pixmap().width() + 2, editor->elevation_metatiles_item->pixmap().height() + 2);
|
||||||
|
|
||||||
displayMapProperties();
|
|
||||||
|
|
||||||
setWindowTitle(map_name + " - " + editor->project->getProjectTitle() + " - pretmap");
|
|
||||||
|
|
||||||
connect(editor->map, SIGNAL(mapChanged(Map*)), this, SLOT(onMapChanged(Map *)));
|
|
||||||
connect(editor->map, SIGNAL(statusBarMessage(QString)), this, SLOT(setStatusBarMessage(QString)));
|
|
||||||
|
|
||||||
setRecentMap(map_name);
|
|
||||||
updateMapList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setRecentMap(QString map_name) {
|
void MainWindow::setRecentMap(QString map_name) {
|
||||||
|
@ -785,6 +792,10 @@ void MainWindow::onMapChanged(Map *map) {
|
||||||
updateMapList();
|
updateMapList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onMapNeedsRedrawing(Map *map) {
|
||||||
|
redrawMapScene();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_action_Export_Map_Image_triggered()
|
void MainWindow::on_action_Export_Map_Image_triggered()
|
||||||
{
|
{
|
||||||
QString defaultFilepath = QString("%1/%2.png").arg(editor->project->root).arg(editor->map->name);
|
QString defaultFilepath = QString("%1/%2.png").arg(editor->project->root).arg(editor->map->name);
|
||||||
|
@ -838,3 +849,68 @@ void MainWindow::on_comboBox_SecondaryTileset_activated(const QString &tilesetLa
|
||||||
{
|
{
|
||||||
editor->updateSecondaryTileset(tilesetLabel);
|
editor->updateSecondaryTileset(tilesetLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_pushButton_clicked()
|
||||||
|
{
|
||||||
|
QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||||
|
dialog.setWindowTitle("Change Map Dimensions");
|
||||||
|
dialog.setWindowModality(Qt::NonModal);
|
||||||
|
|
||||||
|
QFormLayout form(&dialog);
|
||||||
|
|
||||||
|
QSpinBox *widthSpinBox = new QSpinBox();
|
||||||
|
QSpinBox *heightSpinBox = new QSpinBox();
|
||||||
|
widthSpinBox->setMinimum(1);
|
||||||
|
heightSpinBox->setMinimum(1);
|
||||||
|
// See below for explanation of maximum map dimensions
|
||||||
|
widthSpinBox->setMaximum(0x1E7);
|
||||||
|
heightSpinBox->setMaximum(0x1D1);
|
||||||
|
widthSpinBox->setValue(editor->map->getWidth());
|
||||||
|
heightSpinBox->setValue(editor->map->getHeight());
|
||||||
|
form.addRow(new QLabel("Width"), widthSpinBox);
|
||||||
|
form.addRow(new QLabel("Height"), heightSpinBox);
|
||||||
|
|
||||||
|
QLabel *errorLabel = new QLabel();
|
||||||
|
QPalette errorPalette;
|
||||||
|
errorPalette.setColor(QPalette::WindowText, Qt::red);
|
||||||
|
errorLabel->setPalette(errorPalette);
|
||||||
|
errorLabel->setVisible(false);
|
||||||
|
|
||||||
|
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
|
||||||
|
form.addRow(&buttonBox);
|
||||||
|
connect(&buttonBox, &QDialogButtonBox::accepted, [&dialog, &widthSpinBox, &heightSpinBox, &errorLabel](){
|
||||||
|
// Ensure width and height are an acceptable size.
|
||||||
|
// The maximum number of metatiles in a map is the following:
|
||||||
|
// max = (width + 15) * (height + 14)
|
||||||
|
// This limit can be found in fieldmap.c in pokeruby/pokeemerald.
|
||||||
|
int realWidth = widthSpinBox->value() + 15;
|
||||||
|
int realHeight = heightSpinBox->value() + 14;
|
||||||
|
int numMetatiles = realWidth * realHeight;
|
||||||
|
if (numMetatiles <= 0x2800) {
|
||||||
|
dialog.accept();
|
||||||
|
} else {
|
||||||
|
QString errorText = QString("Error: The specified width and height are too large.\n"
|
||||||
|
"The maximum width and height is the following: (width + 15) * (height + 14) <= 10240\n"
|
||||||
|
"The specified width and height was: (%1 + 15) * (%2 + 14) = %3")
|
||||||
|
.arg(widthSpinBox->value())
|
||||||
|
.arg(heightSpinBox->value())
|
||||||
|
.arg(numMetatiles);
|
||||||
|
errorLabel->setText(errorText);
|
||||||
|
errorLabel->setVisible(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
|
||||||
|
|
||||||
|
form.addRow(errorLabel);
|
||||||
|
|
||||||
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
editor->map->setDimensions(widthSpinBox->value(), heightSpinBox->value());
|
||||||
|
editor->map->commit();
|
||||||
|
onMapNeedsRedrawing(editor->map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_checkBox_smartPaths_stateChanged(int selected)
|
||||||
|
{
|
||||||
|
editor->map->smart_paths_enabled = selected == Qt::Checked;
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ private slots:
|
||||||
|
|
||||||
void onLoadMapRequested(QString, QString);
|
void onLoadMapRequested(QString, QString);
|
||||||
void onMapChanged(Map *map);
|
void onMapChanged(Map *map);
|
||||||
|
void onMapNeedsRedrawing(Map *map);
|
||||||
|
|
||||||
void on_action_Save_triggered();
|
void on_action_Save_triggered();
|
||||||
void on_tabWidget_2_currentChanged(int index);
|
void on_tabWidget_2_currentChanged(int index);
|
||||||
|
@ -93,6 +94,10 @@ private slots:
|
||||||
|
|
||||||
void on_comboBox_SecondaryTileset_activated(const QString &arg1);
|
void on_comboBox_SecondaryTileset_activated(const QString &arg1);
|
||||||
|
|
||||||
|
void on_pushButton_clicked();
|
||||||
|
|
||||||
|
void on_checkBox_smartPaths_stateChanged(int selected);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
QStandardItemModel *mapListModel;
|
QStandardItemModel *mapListModel;
|
||||||
|
@ -100,6 +105,7 @@ private:
|
||||||
Editor *editor = NULL;
|
Editor *editor = NULL;
|
||||||
QIcon* mapIcon;
|
QIcon* mapIcon;
|
||||||
void setMap(QString);
|
void setMap(QString);
|
||||||
|
void redrawMapScene();
|
||||||
void loadDataStructures();
|
void loadDataStructures();
|
||||||
void populateMapList();
|
void populateMapList();
|
||||||
QString getExistingDirectory(QString);
|
QString getExistingDirectory(QString);
|
||||||
|
|
|
@ -228,10 +228,20 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="checkBox_ToggleGrid">
|
<widget class="QCheckBox" name="checkBox_smartPaths">
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">margin-left: 10px</string>
|
<string notr="true">margin-left: 10px</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Smart Paths</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkBox_ToggleGrid">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show Grid</string>
|
<string>Show Grid</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -250,6 +260,13 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Change Dimensions</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -291,7 +308,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>436</width>
|
<width>436</width>
|
||||||
<height>621</height>
|
<height>620</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_8">
|
<layout class="QGridLayout" name="gridLayout_8">
|
||||||
|
|
113
map.cpp
113
map.cpp
|
@ -6,6 +6,7 @@
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
|
||||||
Map::Map(QObject *parent) : QObject(parent)
|
Map::Map(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
paint_tile_index = 1;
|
paint_tile_index = 1;
|
||||||
|
@ -276,6 +277,7 @@ QPixmap Map::render(bool ignoreCache = false) {
|
||||||
cacheBlockdata();
|
cacheBlockdata();
|
||||||
pixmap = pixmap.fromImage(image);
|
pixmap = pixmap.fromImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pixmap;
|
return pixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +389,7 @@ void Map::drawSelection(int i, int w, int selectionWidth, int selectionHeight, Q
|
||||||
int y = i / w;
|
int y = i / w;
|
||||||
painter->save();
|
painter->save();
|
||||||
|
|
||||||
QColor penColor = smart_paths_enabled ? QColor(0xff, 0x0, 0xff) : QColor(0xff, 0xff, 0xff);
|
QColor penColor = QColor(0xff, 0xff, 0xff);
|
||||||
painter->setPen(penColor);
|
painter->setPen(penColor);
|
||||||
int rectWidth = selectionWidth * 16;
|
int rectWidth = selectionWidth * 16;
|
||||||
int rectHeight = selectionHeight * 16;
|
int rectHeight = selectionHeight * 16;
|
||||||
|
@ -427,6 +429,36 @@ QPixmap Map::renderMetatiles() {
|
||||||
return QPixmap::fromImage(image);
|
return QPixmap::fromImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Map::setNewDimensionsBlockdata(int newWidth, int newHeight) {
|
||||||
|
int oldWidth = getWidth();
|
||||||
|
int oldHeight = getHeight();
|
||||||
|
|
||||||
|
Blockdata* newBlockData = new Blockdata;
|
||||||
|
|
||||||
|
for (int y = 0; y < newHeight; y++)
|
||||||
|
for (int x = 0; x < newWidth; x++) {
|
||||||
|
if (x < oldWidth && y < oldHeight) {
|
||||||
|
int index = y * oldWidth + x;
|
||||||
|
newBlockData->addBlock(layout->blockdata->blocks->value(index));
|
||||||
|
} else {
|
||||||
|
newBlockData->addBlock(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout->blockdata->copyFrom(newBlockData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata) {
|
||||||
|
if (setNewBlockdata) {
|
||||||
|
setNewDimensionsBlockdata(newWidth, newHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
layout->width = QString::number(newWidth);
|
||||||
|
layout->height = QString::number(newHeight);
|
||||||
|
|
||||||
|
emit mapChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
Block* Map::getBlock(int x, int y) {
|
Block* Map::getBlock(int x, int y) {
|
||||||
if (layout->blockdata && layout->blockdata->blocks) {
|
if (layout->blockdata && layout->blockdata->blocks) {
|
||||||
if (x >= 0 && x < getWidth())
|
if (x >= 0 && x < getWidth())
|
||||||
|
@ -445,38 +477,6 @@ void Map::_setBlock(int x, int y, Block block) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::_floodFill(int x, int y, uint tile) {
|
|
||||||
QList<QPoint> todo;
|
|
||||||
todo.append(QPoint(x, y));
|
|
||||||
while (todo.length()) {
|
|
||||||
QPoint point = todo.takeAt(0);
|
|
||||||
x = point.x();
|
|
||||||
y = point.y();
|
|
||||||
Block *block = getBlock(x, y);
|
|
||||||
if (block == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
uint old_tile = block->tile;
|
|
||||||
if (old_tile == tile) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
block->tile = tile;
|
|
||||||
_setBlock(x, y, *block);
|
|
||||||
if ((block = getBlock(x + 1, y)) && block->tile == old_tile) {
|
|
||||||
todo.append(QPoint(x + 1, y));
|
|
||||||
}
|
|
||||||
if ((block = getBlock(x - 1, y)) && block->tile == old_tile) {
|
|
||||||
todo.append(QPoint(x - 1, y));
|
|
||||||
}
|
|
||||||
if ((block = getBlock(x, y + 1)) && block->tile == old_tile) {
|
|
||||||
todo.append(QPoint(x, y + 1));
|
|
||||||
}
|
|
||||||
if ((block = getBlock(x, y - 1)) && block->tile == old_tile) {
|
|
||||||
todo.append(QPoint(x, y - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::_floodFillCollision(int x, int y, uint collision) {
|
void Map::_floodFillCollision(int x, int y, uint collision) {
|
||||||
QList<QPoint> todo;
|
QList<QPoint> todo;
|
||||||
todo.append(QPoint(x, y));
|
todo.append(QPoint(x, y));
|
||||||
|
@ -578,29 +578,48 @@ void Map::_floodFillCollisionElevation(int x, int y, uint collision, uint elevat
|
||||||
|
|
||||||
|
|
||||||
void Map::undo() {
|
void Map::undo() {
|
||||||
|
HistoryItem *commit = history.back();
|
||||||
|
if (!commit)
|
||||||
|
return;
|
||||||
|
|
||||||
if (layout->blockdata) {
|
if (layout->blockdata) {
|
||||||
Blockdata *commit = history.back();
|
layout->blockdata->copyFrom(commit->metatiles);
|
||||||
if (commit != NULL) {
|
if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight())
|
||||||
layout->blockdata->copyFrom(commit);
|
{
|
||||||
emit mapChanged(this);
|
this->setDimensions(commit->layoutWidth, commit->layoutHeight, false);
|
||||||
|
emit mapNeedsRedrawing(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit mapChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::redo() {
|
void Map::redo() {
|
||||||
|
HistoryItem *commit = history.next();
|
||||||
|
if (!commit)
|
||||||
|
return;
|
||||||
|
|
||||||
if (layout->blockdata) {
|
if (layout->blockdata) {
|
||||||
Blockdata *commit = history.next();
|
layout->blockdata->copyFrom(commit->metatiles);
|
||||||
if (commit != NULL) {
|
if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight())
|
||||||
layout->blockdata->copyFrom(commit);
|
{
|
||||||
emit mapChanged(this);
|
this->setDimensions(commit->layoutWidth, commit->layoutHeight, false);
|
||||||
|
emit mapNeedsRedrawing(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit mapChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::commit() {
|
void Map::commit() {
|
||||||
if (layout->blockdata) {
|
if (layout->blockdata) {
|
||||||
if (!layout->blockdata->equals(history.current())) {
|
HistoryItem *item = history.current();
|
||||||
Blockdata* commit = layout->blockdata->copy();
|
bool atCurrentHistory = item
|
||||||
|
&& layout->blockdata->equals(item->metatiles)
|
||||||
|
&& this->getWidth() == item->layoutWidth
|
||||||
|
&& this->getHeight() == item->layoutHeight;
|
||||||
|
if (!atCurrentHistory) {
|
||||||
|
HistoryItem *commit = new HistoryItem(layout->blockdata->copy(), this->getWidth(), this->getHeight());
|
||||||
history.push(commit);
|
history.push(commit);
|
||||||
emit mapChanged(this);
|
emit mapChanged(this);
|
||||||
}
|
}
|
||||||
|
@ -615,14 +634,6 @@ void Map::setBlock(int x, int y, Block block) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::floodFill(int x, int y, uint tile) {
|
|
||||||
Block *block = getBlock(x, y);
|
|
||||||
if (block && block->tile != tile) {
|
|
||||||
_floodFill(x, y, tile);
|
|
||||||
commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::floodFillCollision(int x, int y, uint collision) {
|
void Map::floodFillCollision(int x, int y, uint collision) {
|
||||||
Block *block = getBlock(x, y);
|
Block *block = getBlock(x, y);
|
||||||
if (block && block->collision != collision) {
|
if (block && block->collision != collision) {
|
||||||
|
|
18
map.h
18
map.h
|
@ -10,6 +10,17 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGraphicsPixmapItem>
|
#include <QGraphicsPixmapItem>
|
||||||
|
|
||||||
|
class HistoryItem {
|
||||||
|
public:
|
||||||
|
Blockdata *metatiles;
|
||||||
|
short layoutWidth;
|
||||||
|
short layoutHeight;
|
||||||
|
HistoryItem(Blockdata *metatiles_, short layoutWidth_, short layoutHeight_) {
|
||||||
|
this->metatiles = metatiles_;
|
||||||
|
this->layoutWidth = layoutWidth_;
|
||||||
|
this->layoutHeight = layoutHeight_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class History {
|
class History {
|
||||||
|
@ -173,8 +184,6 @@ public:
|
||||||
void setBlock(int x, int y, Block block);
|
void setBlock(int x, int y, Block block);
|
||||||
void _setBlock(int x, int y, Block block);
|
void _setBlock(int x, int y, Block block);
|
||||||
|
|
||||||
void floodFill(int x, int y, uint tile);
|
|
||||||
void _floodFill(int x, int y, uint tile);
|
|
||||||
void floodFillCollision(int x, int y, uint collision);
|
void floodFillCollision(int x, int y, uint collision);
|
||||||
void _floodFillCollision(int x, int y, uint collision);
|
void _floodFillCollision(int x, int y, uint collision);
|
||||||
void floodFillElevation(int x, int y, uint elevation);
|
void floodFillElevation(int x, int y, uint elevation);
|
||||||
|
@ -182,7 +191,7 @@ public:
|
||||||
void floodFillCollisionElevation(int x, int y, uint collision, uint elevation);
|
void floodFillCollisionElevation(int x, int y, uint collision, uint elevation);
|
||||||
void _floodFillCollisionElevation(int x, int y, uint collision, uint elevation);
|
void _floodFillCollisionElevation(int x, int y, uint collision, uint elevation);
|
||||||
|
|
||||||
History<Blockdata*> history;
|
History<HistoryItem*> history;
|
||||||
void undo();
|
void undo();
|
||||||
void redo();
|
void redo();
|
||||||
void commit();
|
void commit();
|
||||||
|
@ -194,6 +203,8 @@ public:
|
||||||
|
|
||||||
QList<Connection*> connections;
|
QList<Connection*> connections;
|
||||||
QPixmap renderConnection(Connection);
|
QPixmap renderConnection(Connection);
|
||||||
|
void setNewDimensionsBlockdata(int newWidth, int newHeight);
|
||||||
|
void setDimensions(int newWidth, int newHeight, bool setNewBlockData = true);
|
||||||
|
|
||||||
QPixmap renderBorder();
|
QPixmap renderBorder();
|
||||||
void cacheBorder();
|
void cacheBorder();
|
||||||
|
@ -212,6 +223,7 @@ signals:
|
||||||
void paintTileChanged(Map *map);
|
void paintTileChanged(Map *map);
|
||||||
void paintCollisionChanged(Map *map);
|
void paintCollisionChanged(Map *map);
|
||||||
void mapChanged(Map *map);
|
void mapChanged(Map *map);
|
||||||
|
void mapNeedsRedrawing(Map *map);
|
||||||
void statusBarMessage(QString);
|
void statusBarMessage(QString);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
Loading…
Reference in a new issue