diff --git a/forms/gridsettingsdialog.ui b/forms/gridsettingsdialog.ui
new file mode 100644
index 00000000..855b098b
--- /dev/null
+++ b/forms/gridsettingsdialog.ui
@@ -0,0 +1,144 @@
+
+
+ GridSettingsDialog
+
+
+
+ 0
+ 0
+ 416
+ 350
+
+
+
+ Grid Settings
+
+
+ -
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 390
+ 284
+
+
+
+
-
+
+
+ Offset (in metatiles)
+
+
+
-
+
+
+ X
+
+
+
+ -
+
+
+ Y
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Style
+
+
+
+ -
+
+
+ Dimensions (in metatiles)
+
+
+
-
+
+
+ Width
+
+
+
+ -
+
+
+ Height
+
+
+
+ -
+
+
+ 1
+
+
+
+ -
+
+
+ 1
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Color
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Orientation::Horizontal
+
+
+ QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::RestoreDefaults
+
+
+
+
+
+
+
diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui
index d4538dcb..60dc95e7 100644
--- a/forms/mainwindow.ui
+++ b/forms/mainwindow.ui
@@ -3077,10 +3077,13 @@
+
+
+
diff --git a/include/editor.h b/include/editor.h
index 7ef5ba10..9e8c7d28 100644
--- a/include/editor.h
+++ b/include/editor.h
@@ -23,6 +23,7 @@
#include "collisionpixmapitem.h"
#include "mappixmapitem.h"
#include "settings.h"
+#include "gridsettingsdialog.h"
#include "movablerect.h"
#include "cursortilerect.h"
#include "mapruler.h"
@@ -48,6 +49,7 @@ public:
QPointer project = nullptr;
Map *map = nullptr;
Settings *settings;
+ GridSettings gridSettings;
void setProject(Project * project);
void saveProject();
void save();
@@ -118,7 +120,7 @@ public:
QPointer collision_item = nullptr;
QGraphicsItemGroup *events_group = nullptr;
QList borderItems;
- QList gridLines;
+ QGraphicsItemGroup *mapGrid = nullptr;
MovableRect *playerViewRect = nullptr;
CursorTileRect *cursorMapTileRect = nullptr;
MapRuler *map_ruler = nullptr;
@@ -165,6 +167,7 @@ public slots:
void maskNonVisibleConnectionTiles();
void onBorderMetatilesChanged();
void selectedEventIndexChanged(int index, Event::Group eventGroup);
+ void toggleGrid(bool);
private:
const QImage defaultCollisionImgSheet = QImage(":/images/collisions.png");
@@ -219,7 +222,6 @@ private slots:
void onHoveredMapMovementPermissionCleared();
void onSelectedMetatilesChanged();
void onWheelZoom(int);
- void onToggleGridClicked(bool);
signals:
void objectsChanged();
@@ -231,6 +233,7 @@ signals:
void currentMetatilesSelectionChanged();
void mapRulerStatusChanged(const QString &);
void tilesetUpdated(QString);
+ void gridToggled(bool);
};
#endif // EDITOR_H
diff --git a/include/mainwindow.h b/include/mainwindow.h
index c2726efc..3f4625db 100644
--- a/include/mainwindow.h
+++ b/include/mainwindow.h
@@ -26,6 +26,7 @@
#include "shortcutseditor.h"
#include "preferenceeditor.h"
#include "projectsettingseditor.h"
+#include "gridsettingsdialog.h"
#include "customscriptseditor.h"
#include "wildmonchart.h"
#include "updatepromoter.h"
@@ -302,6 +303,8 @@ private slots:
void on_actionProject_Settings_triggered();
void on_actionCustom_Scripts_triggered();
void reloadScriptEngine();
+ void on_actionShow_Grid_triggered();
+ void on_actionGrid_Settings_triggered();
public:
Ui::MainWindow *ui;
@@ -316,6 +319,7 @@ private:
QPointer newMapPrompt = nullptr;
QPointer preferenceEditor = nullptr;
QPointer projectSettingsEditor = nullptr;
+ QPointer gridSettingsDialog = nullptr;
QPointer customScriptsEditor = nullptr;
QPointer updatePromoter = nullptr;
QPointer networkAccessManager = nullptr;
diff --git a/include/ui/gridsettingsdialog.h b/include/ui/gridsettingsdialog.h
new file mode 100644
index 00000000..806608a0
--- /dev/null
+++ b/include/ui/gridsettingsdialog.h
@@ -0,0 +1,60 @@
+#ifndef GRIDSETTINGSDIALOG_H
+#define GRIDSETTINGSDIALOG_H
+
+#include
+#include
+
+namespace Ui {
+class GridSettingsDialog;
+}
+
+struct GridSettings {
+ uint width = 16;
+ uint height = 16;
+ int offsetX = 0;
+ int offsetY = 0;
+ QString style;
+ QColor color;
+};
+
+
+class GridSettingsDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit GridSettingsDialog(GridSettings *settings = nullptr, QWidget *parent = nullptr);
+ ~GridSettingsDialog();
+
+signals:
+ void changedGridSettings();
+
+private:
+ Ui::GridSettingsDialog *ui;
+ GridSettings *settings;
+ GridSettings originalSettings;
+
+ void reset(bool force = false);
+
+private slots:
+ void dialogButtonClicked(QAbstractButton *button);
+ void on_spinBox_Width_valueChanged(int value);
+ void on_spinBox_Height_valueChanged(int value);
+ void on_spinBox_X_valueChanged(int value);
+ void on_spinBox_Y_valueChanged(int value);
+ void on_comboBox_Style_currentTextChanged(QString style);
+};
+
+inline bool operator==(const struct GridSettings &a, const struct GridSettings &b) {
+ return a.width == b.width
+ && a.height == b.height
+ && a.offsetX == b.offsetX
+ && a.offsetY == b.offsetY
+ && a.style == b.style
+ && a.color == b.color;
+}
+
+inline bool operator!=(const struct GridSettings &a, const struct GridSettings &b) {
+ return !(operator==(a, b));
+}
+
+#endif // GRIDSETTINGSDIALOG_H
diff --git a/porymap.pro b/porymap.pro
index f36f536f..ae49c4aa 100644
--- a/porymap.pro
+++ b/porymap.pro
@@ -60,6 +60,7 @@ SOURCES += src/core/block.cpp \
src/ui/collisionpixmapitem.cpp \
src/ui/connectionpixmapitem.cpp \
src/ui/currentselectedmetatilespixmapitem.cpp \
+ src/ui/gridsettingsdialog.cpp \
src/ui/newmapconnectiondialog.cpp \
src/ui/overlay.cpp \
src/ui/prefab.cpp \
@@ -157,6 +158,7 @@ HEADERS += include/core/block.h \
include/ui/collisionpixmapitem.h \
include/ui/connectionpixmapitem.h \
include/ui/currentselectedmetatilespixmapitem.h \
+ include/ui/gridsettingsdialog.h \
include/ui/newmapconnectiondialog.h \
include/ui/prefabframe.h \
include/ui/projectsettingseditor.h \
@@ -219,6 +221,7 @@ HEADERS += include/core/block.h \
FORMS += forms/mainwindow.ui \
forms/connectionslistitem.ui \
+ forms/gridsettingsdialog.ui \
forms/newmapconnectiondialog.ui \
forms/prefabcreationdialog.ui \
forms/prefabframe.ui \
diff --git a/src/editor.cpp b/src/editor.cpp
index ad228d77..dc15b059 100644
--- a/src/editor.cpp
+++ b/src/editor.cpp
@@ -47,6 +47,10 @@ Editor::Editor(Ui::MainWindow* ui)
connect(ui->stackedWidget_WildMons, &QStackedWidget::currentChanged, [this] {
emit wildMonTableOpened(getCurrentWildMonTable());
});
+
+ connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this, &Editor::openMapScripts);
+ connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this, &Editor::openProjectInTextEditor);
+ connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::toggleGrid);
}
Editor::~Editor()
@@ -1842,40 +1846,49 @@ int Editor::getBorderDrawDistance(int dimension) {
}
}
-void Editor::onToggleGridClicked(bool checked) {
+void Editor::toggleGrid(bool checked) {
+ if (porymapConfig.showGrid == checked)
+ return;
porymapConfig.showGrid = checked;
+
+ // Synchronize action and checkbox
+ const QSignalBlocker b_Action(ui->actionShow_Grid);
+ const QSignalBlocker b_Checkbox(ui->checkBox_ToggleGrid);
+ ui->actionShow_Grid->setChecked(checked);
+ ui->checkBox_ToggleGrid->setChecked(checked);
+
+ this->mapGrid->setVisible(checked);
+
if (ui->graphicsView_Map->scene())
ui->graphicsView_Map->scene()->update();
}
void Editor::clearMapGrid() {
- for (QGraphicsLineItem* item : gridLines) {
- if (item) delete item;
- }
- gridLines.clear();
+ delete this->mapGrid;
+ this->mapGrid = nullptr;
}
void Editor::displayMapGrid() {
clearMapGrid();
- ui->checkBox_ToggleGrid->disconnect();
- int pixelWidth = map->getWidth() * 16;
- int pixelHeight = map->getHeight() * 16;
- for (int i = 0; i <= map->getWidth(); i++) {
- int x = i * 16;
- QGraphicsLineItem *line = new QGraphicsLineItem(x, 0, x, pixelHeight);
- line->setVisible(ui->checkBox_ToggleGrid->isChecked());
- gridLines.append(line);
- connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);});
- }
- for (int j = 0; j <= map->getHeight(); j++) {
- int y = j * 16;
- QGraphicsLineItem *line = new QGraphicsLineItem(0, y, pixelWidth, y);
- line->setVisible(ui->checkBox_ToggleGrid->isChecked());
- gridLines.append(line);
- connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);});
- }
- connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::onToggleGridClicked);
+ // Note: The grid lines are not added to the scene. They need to be drawn on top of the overlay
+ // elements of the scripting API, so they're painted manually in MapView::drawForeground.
+ this->mapGrid = new QGraphicsItemGroup();
+
+ const uint pixelMapWidth = map->getWidth() * 16;
+ const uint pixelMapHeight = map->getHeight() * 16;
+
+ // Create vertical lines
+ int offset = this->gridSettings.offsetX % this->gridSettings.width;
+ for (uint i = offset; i <= pixelMapWidth; i += this->gridSettings.width)
+ this->mapGrid->addToGroup(new QGraphicsLineItem(i, 0, i, pixelMapHeight));
+
+ // Create horizontal lines
+ offset = this->gridSettings.offsetY % this->gridSettings.height;
+ for (uint i = offset; i <= pixelMapHeight; i += this->gridSettings.height)
+ this->mapGrid->addToGroup(new QGraphicsLineItem(0, i, pixelMapWidth, i));
+
+ this->mapGrid->setVisible(porymapConfig.showGrid);
}
void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad)
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 588ce90f..1623d055 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -149,10 +149,6 @@ void MainWindow::initExtraShortcuts() {
shortcutReset_Zoom->setObjectName("shortcutZoom_Reset");
shortcutReset_Zoom->setWhatsThis("Zoom Reset");
- auto *shortcutToggle_Grid = new Shortcut(QKeySequence("Ctrl+G"), ui->checkBox_ToggleGrid, SLOT(toggle()));
- shortcutToggle_Grid->setObjectName("shortcutToggle_Grid");
- shortcutToggle_Grid->setWhatsThis("Toggle Grid");
-
auto *shortcutDuplicate_Events = new Shortcut(QKeySequence("Ctrl+D"), this, SLOT(duplicate()));
shortcutDuplicate_Events->setObjectName("shortcutDuplicate_Events");
shortcutDuplicate_Events->setWhatsThis("Duplicate Selected Event(s)");
@@ -317,8 +313,6 @@ void MainWindow::initEditor() {
connect(this->editor, &Editor::wildMonTableEdited, [this] { this->markMapEdited(); });
connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged);
connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated);
- connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this->editor, &Editor::openMapScripts);
- connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this->editor, &Editor::openProjectInTextEditor);
this->loadUserSettings();
@@ -465,27 +459,45 @@ void MainWindow::applyMapListFilter(QString filterText)
}
void MainWindow::loadUserSettings() {
- const QSignalBlocker blocker1(ui->horizontalSlider_CollisionTransparency);
- const QSignalBlocker blocker2(ui->slider_DiveEmergeMapOpacity);
- const QSignalBlocker blocker3(ui->slider_DiveMapOpacity);
- const QSignalBlocker blocker4(ui->slider_EmergeMapOpacity);
- const QSignalBlocker blocker5(ui->horizontalSlider_MetatileZoom);
- const QSignalBlocker blocker6(ui->horizontalSlider_CollisionZoom);
-
+ // Better Cursors
ui->actionBetter_Cursors->setChecked(porymapConfig.prettyCursors);
this->editor->settings->betterCursors = porymapConfig.prettyCursors;
+
+ // Player view rectangle
ui->actionPlayer_View_Rectangle->setChecked(porymapConfig.showPlayerView);
this->editor->settings->playerViewRectEnabled = porymapConfig.showPlayerView;
+
+ // Cursor tile outline
ui->actionCursor_Tile_Outline->setChecked(porymapConfig.showCursorTile);
this->editor->settings->cursorTileRectEnabled = porymapConfig.showCursorTile;
+
+ // Border
ui->checkBox_ToggleBorder->setChecked(porymapConfig.showBorder);
+
+ // Grid
+ const QSignalBlocker b_Grid(ui->checkBox_ToggleGrid);
+ ui->actionShow_Grid->setChecked(porymapConfig.showGrid);
ui->checkBox_ToggleGrid->setChecked(porymapConfig.showGrid);
+
+ // Mirror connections
ui->checkBox_MirrorConnections->setChecked(porymapConfig.mirrorConnectingMaps);
+
+ // Collision opacity/transparency
+ const QSignalBlocker b_CollisionTransparency(ui->horizontalSlider_CollisionTransparency);
this->editor->collisionOpacity = static_cast(porymapConfig.collisionOpacity) / 100;
ui->horizontalSlider_CollisionTransparency->setValue(porymapConfig.collisionOpacity);
+
+ // Dive map opacity/transparency
+ const QSignalBlocker b_DiveEmergeOpacity(ui->slider_DiveEmergeMapOpacity);
+ const QSignalBlocker b_DiveMapOpacity(ui->slider_DiveMapOpacity);
+ const QSignalBlocker b_EmergeMapOpacity(ui->slider_EmergeMapOpacity);
ui->slider_DiveEmergeMapOpacity->setValue(porymapConfig.diveEmergeMapOpacity);
ui->slider_DiveMapOpacity->setValue(porymapConfig.diveMapOpacity);
ui->slider_EmergeMapOpacity->setValue(porymapConfig.emergeMapOpacity);
+
+ // Zoom
+ const QSignalBlocker b_MetatileZoom(ui->horizontalSlider_MetatileZoom);
+ const QSignalBlocker b_CollisionZoom(ui->horizontalSlider_CollisionZoom);
ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.metatilesZoom);
ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.collisionZoom);
@@ -1910,6 +1922,18 @@ void MainWindow::on_actionCursor_Tile_Outline_triggered()
}
}
+void MainWindow::on_actionShow_Grid_triggered() {
+ this->editor->toggleGrid(ui->actionShow_Grid->isChecked());
+}
+
+void MainWindow::on_actionGrid_Settings_triggered() {
+ if (!this->gridSettingsDialog) {
+ this->gridSettingsDialog = new GridSettingsDialog(&this->editor->gridSettings, this);
+ connect(this->gridSettingsDialog, &GridSettingsDialog::changedGridSettings, this->editor, &Editor::displayMapGrid);
+ }
+ openSubWindow(this->gridSettingsDialog);
+}
+
void MainWindow::on_actionShortcuts_triggered()
{
if (!shortcutsEditor)
diff --git a/src/ui/graphicsview.cpp b/src/ui/graphicsview.cpp
index 1c86e004..c6b78bba 100644
--- a/src/ui/graphicsview.cpp
+++ b/src/ui/graphicsview.cpp
@@ -31,9 +31,11 @@ void MapView::drawForeground(QPainter *painter, const QRectF&) {
if (!editor) return;
QStyleOptionGraphicsItem option;
- for (QGraphicsLineItem* line : editor->gridLines) {
- if (line && line->isVisible())
- line->paint(painter, &option, this);
+ if (editor->mapGrid) {
+ for (auto item : editor->mapGrid->childItems()) {
+ if (item->isVisible())
+ item->paint(painter, &option, this);
+ }
}
if (editor->playerViewRect && editor->playerViewRect->isVisible())
editor->playerViewRect->paint(painter, &option, this);
diff --git a/src/ui/gridsettingsdialog.cpp b/src/ui/gridsettingsdialog.cpp
new file mode 100644
index 00000000..14a0d8b3
--- /dev/null
+++ b/src/ui/gridsettingsdialog.cpp
@@ -0,0 +1,100 @@
+#include "ui_gridsettingsdialog.h"
+#include "gridsettingsdialog.h"
+
+// TODO: Add color picker
+// TODO: Add styles
+// TODO: Update units in UI
+// TODO: Add linking chain button to width/height
+// TODO: Add "snap to metatile" check box?
+// TODO: Save settings in config
+// TODO: Look into custom painting to improve performance
+// TODO: Add tooltips
+
+GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::GridSettingsDialog),
+ settings(settings)
+{
+ ui->setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ // TODO: Populate comboBox_Style
+
+ ui->spinBox_Width->setMaximum(INT_MAX);
+ ui->spinBox_Height->setMaximum(INT_MAX);
+ ui->spinBox_X->setMaximum(INT_MAX);
+ ui->spinBox_Y->setMaximum(INT_MAX);
+
+ // Initialize UI values
+ if (!this->settings)
+ this->settings = new GridSettings; // TODO: Don't leak this
+ this->originalSettings = *this->settings;
+ reset(true);
+
+ connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &GridSettingsDialog::dialogButtonClicked);
+
+ // TODO: Connect color picker
+ // connect(ui->, &, this, &GridSettingsDialog::changedGridSettings);
+}
+
+void GridSettingsDialog::reset(bool force) {
+ if (!force && *this->settings == this->originalSettings)
+ return;
+ *this->settings = this->originalSettings;
+
+ // Avoid sending changedGridSettings multiple times
+ const QSignalBlocker b_Width(ui->spinBox_Width);
+ const QSignalBlocker b_Height(ui->spinBox_Height);
+ const QSignalBlocker b_X(ui->spinBox_X);
+ const QSignalBlocker b_Y(ui->spinBox_Y);
+
+ ui->spinBox_Width->setValue(this->settings->width);
+ ui->spinBox_Height->setValue(this->settings->height);
+ ui->spinBox_X->setValue(this->settings->offsetX);
+ ui->spinBox_Y->setValue(this->settings->offsetY);
+ // TODO: Initialize comboBox_Style with settings->style
+ // TODO: Initialize color with settings-color
+
+ emit changedGridSettings();
+}
+
+void GridSettingsDialog::on_spinBox_Width_valueChanged(int value) {
+ this->settings->width = value;
+ emit changedGridSettings();
+}
+
+void GridSettingsDialog::on_spinBox_Height_valueChanged(int value) {
+ this->settings->height = value;
+ emit changedGridSettings();
+}
+
+void GridSettingsDialog::on_spinBox_X_valueChanged(int value) {
+ this->settings->offsetX = value;
+ emit changedGridSettings();
+}
+
+void GridSettingsDialog::on_spinBox_Y_valueChanged(int value) {
+ this->settings->offsetY = value;
+ emit changedGridSettings();
+}
+
+void GridSettingsDialog::on_comboBox_Style_currentTextChanged(QString text) {
+ this->settings->style = text;
+ emit changedGridSettings();
+}
+
+void GridSettingsDialog::dialogButtonClicked(QAbstractButton *button) {
+ auto role = ui->buttonBox->buttonRole(button);
+ if (role == QDialogButtonBox::AcceptRole) {
+ close();
+ } else if (role == QDialogButtonBox::RejectRole) {
+ reset();
+ close();
+ } else if (role == QDialogButtonBox::ResetRole) {
+ reset();
+ }
+}
+
+GridSettingsDialog::~GridSettingsDialog() {
+ delete ui;
+}