Add grid settings window

This commit is contained in:
GriffinR 2024-09-27 11:31:55 -04:00
parent d369806c94
commit 16536eb940
10 changed files with 419 additions and 44 deletions

144
forms/gridsettingsdialog.ui Normal file
View file

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GridSettingsDialog</class>
<widget class="QDialog" name="GridSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>416</width>
<height>350</height>
</rect>
</property>
<property name="windowTitle">
<string>Grid Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>390</width>
<height>284</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_Offset">
<property name="title">
<string>Offset (in metatiles)</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_X">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_Y">
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBox_X"/>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_Y"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_Style">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Style</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_Dimensions">
<property name="title">
<string>Dimensions (in metatiles)</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_Width">
<property name="text">
<string>Width</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_Height">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBox_Width">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_Height">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBox_Style"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_Color">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::RestoreDefaults</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
</ui>

View file

@ -3077,10 +3077,13 @@
</property>
<addaction name="actionZoom_In"/>
<addaction name="actionZoom_Out"/>
<addaction name="separator"/>
<addaction name="actionCursor_Tile_Outline"/>
<addaction name="actionPlayer_View_Rectangle"/>
<addaction name="actionBetter_Cursors"/>
<addaction name="actionDive_Emerge_Map"/>
<addaction name="actionShow_Grid"/>
<addaction name="actionGrid_Settings"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
@ -3312,7 +3315,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Player View Rectangle</string>
<string>Show Player View Rectangle</string>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show the player's view rectangle on the map based on the cursor's position.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -3329,7 +3332,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Cursor Tile Outline</string>
<string>Show Cursor Tile Outline</string>
</property>
<property name="shortcut">
<string>C</string>
@ -3428,7 +3431,26 @@
<bool>true</bool>
</property>
<property name="text">
<string>Dive/Emerge Map</string>
<string>Show Dive/Emerge Map</string>
</property>
</action>
<action name="actionShow_Grid">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Show Grid</string>
</property>
<property name="shortcut">
<string>Ctrl+G</string>
</property>
</action>
<action name="actionGrid_Settings">
<property name="text">
<string>Grid Settings...</string>
</property>
</action>
</widget>

View file

@ -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> project = nullptr;
Map *map = nullptr;
Settings *settings;
GridSettings gridSettings;
void setProject(Project * project);
void saveProject();
void save();
@ -118,7 +120,7 @@ public:
QPointer<CollisionPixmapItem> collision_item = nullptr;
QGraphicsItemGroup *events_group = nullptr;
QList<QGraphicsPixmapItem*> borderItems;
QList<QGraphicsLineItem*> 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

View file

@ -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<NewMapPopup> newMapPrompt = nullptr;
QPointer<PreferenceEditor> preferenceEditor = nullptr;
QPointer<ProjectSettingsEditor> projectSettingsEditor = nullptr;
QPointer<GridSettingsDialog> gridSettingsDialog = nullptr;
QPointer<CustomScriptsEditor> customScriptsEditor = nullptr;
QPointer<UpdatePromoter> updatePromoter = nullptr;
QPointer<NetworkAccessManager> networkAccessManager = nullptr;

View file

@ -0,0 +1,60 @@
#ifndef GRIDSETTINGSDIALOG_H
#define GRIDSETTINGSDIALOG_H
#include <QDialog>
#include <QAbstractButton>
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

View file

@ -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 \

View file

@ -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)

View file

@ -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<qreal>(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)

View file

@ -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);

View file

@ -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;
}