From 16536eb940458285ef9f13f6a25f624559ce3cb1 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 27 Sep 2024 11:31:55 -0400 Subject: [PATCH 1/8] Add grid settings window --- forms/gridsettingsdialog.ui | 144 ++++++++++++++++++++++++++++++++ forms/mainwindow.ui | 28 ++++++- include/editor.h | 7 +- include/mainwindow.h | 4 + include/ui/gridsettingsdialog.h | 60 +++++++++++++ porymap.pro | 3 + src/editor.cpp | 59 ++++++++----- src/mainwindow.cpp | 50 ++++++++--- src/ui/graphicsview.cpp | 8 +- src/ui/gridsettingsdialog.cpp | 100 ++++++++++++++++++++++ 10 files changed, 419 insertions(+), 44 deletions(-) create mode 100644 forms/gridsettingsdialog.ui create mode 100644 include/ui/gridsettingsdialog.h create mode 100644 src/ui/gridsettingsdialog.cpp 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 @@ + + + @@ -3312,7 +3315,7 @@ true - Player View Rectangle + Show Player View Rectangle <html><head/><body><p>Show the player's view rectangle on the map based on the cursor's position.</p></body></html> @@ -3329,7 +3332,7 @@ true - Cursor Tile Outline + Show Cursor Tile Outline C @@ -3428,7 +3431,26 @@ true - Dive/Emerge Map + Show Dive/Emerge Map + + + + + true + + + true + + + Show Grid + + + Ctrl+G + + + + + Grid Settings... 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; +} From 2cd4cb933436c32981a4641823197ae90f8dfedb Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 27 Sep 2024 22:19:52 -0400 Subject: [PATCH 2/8] Add styles to grid settings --- forms/gridsettingsdialog.ui | 78 ++++++++++++++++++++++++--------- include/editor.h | 1 - include/settings.h | 9 ++++ include/ui/gridsettingsdialog.h | 14 ++---- src/editor.cpp | 18 ++++++-- src/ui/gridsettingsdialog.cpp | 41 ++++++++++++----- 6 files changed, 113 insertions(+), 48 deletions(-) diff --git a/forms/gridsettingsdialog.ui b/forms/gridsettingsdialog.ui index 855b098b..c5aa299d 100644 --- a/forms/gridsettingsdialog.ui +++ b/forms/gridsettingsdialog.ui @@ -6,8 +6,8 @@ 0 0 - 416 - 350 + 423 + 375 @@ -24,15 +24,15 @@ 0 0 - 390 - 284 + 397 + 309 - Offset (in metatiles) + Offset (in pixels) @@ -50,14 +50,27 @@ - + - + + + + + + 0 + 0 + + + + Color + + + @@ -74,7 +87,7 @@ - Dimensions (in metatiles) + Dimensions (in pixels) @@ -92,14 +105,14 @@ - + 1 - + 1 @@ -109,21 +122,31 @@ - - - - - - - 0 - 0 - + + + false - - Color + + QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow + + + 0 + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + @@ -140,5 +163,18 @@ + + + NoScrollSpinBox + QSpinBox +
noscrollspinbox.h
+
+ + NoScrollComboBox + QComboBox +
noscrollcombobox.h
+
+
+ diff --git a/include/editor.h b/include/editor.h index 9e8c7d28..671c70d0 100644 --- a/include/editor.h +++ b/include/editor.h @@ -23,7 +23,6 @@ #include "collisionpixmapitem.h" #include "mappixmapitem.h" #include "settings.h" -#include "gridsettingsdialog.h" #include "movablerect.h" #include "cursortilerect.h" #include "mapruler.h" diff --git a/include/settings.h b/include/settings.h index d37283cd..0e0e8df5 100644 --- a/include/settings.h +++ b/include/settings.h @@ -4,6 +4,15 @@ #include +struct GridSettings { + uint width = 16; + uint height = 16; + int offsetX = 0; + int offsetY = 0; + Qt::PenStyle style = Qt::SolidLine; + QColor color = Qt::black; +}; + class Settings { public: diff --git a/include/ui/gridsettingsdialog.h b/include/ui/gridsettingsdialog.h index 806608a0..957edb43 100644 --- a/include/ui/gridsettingsdialog.h +++ b/include/ui/gridsettingsdialog.h @@ -4,20 +4,12 @@ #include #include +#include "settings.h" + 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 @@ -41,7 +33,7 @@ private slots: 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); + void on_comboBox_Style_currentIndexChanged(int index); }; inline bool operator==(const struct GridSettings &a, const struct GridSettings &b) { diff --git a/src/editor.cpp b/src/editor.cpp index dc15b059..99e18c3e 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1878,15 +1878,25 @@ void Editor::displayMapGrid() { const uint pixelMapWidth = map->getWidth() * 16; const uint pixelMapHeight = map->getHeight() * 16; + QPen pen; + pen.setStyle(this->gridSettings.style); + pen.setColor(this->gridSettings.color); + // 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)); + for (uint i = offset; i <= pixelMapWidth; i += this->gridSettings.width) { + auto line = new QGraphicsLineItem(i, 0, i, pixelMapHeight); + line->setPen(pen); + this->mapGrid->addToGroup(line); + } // 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)); + for (uint i = offset; i <= pixelMapHeight; i += this->gridSettings.height) { + auto line = new QGraphicsLineItem(0, i, pixelMapWidth, i); + line->setPen(pen); + this->mapGrid->addToGroup(line); + } this->mapGrid->setVisible(porymapConfig.showGrid); } diff --git a/src/ui/gridsettingsdialog.cpp b/src/ui/gridsettingsdialog.cpp index 14a0d8b3..10934196 100644 --- a/src/ui/gridsettingsdialog.cpp +++ b/src/ui/gridsettingsdialog.cpp @@ -2,14 +2,19 @@ #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 +const QList> penStyleMap = { + {"Solid", Qt::SolidLine}, + {"Large Dashes", Qt::DashLine}, + {"Small Dashes", Qt::DotLine}, + {"Dots", Qt::CustomDashLine}, // TODO: Implement a custom pattern for this +}; + GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) : QDialog(parent), ui(new Ui::GridSettingsDialog), @@ -18,14 +23,16 @@ GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - // TODO: Populate comboBox_Style + // Populate the styles combo box + for (const auto &pair : penStyleMap) + ui->comboBox_Style->addItem(pair.first, static_cast(pair.second)); 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 + // Initialize the settings if (!this->settings) this->settings = new GridSettings; // TODO: Don't leak this this->originalSettings = *this->settings; @@ -37,6 +44,10 @@ GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) // connect(ui->, &, this, &GridSettingsDialog::changedGridSettings); } +GridSettingsDialog::~GridSettingsDialog() { + delete ui; +} + void GridSettingsDialog::reset(bool force) { if (!force && *this->settings == this->originalSettings) return; @@ -47,12 +58,21 @@ void GridSettingsDialog::reset(bool force) { const QSignalBlocker b_Height(ui->spinBox_Height); const QSignalBlocker b_X(ui->spinBox_X); const QSignalBlocker b_Y(ui->spinBox_Y); + const QSignalBlocker b_Style(ui->comboBox_Style); 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: Debug + //ui->comboBox_Style->setCurrentIndex(ui->comboBox_Style->findData(static_cast(this->settings->style))); + for (const auto &pair : penStyleMap) { + if (pair.second == this->settings->style) { + ui->comboBox_Style->setCurrentText(pair.first); + break; + } + } // TODO: Initialize color with settings-color emit changedGridSettings(); @@ -78,8 +98,11 @@ void GridSettingsDialog::on_spinBox_Y_valueChanged(int value) { emit changedGridSettings(); } -void GridSettingsDialog::on_comboBox_Style_currentTextChanged(QString text) { - this->settings->style = text; +void GridSettingsDialog::on_comboBox_Style_currentIndexChanged(int index) { + if (index < 0 || index >= penStyleMap.length()) + return; + + this->settings->style = penStyleMap.at(index).second; emit changedGridSettings(); } @@ -94,7 +117,3 @@ void GridSettingsDialog::dialogButtonClicked(QAbstractButton *button) { reset(); } } - -GridSettingsDialog::~GridSettingsDialog() { - delete ui; -} From 274d95eef5dd9f3a3f02ae93786643359d256537 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sat, 28 Sep 2024 03:50:51 -0400 Subject: [PATCH 3/8] Add color input to grid settings --- forms/colorinputwidget.ui | 313 ++++++++++++++++++++++++++++++++ forms/gridsettingsdialog.ui | 117 ++++++------ include/ui/colorinputwidget.h | 45 +++++ include/ui/gridsettingsdialog.h | 1 + porymap.pro | 3 + src/ui/colorinputwidget.cpp | 216 ++++++++++++++++++++++ src/ui/gridsettingsdialog.cpp | 15 +- 7 files changed, 652 insertions(+), 58 deletions(-) create mode 100644 forms/colorinputwidget.ui create mode 100644 include/ui/colorinputwidget.h create mode 100644 src/ui/colorinputwidget.cpp diff --git a/forms/colorinputwidget.ui b/forms/colorinputwidget.ui new file mode 100644 index 00000000..eebd7955 --- /dev/null +++ b/forms/colorinputwidget.ui @@ -0,0 +1,313 @@ + + + ColorInputWidget + + + + 0 + 0 + 221 + 212 + + + + Color + + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Red + + + + + + + Green + + + + + + + Blue + + + + + + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 31 + + + 4 + + + Qt::Orientation::Horizontal + + + + + + + 31 + + + 4 + + + Qt::Orientation::Horizontal + + + + + + + 31 + + + 4 + + + Qt::Orientation::Horizontal + + + + + + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 255 + + + 8 + + + + + + + 255 + + + 8 + + + + + + + 255 + + + 8 + + + + + + + + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::Shadow::Raised + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + # + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + + + + + + + ... + + + + :/icons/pipette.ico:/icons/pipette.ico + + + + + + + + + + + + + diff --git a/forms/gridsettingsdialog.ui b/forms/gridsettingsdialog.ui index c5aa299d..73411742 100644 --- a/forms/gridsettingsdialog.ui +++ b/forms/gridsettingsdialog.ui @@ -6,8 +6,8 @@ 0 0 - 423 - 375 + 331 + 467 @@ -24,39 +24,23 @@ 0 0 - 397 - 309 + 305 + 401 - - - - Offset (in pixels) + + + + Qt::Orientation::Vertical - - - - - X - - - - - - - Y - - - - - - - - - - - + + + 20 + 40 + + + @@ -71,6 +55,19 @@ + + + + false + + + QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow + + + 0 + + + @@ -121,31 +118,41 @@ - - - - false - - - QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow - - - 0 + + + + Offset (in pixels) + + + + + X + + + + + + + Y + + + + + + + + + + - - - - Qt::Orientation::Vertical + + + + - - - 20 - 40 - - - + @@ -174,6 +181,12 @@ QComboBox
noscrollcombobox.h
+ + ColorInputWidget + QGroupBox +
colorinputwidget.h
+ 1 +
diff --git a/include/ui/colorinputwidget.h b/include/ui/colorinputwidget.h new file mode 100644 index 00000000..5b414776 --- /dev/null +++ b/include/ui/colorinputwidget.h @@ -0,0 +1,45 @@ +#ifndef COLORINPUTWIDGET_H +#define COLORINPUTWIDGET_H + +#include +#include + +namespace Ui { +class ColorInputWidget; +} + + +class ColorInputWidget : public QGroupBox { + Q_OBJECT +public: + explicit ColorInputWidget(QWidget *parent = nullptr); + explicit ColorInputWidget(const QString &title, QWidget *parent = nullptr); + ~ColorInputWidget(); + + void setColor(QRgb color); + QRgb color() const { return m_color; } + + bool setBitDepth(int bits); + int bitDepth() const { return m_bitDepth; } + +signals: + void colorChanged(QRgb color); + void bitDepthChanged(int bits); + +private: + Ui::ColorInputWidget *ui; + + QRgb m_color = 0; + int m_bitDepth = 0; + + void init(); + void updateColorUi(); + void pickColor(); + void blockEditSignals(bool block); + + void setRgbFromSliders(); + void setRgbFromSpinners(); + void setRgbFromHexString(const QString &); +}; + +#endif // COLORINPUTWIDGET_H diff --git a/include/ui/gridsettingsdialog.h b/include/ui/gridsettingsdialog.h index 957edb43..9c64f29d 100644 --- a/include/ui/gridsettingsdialog.h +++ b/include/ui/gridsettingsdialog.h @@ -34,6 +34,7 @@ private slots: void on_spinBox_X_valueChanged(int value); void on_spinBox_Y_valueChanged(int value); void on_comboBox_Style_currentIndexChanged(int index); + void onColorChanged(QRgb color); }; inline bool operator==(const struct GridSettings &a, const struct GridSettings &b) { diff --git a/porymap.pro b/porymap.pro index ae49c4aa..182ea11a 100644 --- a/porymap.pro +++ b/porymap.pro @@ -51,6 +51,7 @@ SOURCES += src/core/block.cpp \ src/scriptapi/apiutility.cpp \ src/scriptapi/scripting.cpp \ src/ui/aboutporymap.cpp \ + src/ui/colorinputwidget.cpp \ src/ui/connectionslistitem.cpp \ src/ui/customscriptseditor.cpp \ src/ui/customscriptslistitem.cpp \ @@ -175,6 +176,7 @@ HEADERS += include/core/block.h \ include/ui/prefabcreationdialog.h \ include/ui/regionmappixmapitem.h \ include/ui/citymappixmapitem.h \ + include/ui/colorinputwidget.h \ include/ui/mapsceneeventfilter.h \ include/ui/metatilelayersitem.h \ include/ui/metatileselector.h \ @@ -220,6 +222,7 @@ HEADERS += include/core/block.h \ include/ui/wildmonchart.h FORMS += forms/mainwindow.ui \ + forms/colorinputwidget.ui \ forms/connectionslistitem.ui \ forms/gridsettingsdialog.ui \ forms/newmapconnectiondialog.ui \ diff --git a/src/ui/colorinputwidget.cpp b/src/ui/colorinputwidget.cpp new file mode 100644 index 00000000..200567af --- /dev/null +++ b/src/ui/colorinputwidget.cpp @@ -0,0 +1,216 @@ +#include "colorinputwidget.h" +#include "ui_colorinputwidget.h" +#include "colorpicker.h" + +#include + +// TODO: Refactor palette editor to make use of this class + +class HexCodeValidator : public QValidator { + virtual QValidator::State validate(QString &input, int &) const override { + input = input.toUpper(); + return QValidator::Acceptable; + } +}; + +static inline int rgb5(int rgb) { return round(static_cast(rgb * 31) / 255.0); } +static inline int rgb8(int rgb) { return round(rgb * 255. / 31.); } +static inline int gbaRed(int rgb) { return rgb & 0x1f; } +static inline int gbaGreen(int rgb) { return (rgb >> 5) & 0x1f; } +static inline int gbaBlue(int rgb) { return (rgb >> 10) & 0x1f; } + +ColorInputWidget::ColorInputWidget(QWidget *parent) : + QGroupBox(parent), + ui(new Ui::ColorInputWidget) +{ + init(); +} + +ColorInputWidget::ColorInputWidget(const QString &title, QWidget *parent) : + QGroupBox(title, parent), + ui(new Ui::ColorInputWidget) +{ + init(); +} + +void ColorInputWidget::init() { + ui->setupUi(this); + + connect(ui->slider_Red, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); + connect(ui->slider_Green, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); + connect(ui->slider_Blue, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); + + connect(ui->spinBox_Red, QOverload::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners); + connect(ui->spinBox_Green, QOverload::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners); + connect(ui->spinBox_Blue, QOverload::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners); + + static const HexCodeValidator hexValidator; + ui->lineEdit_Hex->setValidator(&hexValidator); + connect(ui->lineEdit_Hex, &QLineEdit::textEdited, this, &ColorInputWidget::setRgbFromHexString); + + connect(ui->button_Eyedrop, &QToolButton::clicked, this, &ColorInputWidget::pickColor); + + setBitDepth(24); +} + +ColorInputWidget::~ColorInputWidget() { + delete ui; +} + +void ColorInputWidget::updateColorUi() { + blockEditSignals(true); + + int red = qRed(m_color); + int green = qGreen(m_color); + int blue = qBlue(m_color); + + if (m_bitDepth == 15) { + // Sliders + ui->slider_Red->setValue(rgb5(red)); + ui->slider_Green->setValue(rgb5(green)); + ui->slider_Blue->setValue(rgb5(blue)); + + // Hex + int hex15 = (rgb5(blue) << 10) | (rgb5(green) << 5) | rgb5(red); + ui->lineEdit_Hex->setText(QString("%1").arg(hex15, 4, 16, QLatin1Char('0')).toUpper()); + + // Spinners + ui->spinBox_Red->setValue(rgb5(red)); + ui->spinBox_Green->setValue(rgb5(green)); + ui->spinBox_Blue->setValue(rgb5(blue)); + } else { + // Sliders + ui->slider_Red->setValue(red); + ui->slider_Green->setValue(green); + ui->slider_Blue->setValue(blue); + + // Hex + QColor color(red, green, blue); + ui->lineEdit_Hex->setText(color.name().remove(0, 1).toUpper()); + + // Spinners + ui->spinBox_Red->setValue(red); + ui->spinBox_Green->setValue(green); + ui->spinBox_Blue->setValue(blue); + } + + ui->frame_ColorDisplay->setStyleSheet(QString("background-color: rgb(%1, %2, %3);").arg(red).arg(green).arg(blue)); + + blockEditSignals(false); +} + +void ColorInputWidget::blockEditSignals(bool block) { + ui->slider_Red->blockSignals(block); + ui->slider_Green->blockSignals(block); + ui->slider_Blue->blockSignals(block); + + ui->spinBox_Red->blockSignals(block); + ui->spinBox_Green->blockSignals(block); + ui->spinBox_Blue->blockSignals(block); + + ui->lineEdit_Hex->blockSignals(block); +} + +bool ColorInputWidget::setBitDepth(int bits) { + if (m_bitDepth == bits) + return true; + + int singleStep, pageStep, maximum; + QString hexInputMask; + if (bits == 15) { + singleStep = 1; + pageStep = 4; + maximum = 31; + hexInputMask = "HHHH"; + } else if (bits == 24) { + singleStep = 8; + pageStep = 24; + maximum = 255; + hexInputMask = "HHHHHH"; + } else { + // Unsupported bit depth + return false; + } + m_bitDepth = bits; + + blockEditSignals(true); + ui->slider_Red->setSingleStep(singleStep); + ui->slider_Green->setSingleStep(singleStep); + ui->slider_Blue->setSingleStep(singleStep); + ui->slider_Red->setPageStep(pageStep); + ui->slider_Green->setPageStep(pageStep); + ui->slider_Blue->setPageStep(pageStep); + ui->slider_Red->setMaximum(maximum); + ui->slider_Green->setMaximum(maximum); + ui->slider_Blue->setMaximum(maximum); + + ui->spinBox_Red->setSingleStep(singleStep); + ui->spinBox_Green->setSingleStep(singleStep); + ui->spinBox_Blue->setSingleStep(singleStep); + ui->spinBox_Red->setMaximum(maximum); + ui->spinBox_Green->setMaximum(maximum); + ui->spinBox_Blue->setMaximum(maximum); + + ui->lineEdit_Hex->setInputMask(hexInputMask); + ui->lineEdit_Hex->setMaxLength(hexInputMask.length()); + + updateColorUi(); + blockEditSignals(false); + emit bitDepthChanged(m_bitDepth); + return true; +} + +void ColorInputWidget::setColor(QRgb rgb) { + if (m_color == rgb) + return; + m_color = rgb; + updateColorUi(); + emit colorChanged(m_color); +} + +void ColorInputWidget::setRgbFromSliders() { + if (m_bitDepth == 15) { + setColor(qRgb(rgb8(ui->slider_Red->value()), + rgb8(ui->slider_Green->value()), + rgb8(ui->slider_Blue->value()))); + } else { + setColor(qRgb(ui->slider_Red->value(), + ui->slider_Green->value(), + ui->slider_Blue->value())); + } +} + +void ColorInputWidget::setRgbFromSpinners() { + if (m_bitDepth == 15) { + setColor(qRgb(rgb8(ui->spinBox_Red->value()), rgb8(ui->spinBox_Green->value()), rgb8(ui->spinBox_Blue->value()))); + } else { + setColor(qRgb(ui->spinBox_Red->value(), ui->spinBox_Green->value(), ui->spinBox_Blue->value())); + } +} + +void ColorInputWidget::setRgbFromHexString(const QString &text) { + if ((m_bitDepth == 24 && text.length() != 6) + || (m_bitDepth == 15 && text.length() != 4)) + return; + + bool ok = false; + int rgb = text.toInt(&ok, 16); + if (!ok) rgb = 0xFFFFFFFF; + + if (m_bitDepth == 15) { + int rc = gbaRed(rgb); + int gc = gbaGreen(rgb); + int bc = gbaBlue(rgb); + setColor(qRgb(rgb8(rc), rgb8(gc), rgb8(bc))); + } else { + setColor(qRgb(qRed(rgb), qGreen(rgb), qBlue(rgb))); + } +} + +void ColorInputWidget::pickColor() { + ColorPicker picker(this); + if (picker.exec() == QDialog::Accepted) { + QColor c = picker.getColor(); + setColor(c.rgb()); + } +} diff --git a/src/ui/gridsettingsdialog.cpp b/src/ui/gridsettingsdialog.cpp index 10934196..bfc814bc 100644 --- a/src/ui/gridsettingsdialog.cpp +++ b/src/ui/gridsettingsdialog.cpp @@ -1,7 +1,6 @@ #include "ui_gridsettingsdialog.h" #include "gridsettingsdialog.h" -// TODO: Add color picker // TODO: Add linking chain button to width/height // TODO: Add "snap to metatile" check box? // TODO: Save settings in config @@ -39,9 +38,7 @@ GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) reset(true); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &GridSettingsDialog::dialogButtonClicked); - - // TODO: Connect color picker - // connect(ui->, &, this, &GridSettingsDialog::changedGridSettings); + connect(ui->colorInput, &ColorInputWidget::colorChanged, this, &GridSettingsDialog::onColorChanged); } GridSettingsDialog::~GridSettingsDialog() { @@ -59,11 +56,13 @@ void GridSettingsDialog::reset(bool force) { const QSignalBlocker b_X(ui->spinBox_X); const QSignalBlocker b_Y(ui->spinBox_Y); const QSignalBlocker b_Style(ui->comboBox_Style); + const QSignalBlocker b_Color(ui->colorInput); 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); + ui->colorInput->setColor(this->settings->color.rgb()); // TODO: Debug //ui->comboBox_Style->setCurrentIndex(ui->comboBox_Style->findData(static_cast(this->settings->style))); @@ -73,7 +72,6 @@ void GridSettingsDialog::reset(bool force) { break; } } - // TODO: Initialize color with settings-color emit changedGridSettings(); } @@ -106,6 +104,11 @@ void GridSettingsDialog::on_comboBox_Style_currentIndexChanged(int index) { emit changedGridSettings(); } +void GridSettingsDialog::onColorChanged(QRgb color) { + this->settings->color = QColor::fromRgb(color); + emit changedGridSettings(); +} + void GridSettingsDialog::dialogButtonClicked(QAbstractButton *button) { auto role = ui->buttonBox->buttonRole(button); if (role == QDialogButtonBox::AcceptRole) { @@ -114,6 +117,6 @@ void GridSettingsDialog::dialogButtonClicked(QAbstractButton *button) { reset(); close(); } else if (role == QDialogButtonBox::ResetRole) { - reset(); + reset(); // TODO: We should restore to original defaults, not to the values when the window was opened. } } From a277e193346487d849fdd4623659ba72e211e5d5 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sat, 28 Sep 2024 19:28:07 -0400 Subject: [PATCH 4/8] Add linking buttons to grid settings --- forms/gridsettingsdialog.ui | 114 ++++++++++++++++++++++++-------- include/ui/gridsettingsdialog.h | 6 ++ resources/icons/link.ico | Bin 0 -> 1282 bytes resources/icons/link_broken.ico | Bin 0 -> 2069 bytes resources/images.qrc | 2 + src/ui/gridsettingsdialog.cpp | 68 ++++++++++++++----- 6 files changed, 147 insertions(+), 43 deletions(-) create mode 100755 resources/icons/link.ico create mode 100755 resources/icons/link_broken.ico diff --git a/forms/gridsettingsdialog.ui b/forms/gridsettingsdialog.ui index 73411742..8673a9b3 100644 --- a/forms/gridsettingsdialog.ui +++ b/forms/gridsettingsdialog.ui @@ -86,30 +86,60 @@ Dimensions (in pixels) - - - + + + - Width + ... + + + + :/icons/link_broken.ico + :/icons/link.ico:/icons/link_broken.ico + + + true + + + true + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true - - - - Height - - - - - + + 1 - + + + Height + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + Width + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + 1 @@ -123,26 +153,56 @@ Offset (in pixels) - - - - - X - - - - + + Y + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + X + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + - - + + + + ... + + + + :/icons/link_broken.ico + :/icons/link.ico:/icons/link_broken.ico + + + true + + + true + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true + + @@ -188,6 +248,8 @@ 1 - + + + diff --git a/include/ui/gridsettingsdialog.h b/include/ui/gridsettingsdialog.h index 9c64f29d..cd04a048 100644 --- a/include/ui/gridsettingsdialog.h +++ b/include/ui/gridsettingsdialog.h @@ -24,8 +24,14 @@ private: Ui::GridSettingsDialog *ui; GridSettings *settings; GridSettings originalSettings; + bool dimensionsLinked = true; + bool offsetsLinked = true; void reset(bool force = false); + void setWidth(int value); + void setHeight(int value); + void setOffsetX(int value); + void setOffsetY(int value); private slots: void dialogButtonClicked(QAbstractButton *button); diff --git a/resources/icons/link.ico b/resources/icons/link.ico new file mode 100755 index 0000000000000000000000000000000000000000..b0c35b59a32a35922e235ce13cfaea86fb337aa3 GIT binary patch literal 1282 zcmV+d1^xPoP)20c}Tt0!?8C z=xDn*fBM6aEEdGD1Q?8M&Y9_)i5akqKa4SPh|I~&Y>66U;$^0z!)-+4-0+8)a_I%U zEl{ADC53V5Mi*U6ZE3c)r#Ij4^t1vi!Z=-alJ}&^cTS)8d%x#>pXcx*kqA7@D}~&6 zJYKT@m)F|XS&}XiT?~c8d7)qsBB3zQ0s3OgyG?s>Js5wGR3OO-@Y_329w;g(R99>( z2cOpuF1H)(4hKw6O~ahc25s*je-xjiA4CHD*7gq$$cl>8H8s^>7#;>{#tH%24?=+u zBvL8ZY&U?Sti2z9cxpGPL`pJuz8GAqGl1D_2Ghj&r{+JenN(%vZ}@266FE6KnAB`7 zJ}(Q+YtOLuHVAAbFlu>?>CD>Xxb$L#{SQhBQJ&=DPBID+pZ;MLWYpw%0&4X0q{ z`gF%1zyGGk^}ESPAT<;U!MyVyu>XA< z_x1fmj>aCF1Dr`1!U?C>YN4>G0Cv{Z!slO}2A|IdTedvevmCrX3Vw^-eIywi0GG?@ zk|^X^yXtm;`b-yGy*dJ~A3X|$aQ%bYMBsNY!pRuLsc#>9XLj>ujF8&{$uO ztrlk3&RI$mtJ;5(+H>LDIb6T_)#)#`&CT6x%Fo{j8Ch9iw>wA$=96Md?@={$GOU^C zW_vie|CLv_%jJp=GG6-!w5V#-5>?}x0HbPNpP$$zKnwNJBJh}`eionYQh%=AnbHH2hq1bORO`x*Qe6b9y2~yrUDVF8gVkKsoJ_d9XpCe_*>rGa>6K)xosNU38rrDURE=u_q!PIp#RnS>pWGl6ZY7)`u~t>%ngG*^7}*$k7@6$xtXb8P skwA z>43aYs3lk-Ckl>Y1yT7@F`jF{;8kK7!bYLId{iR=9Eoy4aIus+^^mx_uAh#{B@sKm(<1yx1Ee$b^Nd&4yW3w(gU zNi^&qrlMG(fS*(j0UmfFj!z_k0LdK>x)Ukx6j#8F2oedP8-eJF1Bp}*Pbv`vK0a6^ znp_Z14QB*=jD?(N*hCnXQ3(X4Qi)f7jhD(32q1+*ArRdNZf-aPfm5VQV6F-$QLI@| zU_c7KTquKuQVC#C7Kp}e-HNsE$@n|FbZNB5}5(Xg=vr=KrR&nA5x|Y7x&`1sNP4e zU~w9D}z0mZ${eipeXA=3@6ncibZ??F5^H~Y+)(~^x>5v3J35UIcAK&7rn-lnCtei=1u}x0%FhkmF6tX4#Xf(r>&_jp zKIL8X$isq3`ABudi2GIFU7O9w&vE34m025I2cMR7=d@8Y(={QMhjs;dcJa&JDjq4f zb)7q9RF-mFB*`+;wgSd;T(jFeD$s)-+`|2i}D)pB9$)H)~Ry}1?m1pzV z(Ce9W%HYKK;Om(a5Awb^{&}Qb|6c8E-HQ9$-l_9XHS61tO}~F+6O7)QqPhPvGe=Zh z5%6Q6fWUV>ody61~LTN-!mqYAou==*m3-u$<^Bx zI6=#hN6TG)18X`b4QDcyHBBDT@~twna+YKLXB91Zbw2s@Nxk=6q3aIIR^`qF{PqxF+EF_-2_I{nRbn%NF!TdGTA#W$wOQDG z{c7pMUw#a_Lae^a?7%sWrnG3R;~l=p-Z=KMjqa0H@5PFDQZ<$y+y}Xl-q*&4u3Mq^ zxIn{X9rJRI_^O2O6`4~0o$jXpJ4Z@Uf`FX7gTGOwL9ZN7VdUQwjLxw8pCFS;0tckVw=w zsj7M^_Z3gv$*pAO3J{GO3 z5A6NfvSp2hKzOTp2?U3S_vmg%3^N`c2#C!;ebn?O&qy88FY#h=dKc3;%fg1}w6q@Gy)e$-TMtV&5(h_;X}ZQ@4m~8~0{g*) z>wL`qZ$H~H*grE9644k5Fz=NyboP+|MKTypi7pBsMEO#fg;6+KS-U)efXDgXcg literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index 73ed0620..26f51f42 100644 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -17,6 +17,8 @@ icons/folder_map.ico icons/folder.ico icons/help.ico + icons/link_broken.ico + icons/link.ico icons/map_edited.ico icons/map_opened.ico icons/map.ico diff --git a/src/ui/gridsettingsdialog.cpp b/src/ui/gridsettingsdialog.cpp index bfc814bc..3ce0d4df 100644 --- a/src/ui/gridsettingsdialog.cpp +++ b/src/ui/gridsettingsdialog.cpp @@ -1,8 +1,6 @@ #include "ui_gridsettingsdialog.h" #include "gridsettingsdialog.h" -// 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 @@ -31,6 +29,9 @@ GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) ui->spinBox_X->setMaximum(INT_MAX); ui->spinBox_Y->setMaximum(INT_MAX); + ui->button_LinkDimensions->setChecked(this->dimensionsLinked); + ui->button_LinkOffsets->setChecked(this->offsetsLinked); + // Initialize the settings if (!this->settings) this->settings = new GridSettings; // TODO: Don't leak this @@ -38,6 +39,8 @@ GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) reset(true); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &GridSettingsDialog::dialogButtonClicked); + connect(ui->button_LinkDimensions, &QAbstractButton::toggled, [this](bool on) { this->dimensionsLinked = on; }); + connect(ui->button_LinkOffsets, &QAbstractButton::toggled, [this](bool on) { this->offsetsLinked = on; }); connect(ui->colorInput, &ColorInputWidget::colorChanged, this, &GridSettingsDialog::onColorChanged); } @@ -50,20 +53,15 @@ void GridSettingsDialog::reset(bool force) { 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); - const QSignalBlocker b_Style(ui->comboBox_Style); - const QSignalBlocker b_Color(ui->colorInput); + setWidth(this->settings->width); + setHeight(this->settings->height); + setOffsetX(this->settings->offsetX); + setOffsetY(this->settings->offsetY); - 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); + const QSignalBlocker b_Color(ui->colorInput); ui->colorInput->setColor(this->settings->color.rgb()); + const QSignalBlocker b_Style(ui->comboBox_Style); // TODO: Debug //ui->comboBox_Style->setCurrentIndex(ui->comboBox_Style->findData(static_cast(this->settings->style))); for (const auto &pair : penStyleMap) { @@ -76,23 +74,59 @@ void GridSettingsDialog::reset(bool force) { emit changedGridSettings(); } -void GridSettingsDialog::on_spinBox_Width_valueChanged(int value) { +void GridSettingsDialog::setWidth(int value) { + const QSignalBlocker b(ui->spinBox_Width); + ui->spinBox_Width->setValue(value); this->settings->width = value; +} + +void GridSettingsDialog::setHeight(int value) { + const QSignalBlocker b(ui->spinBox_Height); + ui->spinBox_Height->setValue(value); + this->settings->height = value; +} + +void GridSettingsDialog::setOffsetX(int value) { + const QSignalBlocker b(ui->spinBox_X); + ui->spinBox_X->setValue(value); + this->settings->offsetX = value; +} + +void GridSettingsDialog::setOffsetY(int value) { + const QSignalBlocker b(ui->spinBox_Y); + ui->spinBox_Y->setValue(value); + this->settings->offsetY = value; +} + +void GridSettingsDialog::on_spinBox_Width_valueChanged(int value) { + setWidth(value); + if (this->dimensionsLinked) + setHeight(value); + emit changedGridSettings(); } void GridSettingsDialog::on_spinBox_Height_valueChanged(int value) { - this->settings->height = value; + setHeight(value); + if (this->dimensionsLinked) + setWidth(value); + emit changedGridSettings(); } void GridSettingsDialog::on_spinBox_X_valueChanged(int value) { - this->settings->offsetX = value; + setOffsetX(value); + if (this->offsetsLinked) + setOffsetY(value); + emit changedGridSettings(); } void GridSettingsDialog::on_spinBox_Y_valueChanged(int value) { - this->settings->offsetY = value; + setOffsetY(value); + if (this->offsetsLinked) + setOffsetX(value); + emit changedGridSettings(); } From 44642c347f4ca894ce3db015407b7ab43cdad8eb Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 29 Sep 2024 16:10:48 -0400 Subject: [PATCH 5/8] Add custom dash patterns to grid settings --- forms/gridsettingsdialog.ui | 28 +++- include/editor.h | 2 + include/mainwindow.h | 2 +- include/settings.h | 9 -- include/ui/gridsettings.h | 99 ++++++++++++++ include/ui/gridsettingsdialog.h | 59 -------- porymap.pro | 4 +- src/editor.cpp | 28 ++-- src/mainwindow.cpp | 2 +- src/ui/graphicsview.cpp | 20 ++- src/ui/gridsettings.cpp | 230 ++++++++++++++++++++++++++++++++ src/ui/gridsettingsdialog.cpp | 156 ---------------------- 12 files changed, 394 insertions(+), 245 deletions(-) create mode 100644 include/ui/gridsettings.h delete mode 100644 include/ui/gridsettingsdialog.h create mode 100644 src/ui/gridsettings.cpp delete mode 100644 src/ui/gridsettingsdialog.cpp diff --git a/forms/gridsettingsdialog.ui b/forms/gridsettingsdialog.ui index 8673a9b3..75d31de1 100644 --- a/forms/gridsettingsdialog.ui +++ b/forms/gridsettingsdialog.ui @@ -114,7 +114,10 @@ - 1 + 2 + + + 999 @@ -141,7 +144,10 @@ - 1 + 2 + + + 999 @@ -175,10 +181,24 @@ - + + + 0 + + + 999 + + - + + + 0 + + + 999 + + diff --git a/include/editor.h b/include/editor.h index 671c70d0..88eec307 100644 --- a/include/editor.h +++ b/include/editor.h @@ -23,6 +23,7 @@ #include "collisionpixmapitem.h" #include "mappixmapitem.h" #include "settings.h" +#include "gridsettings.h" #include "movablerect.h" #include "cursortilerect.h" #include "mapruler.h" @@ -68,6 +69,7 @@ public: void displayMapConnections(); void displayMapBorder(); void displayMapGrid(); + void updateMapGrid(); void displayWildMonTables(); void updateMapBorder(); diff --git a/include/mainwindow.h b/include/mainwindow.h index 3f4625db..f2a31741 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -26,7 +26,7 @@ #include "shortcutseditor.h" #include "preferenceeditor.h" #include "projectsettingseditor.h" -#include "gridsettingsdialog.h" +#include "gridsettings.h" #include "customscriptseditor.h" #include "wildmonchart.h" #include "updatepromoter.h" diff --git a/include/settings.h b/include/settings.h index 0e0e8df5..d37283cd 100644 --- a/include/settings.h +++ b/include/settings.h @@ -4,15 +4,6 @@ #include -struct GridSettings { - uint width = 16; - uint height = 16; - int offsetX = 0; - int offsetY = 0; - Qt::PenStyle style = Qt::SolidLine; - QColor color = Qt::black; -}; - class Settings { public: diff --git a/include/ui/gridsettings.h b/include/ui/gridsettings.h new file mode 100644 index 00000000..0a966e4c --- /dev/null +++ b/include/ui/gridsettings.h @@ -0,0 +1,99 @@ +#ifndef GRIDSETTINGS_H +#define GRIDSETTINGS_H + +#include +#include + +class GridSettings { +public: + explicit GridSettings() {}; + ~GridSettings() {}; + + enum Style { + Solid, + LargeDashes, + SmallDashes, + Crosshairs, + Dots, + }; + + uint width = 16; + uint height = 16; + int offsetX = 0; + int offsetY = 0; + Style style = Style::Solid; + QColor color = Qt::black; + QList getHorizontalDashPattern() const { return this->getDashPattern(this->width); } + QList getVerticalDashPattern() const { return this->getDashPattern(this->height); } + + static QString getStyleName(Style style); + static GridSettings::Style getStyleFromName(const QString &name); +private: + static const QMap styleToName; + + QList getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const; + QList getDashPattern(uint length) const; +}; + +inline bool operator==(const GridSettings &a, const 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 GridSettings &a, const GridSettings &b) { + return !(operator==(a, b)); +} + + + +namespace Ui { +class GridSettingsDialog; +} + +class GridSettingsDialog : public QDialog { + Q_OBJECT +public: + explicit GridSettingsDialog(QWidget *parent = nullptr); + explicit GridSettingsDialog(GridSettings *settings, QWidget *parent = nullptr); + ~GridSettingsDialog(); + + void setSettings(const GridSettings &settings); + GridSettings settings() const { return *m_settings; } + + void setDefaultSettings(const GridSettings &settings); + GridSettings defaultSettings() const { return m_defaultSettings; } + +signals: + void changedGridSettings(); + +private: + Ui::GridSettingsDialog *ui; + GridSettings *const m_settings; + const GridSettings m_originalSettings; + GridSettings m_defaultSettings; + bool m_dimensionsLinked = true; + bool m_offsetsLinked = true; + bool m_ownedSettings = false; + + void init(); + void updateInput(); + void setWidth(int value); + void setHeight(int value); + void setOffsetX(int value); + void setOffsetY(int value); + +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(const QString &text); + void onColorChanged(QRgb color); +}; + +#endif // GRIDSETTINGS_H diff --git a/include/ui/gridsettingsdialog.h b/include/ui/gridsettingsdialog.h deleted file mode 100644 index cd04a048..00000000 --- a/include/ui/gridsettingsdialog.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef GRIDSETTINGSDIALOG_H -#define GRIDSETTINGSDIALOG_H - -#include -#include - -#include "settings.h" - -namespace Ui { -class GridSettingsDialog; -} - -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; - bool dimensionsLinked = true; - bool offsetsLinked = true; - - void reset(bool force = false); - void setWidth(int value); - void setHeight(int value); - void setOffsetX(int value); - void setOffsetY(int value); - -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_currentIndexChanged(int index); - void onColorChanged(QRgb color); -}; - -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 182ea11a..6b7fc59d 100644 --- a/porymap.pro +++ b/porymap.pro @@ -61,7 +61,7 @@ SOURCES += src/core/block.cpp \ src/ui/collisionpixmapitem.cpp \ src/ui/connectionpixmapitem.cpp \ src/ui/currentselectedmetatilespixmapitem.cpp \ - src/ui/gridsettingsdialog.cpp \ + src/ui/gridsettings.cpp \ src/ui/newmapconnectiondialog.cpp \ src/ui/overlay.cpp \ src/ui/prefab.cpp \ @@ -159,7 +159,7 @@ HEADERS += include/core/block.h \ include/ui/collisionpixmapitem.h \ include/ui/connectionpixmapitem.h \ include/ui/currentselectedmetatilespixmapitem.h \ - include/ui/gridsettingsdialog.h \ + include/ui/gridsettings.h \ include/ui/newmapconnectiondialog.h \ include/ui/prefabframe.h \ include/ui/projectsettingseditor.h \ diff --git a/src/editor.cpp b/src/editor.cpp index 99e18c3e..3929d1e3 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1875,25 +1875,29 @@ void Editor::displayMapGrid() { // 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; + const int pixelMapWidth = map->getWidth() * 16; + const int pixelMapHeight = map->getHeight() * 16; + + // The grid can be moved with a user-specified x/y offset. The grid's dash patterns will only wrap in full pattern increments, + // so we draw an additional row/column outside the map that can be revealed as the offset changes. + const int offsetX = (this->gridSettings.offsetX % this->gridSettings.width) - this->gridSettings.width; + const int offsetY = (this->gridSettings.offsetY % this->gridSettings.height) - this->gridSettings.height; QPen pen; - pen.setStyle(this->gridSettings.style); pen.setColor(this->gridSettings.color); // Create vertical lines - int offset = this->gridSettings.offsetX % this->gridSettings.width; - for (uint i = offset; i <= pixelMapWidth; i += this->gridSettings.width) { - auto line = new QGraphicsLineItem(i, 0, i, pixelMapHeight); + pen.setDashPattern(this->gridSettings.getVerticalDashPattern()); + for (int i = offsetX; i <= pixelMapWidth; i += this->gridSettings.width) { + auto line = new QGraphicsLineItem(i, offsetY, i, pixelMapHeight); line->setPen(pen); this->mapGrid->addToGroup(line); } // Create horizontal lines - offset = this->gridSettings.offsetY % this->gridSettings.height; - for (uint i = offset; i <= pixelMapHeight; i += this->gridSettings.height) { - auto line = new QGraphicsLineItem(0, i, pixelMapWidth, i); + pen.setDashPattern(this->gridSettings.getHorizontalDashPattern()); + for (int i = offsetY; i <= pixelMapHeight; i += this->gridSettings.height) { + auto line = new QGraphicsLineItem(offsetX, i, pixelMapWidth, i); line->setPen(pen); this->mapGrid->addToGroup(line); } @@ -1901,6 +1905,12 @@ void Editor::displayMapGrid() { this->mapGrid->setVisible(porymapConfig.showGrid); } +void Editor::updateMapGrid() { + displayMapGrid(); + if (ui->graphicsView_Map->scene()) + ui->graphicsView_Map->scene()->update(); +} + void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) { if (map->layout->tileset_primary_label != tilesetLabel || forceLoad) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1623d055..93ed1dcb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1929,7 +1929,7 @@ void MainWindow::on_actionShow_Grid_triggered() { 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); + connect(this->gridSettingsDialog, &GridSettingsDialog::changedGridSettings, this->editor, &Editor::updateMapGrid); } openSubWindow(this->gridSettingsDialog); } diff --git a/src/ui/graphicsview.cpp b/src/ui/graphicsview.cpp index c6b78bba..f4de5074 100644 --- a/src/ui/graphicsview.cpp +++ b/src/ui/graphicsview.cpp @@ -31,12 +31,24 @@ void MapView::drawForeground(QPainter *painter, const QRectF&) { if (!editor) return; QStyleOptionGraphicsItem option; - if (editor->mapGrid) { - for (auto item : editor->mapGrid->childItems()) { - if (item->isVisible()) - item->paint(painter, &option, this); + + // Draw elements of the map view that should always render on top of anything added by the user with the scripting API. + + // Draw map grid + if (editor->mapGrid && editor->mapGrid->isVisible()) { + painter->save(); + if (editor->map) { + // We're clipping here to hide parts of the grid that are outside the map. + const QRectF mapRect(-0.5, -0.5, editor->map->getWidth() * 16 + 1.5, editor->map->getHeight() * 16 + 1.5); + painter->setClipping(true); + painter->setClipRect(mapRect); } + for (auto item : editor->mapGrid->childItems()) + item->paint(painter, &option, this); + painter->restore(); } + + // Draw cursor rectangles if (editor->playerViewRect && editor->playerViewRect->isVisible()) editor->playerViewRect->paint(painter, &option, this); if (editor->cursorMapTileRect && editor->cursorMapTileRect->isVisible()) diff --git a/src/ui/gridsettings.cpp b/src/ui/gridsettings.cpp new file mode 100644 index 00000000..96494e83 --- /dev/null +++ b/src/ui/gridsettings.cpp @@ -0,0 +1,230 @@ +#include "ui_gridsettingsdialog.h" +#include "gridsettings.h" + +// TODO: Save settings in config + +const QMap GridSettings::styleToName = { + {Style::Solid, "Solid"}, + {Style::LargeDashes, "Large Dashes"}, + {Style::SmallDashes, "Small Dashes"}, + {Style::Crosshairs, "Crosshairs"}, + {Style::Dots, "Dots"}, +}; + +QString GridSettings::getStyleName(GridSettings::Style style) { + return styleToName.value(style); +} + +GridSettings::Style GridSettings::getStyleFromName(const QString &name) { + return styleToName.key(name, GridSettings::Style::Solid); +} + +// We do some extra work here to A: try and center the dashes away from the intersections, and B: keep the dash pattern's total +// length equal to the length of a grid square. This keeps the patterns looking reasonable regardless of the grid size. +// Otherwise, the dashes can start to intersect in weird ways and create grid patterns that don't look like a rectangular grid. +QList GridSettings::getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const { + const qreal minEdgesLength = 0.6*2; + if (length <= dashLength + minEdgesLength) + return {dashLength}; + + // Every dash after the first one needs to have room for a 'gapLength' segment. + const int numDashes = 1 + ((length - minEdgesLength) - dashLength) / (dashLength + gapLength); + + // Total length of the pattern excluding the centering edges. There are always 1 fewer gap segments than dashes. + const qreal mainLength = (dashLength * numDashes) + (gapLength * (numDashes-1)); + + const qreal edgeLength = (length - mainLength) / 2; + + // Fill the pattern + QList pattern = {0, edgeLength}; + for (int i = 0; i < numDashes-1; i++) { + pattern.append(dashLength); + pattern.append(gapLength); + } + pattern.append(dashLength); + pattern.append(edgeLength); + + return pattern; +} + +QList GridSettings::getDashPattern(uint length) const { + switch (this->style) { + + // Equivalent to setting Qt::PenStyle::Solid with no dash pattern. + case Style::Solid: return {1, 0}; + + // Roughly equivalent to Qt::PenStyle::DashLine but with centering. + case Style::LargeDashes: return getCenteredDashPattern(length, 3.0, 2.0); + + // Roughly equivalent to Qt::PenStyle::DotLine but with centering. + case Style::SmallDashes: return getCenteredDashPattern(length, 1.0, 2.5); + + // Dashes only at intersections, in the shape of a crosshair. + case Style::Crosshairs: { + const qreal crosshairLength = 2.0; + return {crosshairLength / 2, length - crosshairLength, crosshairLength / 2, 0}; + } + + // Dots only at intersections. + case Style::Dots: { + const qreal dotLength = 0.1; + return {dotLength, length - dotLength}; + } + + // Invalid + default: return {}; + } +} + + + +GridSettingsDialog::GridSettingsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::GridSettingsDialog), + m_settings(new GridSettings), + m_originalSettings(*m_settings) +{ + m_ownedSettings = true; + init(); +} + +GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) : + QDialog(parent), + ui(new Ui::GridSettingsDialog), + m_settings(settings), + m_originalSettings(*settings) +{ + m_ownedSettings = false; + init(); +} + +void GridSettingsDialog::init() { + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + // Populate the styles combo box + const QSignalBlocker b_Style(ui->comboBox_Style); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Solid)); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::LargeDashes)); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::SmallDashes)); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Crosshairs)); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Dots)); + + ui->button_LinkDimensions->setChecked(m_dimensionsLinked); + ui->button_LinkOffsets->setChecked(m_offsetsLinked); + + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &GridSettingsDialog::dialogButtonClicked); + connect(ui->button_LinkDimensions, &QAbstractButton::toggled, [this](bool on) { m_dimensionsLinked = on; }); + connect(ui->button_LinkOffsets, &QAbstractButton::toggled, [this](bool on) { m_offsetsLinked = on; }); + connect(ui->colorInput, &ColorInputWidget::colorChanged, this, &GridSettingsDialog::onColorChanged); + + updateInput(); +} + +GridSettingsDialog::~GridSettingsDialog() { + delete ui; + if (m_ownedSettings) + delete m_settings; +} + +void GridSettingsDialog::setSettings(const GridSettings &settings) { + if (*m_settings == settings) + return; + *m_settings = settings; + updateInput(); + emit changedGridSettings(); +} + +void GridSettingsDialog::updateInput() { + setWidth(m_settings->width); + setHeight(m_settings->height); + setOffsetX(m_settings->offsetX); + setOffsetY(m_settings->offsetY); + + const QSignalBlocker b_Color(ui->colorInput); + ui->colorInput->setColor(m_settings->color.rgb()); + + const QSignalBlocker b_Style(ui->comboBox_Style); + ui->comboBox_Style->setCurrentText(GridSettings::getStyleName(m_settings->style)); +} + +void GridSettingsDialog::setWidth(int value) { + const QSignalBlocker b(ui->spinBox_Width); + ui->spinBox_Width->setValue(value); + m_settings->width = value; +} + +void GridSettingsDialog::setHeight(int value) { + const QSignalBlocker b(ui->spinBox_Height); + ui->spinBox_Height->setValue(value); + m_settings->height = value; +} + +void GridSettingsDialog::setOffsetX(int value) { + const QSignalBlocker b(ui->spinBox_X); + ui->spinBox_X->setValue(value); + m_settings->offsetX = value; +} + +void GridSettingsDialog::setOffsetY(int value) { + const QSignalBlocker b(ui->spinBox_Y); + ui->spinBox_Y->setValue(value); + m_settings->offsetY = value; +} + +void GridSettingsDialog::on_spinBox_Width_valueChanged(int value) { + setWidth(value); + if (m_dimensionsLinked) + setHeight(value); + + emit changedGridSettings(); +} + +void GridSettingsDialog::on_spinBox_Height_valueChanged(int value) { + setHeight(value); + if (m_dimensionsLinked) + setWidth(value); + + emit changedGridSettings(); +} + +void GridSettingsDialog::on_spinBox_X_valueChanged(int value) { + setOffsetX(value); + if (m_offsetsLinked) + setOffsetY(value); + + emit changedGridSettings(); +} + +void GridSettingsDialog::on_spinBox_Y_valueChanged(int value) { + setOffsetY(value); + if (m_offsetsLinked) + setOffsetX(value); + + emit changedGridSettings(); +} + +void GridSettingsDialog::on_comboBox_Style_currentTextChanged(const QString &text) { + m_settings->style = GridSettings::getStyleFromName(text); + emit changedGridSettings(); +} + +void GridSettingsDialog::onColorChanged(QRgb color) { + m_settings->color = QColor::fromRgb(color); + emit changedGridSettings(); +} + +void GridSettingsDialog::dialogButtonClicked(QAbstractButton *button) { + auto role = ui->buttonBox->buttonRole(button); + if (role == QDialogButtonBox::AcceptRole) { + // "OK" + close(); + } else if (role == QDialogButtonBox::RejectRole) { + // "Cancel" + setSettings(m_originalSettings); + close(); + } else if (role == QDialogButtonBox::ResetRole) { + // "Restore Defaults" + setSettings(m_defaultSettings); + } +} diff --git a/src/ui/gridsettingsdialog.cpp b/src/ui/gridsettingsdialog.cpp deleted file mode 100644 index 3ce0d4df..00000000 --- a/src/ui/gridsettingsdialog.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include "ui_gridsettingsdialog.h" -#include "gridsettingsdialog.h" - -// TODO: Save settings in config -// TODO: Look into custom painting to improve performance -// TODO: Add tooltips - -const QList> penStyleMap = { - {"Solid", Qt::SolidLine}, - {"Large Dashes", Qt::DashLine}, - {"Small Dashes", Qt::DotLine}, - {"Dots", Qt::CustomDashLine}, // TODO: Implement a custom pattern for this -}; - -GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) : - QDialog(parent), - ui(new Ui::GridSettingsDialog), - settings(settings) -{ - ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - - // Populate the styles combo box - for (const auto &pair : penStyleMap) - ui->comboBox_Style->addItem(pair.first, static_cast(pair.second)); - - ui->spinBox_Width->setMaximum(INT_MAX); - ui->spinBox_Height->setMaximum(INT_MAX); - ui->spinBox_X->setMaximum(INT_MAX); - ui->spinBox_Y->setMaximum(INT_MAX); - - ui->button_LinkDimensions->setChecked(this->dimensionsLinked); - ui->button_LinkOffsets->setChecked(this->offsetsLinked); - - // Initialize the settings - 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); - connect(ui->button_LinkDimensions, &QAbstractButton::toggled, [this](bool on) { this->dimensionsLinked = on; }); - connect(ui->button_LinkOffsets, &QAbstractButton::toggled, [this](bool on) { this->offsetsLinked = on; }); - connect(ui->colorInput, &ColorInputWidget::colorChanged, this, &GridSettingsDialog::onColorChanged); -} - -GridSettingsDialog::~GridSettingsDialog() { - delete ui; -} - -void GridSettingsDialog::reset(bool force) { - if (!force && *this->settings == this->originalSettings) - return; - *this->settings = this->originalSettings; - - setWidth(this->settings->width); - setHeight(this->settings->height); - setOffsetX(this->settings->offsetX); - setOffsetY(this->settings->offsetY); - - const QSignalBlocker b_Color(ui->colorInput); - ui->colorInput->setColor(this->settings->color.rgb()); - - const QSignalBlocker b_Style(ui->comboBox_Style); - // TODO: Debug - //ui->comboBox_Style->setCurrentIndex(ui->comboBox_Style->findData(static_cast(this->settings->style))); - for (const auto &pair : penStyleMap) { - if (pair.second == this->settings->style) { - ui->comboBox_Style->setCurrentText(pair.first); - break; - } - } - - emit changedGridSettings(); -} - -void GridSettingsDialog::setWidth(int value) { - const QSignalBlocker b(ui->spinBox_Width); - ui->spinBox_Width->setValue(value); - this->settings->width = value; -} - -void GridSettingsDialog::setHeight(int value) { - const QSignalBlocker b(ui->spinBox_Height); - ui->spinBox_Height->setValue(value); - this->settings->height = value; -} - -void GridSettingsDialog::setOffsetX(int value) { - const QSignalBlocker b(ui->spinBox_X); - ui->spinBox_X->setValue(value); - this->settings->offsetX = value; -} - -void GridSettingsDialog::setOffsetY(int value) { - const QSignalBlocker b(ui->spinBox_Y); - ui->spinBox_Y->setValue(value); - this->settings->offsetY = value; -} - -void GridSettingsDialog::on_spinBox_Width_valueChanged(int value) { - setWidth(value); - if (this->dimensionsLinked) - setHeight(value); - - emit changedGridSettings(); -} - -void GridSettingsDialog::on_spinBox_Height_valueChanged(int value) { - setHeight(value); - if (this->dimensionsLinked) - setWidth(value); - - emit changedGridSettings(); -} - -void GridSettingsDialog::on_spinBox_X_valueChanged(int value) { - setOffsetX(value); - if (this->offsetsLinked) - setOffsetY(value); - - emit changedGridSettings(); -} - -void GridSettingsDialog::on_spinBox_Y_valueChanged(int value) { - setOffsetY(value); - if (this->offsetsLinked) - setOffsetX(value); - - emit changedGridSettings(); -} - -void GridSettingsDialog::on_comboBox_Style_currentIndexChanged(int index) { - if (index < 0 || index >= penStyleMap.length()) - return; - - this->settings->style = penStyleMap.at(index).second; - emit changedGridSettings(); -} - -void GridSettingsDialog::onColorChanged(QRgb color) { - this->settings->color = QColor::fromRgb(color); - 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(); // TODO: We should restore to original defaults, not to the values when the window was opened. - } -} From 932c29993508e897dc215ebaef7a51d396d5aed6 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 1 Oct 2024 02:20:26 -0400 Subject: [PATCH 6/8] Refactor palette editor to use new color input widget --- forms/colorinputwidget.ui | 3 - forms/paletteeditor.ui | 5084 +---------------------------------- include/ui/paletteeditor.h | 35 +- src/ui/colorinputwidget.cpp | 2 - src/ui/paletteeditor.cpp | 342 +-- 5 files changed, 104 insertions(+), 5362 deletions(-) diff --git a/forms/colorinputwidget.ui b/forms/colorinputwidget.ui index eebd7955..11f0bc25 100644 --- a/forms/colorinputwidget.ui +++ b/forms/colorinputwidget.ui @@ -10,9 +10,6 @@ 212 - - Color - diff --git a/forms/paletteeditor.ui b/forms/paletteeditor.ui index 1cd7c959..c1a4ee7a 100644 --- a/forms/paletteeditor.ui +++ b/forms/paletteeditor.ui @@ -7,7 +7,7 @@ 0 0 907 - 886 + 933 @@ -15,5039 +15,13 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Color 0 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 1 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 2 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 3 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 4 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 5 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 6 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 7 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 8 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 9 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 10 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 11 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 12 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 13 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 14 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 15 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - + - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised @@ -5060,14 +34,14 @@ - Qt::StrongFocus + Qt::FocusPolicy::StrongFocus - Qt::Horizontal + Qt::Orientation::Horizontal @@ -5078,7 +52,7 @@ - + Bit Depth: @@ -5101,6 +75,40 @@ + + + + QFrame::Shape::NoFrame + + + true + + + + + 0 + 0 + 883 + 784 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + @@ -5109,7 +117,7 @@ 0 0 907 - 22 + 37 @@ -5137,10 +145,10 @@ Ctrl+Z - Qt::WindowShortcut + Qt::ShortcutContext::WindowShortcut - QAction::NormalPriority + QAction::Priority::NormalPriority @@ -5157,8 +165,6 @@ - - - + diff --git a/include/ui/paletteeditor.h b/include/ui/paletteeditor.h index 9b846d60..6aa9e131 100644 --- a/include/ui/paletteeditor.h +++ b/include/ui/paletteeditor.h @@ -2,10 +2,8 @@ #define PALETTEEDITOR_H #include -#include -#include -#include -#include + +#include "colorinputwidget.h" #include "project.h" #include "history.h" @@ -32,43 +30,26 @@ public: private: Ui::PaletteEditor *ui; Project *project = nullptr; - - QList> sliders; - QList> spinners; - QList frames; - QList pickButtons; - QList hexEdits; + QList colorInputs; Tileset *primaryTileset; Tileset *secondaryTileset; QList> palettesHistory; - void refreshColorUis(); - void updateColorUi(int index, QRgb color); - void commitEditHistory(int paletteid); + Tileset* getTileset(int paletteId); + void refreshColorInputs(); + void commitEditHistory(int paletteId); void restoreWindowState(); - void setSignalsEnabled(bool enabled); - void setColorsFromHistory(PaletteHistoryItem*, int); void closeEvent(QCloseEvent*); - void pickColor(int i); void setRgb(int index, QRgb rgb); - void setRgbFromSliders(int colorIndex); - void setRgbFromHexEdit(int colorIndex); - void setRgbFromSpinners(int colorIndex); + void setPalette(int paletteId, const QList &palette); void setBitDepth(int bits); int bitDepth = 24; - class HexCodeValidator : public QValidator { - virtual QValidator::State validate(QString &input, int &) const override { - input = input.toUpper(); - return QValidator::Acceptable; - } - }; - - HexCodeValidator *hexValidator = nullptr; + static const int numColors = 16; signals: void closed(); diff --git a/src/ui/colorinputwidget.cpp b/src/ui/colorinputwidget.cpp index 200567af..bbd6f764 100644 --- a/src/ui/colorinputwidget.cpp +++ b/src/ui/colorinputwidget.cpp @@ -4,8 +4,6 @@ #include -// TODO: Refactor palette editor to make use of this class - class HexCodeValidator : public QValidator { virtual QValidator::State validate(QString &input, int &) const override { input = input.toUpper(); diff --git a/src/ui/paletteeditor.cpp b/src/ui/paletteeditor.cpp index 8dcd2a7a..456d1f99 100644 --- a/src/ui/paletteeditor.cpp +++ b/src/ui/paletteeditor.cpp @@ -1,19 +1,12 @@ #include "paletteeditor.h" #include "ui_paletteeditor.h" -#include "colorpicker.h" #include "paletteutil.h" #include "config.h" #include "log.h" -#include #include #include -static inline int rgb5(int rgb) { return round(static_cast(rgb * 31) / 255.0); } -static inline int rgb8(int rgb) { return round(rgb * 255. / 31.); } -static inline int gbaRed(int rgb) { return rgb & 0x1f; } -static inline int gbaGreen(int rgb) { return (rgb >> 5) & 0x1f; } -static inline int gbaBlue(int rgb) { return (rgb >> 10) & 0x1f; } PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset *secondaryTileset, int paletteId, QWidget *parent) : QMainWindow(parent), @@ -26,55 +19,13 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset this->ui->spinBox_PaletteId->setMinimum(0); this->ui->spinBox_PaletteId->setMaximum(Project::getNumPalettesTotal() - 1); - this->sliders.clear(); - for (int i = 0; i < 16; i++) { - QList rgbSliders; - rgbSliders.append(this->ui->container->findChild("slider_red_" + QString::number(i))); - rgbSliders.append(this->ui->container->findChild("slider_green_" + QString::number(i))); - rgbSliders.append(this->ui->container->findChild("slider_blue_" + QString::number(i))); - this->sliders.append(rgbSliders); - - connect(this->sliders[i][0], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); }); - connect(this->sliders[i][1], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); }); - connect(this->sliders[i][2], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); }); - } - - this->spinners.clear(); - for (int i = 0; i < 16; i++) { - QList rgbSpinners; - rgbSpinners.append(this->ui->container->findChild("spin_red_" + QString::number(i))); - rgbSpinners.append(this->ui->container->findChild("spin_green_" + QString::number(i))); - rgbSpinners.append(this->ui->container->findChild("spin_blue_" + QString::number(i))); - this->spinners.append(rgbSpinners); - - connect(this->spinners[i][0], QOverload::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); }); - connect(this->spinners[i][1], QOverload::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); }); - connect(this->spinners[i][2], QOverload::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); }); - } - - this->frames.clear(); - for (int i = 0; i < 16; i++) { - this->frames.append(this->ui->container->findChild("colorFrame_" + QString::number(i))); - this->frames[i]->setFrameStyle(QFrame::NoFrame); - } - - this->pickButtons.clear(); - for (int i = 0; i < 16; i++) { - this->pickButtons.append(this->ui->container->findChild("pick_" + QString::number(i))); - } - - this->hexValidator = new HexCodeValidator; - this->hexEdits.clear(); - for (int i = 0; i < 16; i++) { - this->hexEdits.append(this->ui->container->findChild("hex_" + QString::number(i))); - this->hexEdits[i]->setValidator(hexValidator); - } - - // Connect to function that will update color when hex edit is changed - for (int i = 0; i < this->hexEdits.length(); i++) { - connect(this->hexEdits[i], &QLineEdit::textEdited, [this, i](QString text){ - if ((this->bitDepth == 24 && text.length() == 6) || (this->bitDepth == 15 && text.length() == 4)) setRgbFromHexEdit(i); - }); + this->colorInputs.clear(); + const int numColorsPerRow = 4; + for (int i = 0; i < this->numColors; i++) { + auto colorInput = new ColorInputWidget(QString("Color %1").arg(i)); + connect(colorInput, &ColorInputWidget::colorChanged, [this, i](QRgb color) { setRgb(i, color); }); + this->colorInputs.append(colorInput); + ui->layout_Colors->addWidget(colorInput, i / numColorsPerRow, i % numColorsPerRow); } // Setup edit-undo history for each of the palettes. @@ -82,11 +33,6 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset this->palettesHistory.append(History()); } - // Connect the color picker's selection to the correct color index - for (int i = 0; i < 16; i++) { - connect(this->pickButtons[i], &QToolButton::clicked, [this, i](){ this->pickColor(i); }); - } - int bitDepth = porymapConfig.paletteEditorBitDepth; if (bitDepth == 15) { this->ui->bit_depth_15->setChecked(true); @@ -107,229 +53,67 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset PaletteEditor::~PaletteEditor() { delete ui; - delete this->hexValidator; } -void PaletteEditor::updateColorUi(int colorIndex, QRgb rgb) { - setSignalsEnabled(false); - - int red = qRed(rgb); - int green = qGreen(rgb); - int blue = qBlue(rgb); - - if (this->bitDepth == 15) { - // sliders - this->sliders[colorIndex][0]->setValue(rgb5(red)); - this->sliders[colorIndex][1]->setValue(rgb5(green)); - this->sliders[colorIndex][2]->setValue(rgb5(blue)); - - // hex - int hex15 = (rgb5(blue) << 10) | (rgb5(green) << 5) | rgb5(red); - QString hexcode = QString("%1").arg(hex15, 4, 16, QLatin1Char('0')).toUpper(); - this->hexEdits[colorIndex]->setText(hexcode); - - // spinners - this->spinners[colorIndex][0]->setValue(rgb5(red)); - this->spinners[colorIndex][1]->setValue(rgb5(green)); - this->spinners[colorIndex][2]->setValue(rgb5(blue)); - } else { - // sliders - this->sliders[colorIndex][0]->setValue(red); - this->sliders[colorIndex][1]->setValue(green); - this->sliders[colorIndex][2]->setValue(blue); - - // hex - QColor color(red, green, blue); - QString hexcode = color.name().remove(0, 1).toUpper(); - this->hexEdits[colorIndex]->setText(hexcode); - - // spinners - this->spinners[colorIndex][0]->setValue(red); - this->spinners[colorIndex][1]->setValue(green); - this->spinners[colorIndex][2]->setValue(blue); - } - - // frame - QString stylesheet = QString("background-color: rgb(%1, %2, %3);").arg(red).arg(green).arg(blue); - this->frames[colorIndex]->setStyleSheet(stylesheet); - - setSignalsEnabled(true); -} - -void PaletteEditor::setSignalsEnabled(bool enabled) { - // spinners, sliders, hexbox - for (int i = 0; i < this->sliders.length(); i++) { - this->sliders.at(i).at(0)->blockSignals(!enabled); - this->sliders.at(i).at(1)->blockSignals(!enabled); - this->sliders.at(i).at(2)->blockSignals(!enabled); - } - - for (int i = 0; i < this->spinners.length(); i++) { - this->spinners.at(i).at(0)->blockSignals(!enabled); - this->spinners.at(i).at(1)->blockSignals(!enabled); - this->spinners.at(i).at(2)->blockSignals(!enabled); - } - - for (int i = 0; i < this->hexEdits.length(); i++) { - this->hexEdits.at(i)->blockSignals(!enabled); - } +Tileset* PaletteEditor::getTileset(int paletteId) { + return (paletteId < Project::getNumPalettesPrimary()) + ? this->primaryTileset + : this->secondaryTileset; } void PaletteEditor::setBitDepth(int bits) { - setSignalsEnabled(false); - switch (bits) { - case 15: - for (int i = 0; i < 16; i++) { - // sliders ranged [0, 31] with 1 single step and 4 page step - this->sliders[i][0]->setSingleStep(1); - this->sliders[i][1]->setSingleStep(1); - this->sliders[i][2]->setSingleStep(1); - this->sliders[i][0]->setPageStep(4); - this->sliders[i][1]->setPageStep(4); - this->sliders[i][2]->setPageStep(4); - this->sliders[i][0]->setMaximum(31); - this->sliders[i][1]->setMaximum(31); - this->sliders[i][2]->setMaximum(31); - - // spinners limited [0, 31] with 1 step - this->spinners[i][0]->setSingleStep(1); - this->spinners[i][1]->setSingleStep(1); - this->spinners[i][2]->setSingleStep(1); - this->spinners[i][0]->setMaximum(31); - this->spinners[i][1]->setMaximum(31); - this->spinners[i][2]->setMaximum(31); - - // hex box now 4 digits - this->hexEdits[i]->setInputMask("HHHH"); - this->hexEdits[i]->setMaxLength(4); - } - break; - case 24: - default: - for (int i = 0; i < 16; i++) { - // sliders ranged [0, 31] with 1 single step and 4 page step - this->sliders[i][0]->setSingleStep(8); - this->sliders[i][1]->setSingleStep(8); - this->sliders[i][2]->setSingleStep(8); - this->sliders[i][0]->setPageStep(24); - this->sliders[i][1]->setPageStep(24); - this->sliders[i][2]->setPageStep(24); - this->sliders[i][0]->setMaximum(255); - this->sliders[i][1]->setMaximum(255); - this->sliders[i][2]->setMaximum(255); - - // spinners limited [0, 31] with 1 step - this->spinners[i][0]->setSingleStep(8); - this->spinners[i][1]->setSingleStep(8); - this->spinners[i][2]->setSingleStep(8); - this->spinners[i][0]->setMaximum(255); - this->spinners[i][1]->setMaximum(255); - this->spinners[i][2]->setMaximum(255); - - // hex box now 4 digits - this->hexEdits[i]->setInputMask("HHHHHH"); - this->hexEdits[i]->setMaxLength(6); - } - break; - } this->bitDepth = bits; porymapConfig.paletteEditorBitDepth = bits; - refreshColorUis(); - setSignalsEnabled(true); + for (const auto &colorInput : this->colorInputs) { + colorInput->setBitDepth(bits); + } } void PaletteEditor::setRgb(int colorIndex, QRgb rgb) { - int paletteNum = this->ui->spinBox_PaletteId->value(); + const int paletteId = this->ui->spinBox_PaletteId->value(); - Tileset *tileset = paletteNum < Project::getNumPalettesPrimary() - ? this->primaryTileset - : this->secondaryTileset; - tileset->palettes[paletteNum][colorIndex] = rgb; - tileset->palettePreviews[paletteNum][colorIndex] = rgb; - - this->updateColorUi(colorIndex, rgb); + Tileset *tileset = getTileset(paletteId); + tileset->palettes[paletteId][colorIndex] = rgb; + tileset->palettePreviews[paletteId][colorIndex] = rgb; - this->commitEditHistory(paletteNum); - emit this->changedPaletteColor(); + commitEditHistory(paletteId); + emit changedPaletteColor(); } -void PaletteEditor::setRgbFromSliders(int colorIndex) { - if (this->bitDepth == 15) { - setRgb(colorIndex, qRgb(rgb8(this->sliders[colorIndex][0]->value()), - rgb8(this->sliders[colorIndex][1]->value()), - rgb8(this->sliders[colorIndex][2]->value()))); - } else { - setRgb(colorIndex, qRgb(this->sliders[colorIndex][0]->value(), - this->sliders[colorIndex][1]->value(), - this->sliders[colorIndex][2]->value())); +void PaletteEditor::setPalette(int paletteId, const QList &palette) { + Tileset *tileset = getTileset(paletteId); + for (int i = 0; i < this->numColors; i++) { + tileset->palettes[paletteId][i] = palette.at(i); + tileset->palettePreviews[paletteId][i] = palette.at(i); } + refreshColorInputs(); + emit changedPaletteColor(); } -void PaletteEditor::setRgbFromHexEdit(int colorIndex) { - QString text = this->hexEdits[colorIndex]->text(); - bool ok = false; - int rgb = text.toInt(&ok, 16); - if (!ok) rgb = 0xFFFFFFFF; - if (this->bitDepth == 15) { - int rc = gbaRed(rgb); - int gc = gbaGreen(rgb); - int bc = gbaBlue(rgb); - setRgb(colorIndex, qRgb(rgb8(rc), rgb8(gc), rgb8(bc))); - } else { - setRgb(colorIndex, qRgb(qRed(rgb), qGreen(rgb), qBlue(rgb))); - } -} - -void PaletteEditor::setRgbFromSpinners(int colorIndex) { - if (this->bitDepth == 15) { - setRgb(colorIndex, qRgb(rgb8(this->spinners[colorIndex][0]->value()), - rgb8(this->spinners[colorIndex][1]->value()), - rgb8(this->spinners[colorIndex][2]->value()))); - } else { - setRgb(colorIndex, qRgb(this->spinners[colorIndex][0]->value(), - this->spinners[colorIndex][1]->value(), - this->spinners[colorIndex][2]->value())); - } -} - -void PaletteEditor::refreshColorUis() { - int paletteNum = this->ui->spinBox_PaletteId->value(); - for (int i = 0; i < 16; i++) { - QRgb color; - if (paletteNum < Project::getNumPalettesPrimary()) { - color = this->primaryTileset->palettes.at(paletteNum).at(i); - } else { - color = this->secondaryTileset->palettes.at(paletteNum).at(i); - } - - this->updateColorUi(i, color); +void PaletteEditor::refreshColorInputs() { + const int paletteId = ui->spinBox_PaletteId->value(); + Tileset *tileset = getTileset(paletteId); + for (int i = 0; i < this->numColors; i++) { + auto colorInput = this->colorInputs.at(i); + const QSignalBlocker b(colorInput); + colorInput->setColor(tileset->palettes.at(paletteId).at(i)); } } void PaletteEditor::setPaletteId(int paletteId) { - this->ui->spinBox_PaletteId->blockSignals(true); + const QSignalBlocker b(ui->spinBox_PaletteId); this->ui->spinBox_PaletteId->setValue(paletteId); - this->refreshColorUis(); - this->ui->spinBox_PaletteId->blockSignals(false); + this->refreshColorInputs(); } void PaletteEditor::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; - this->refreshColorUis(); -} - -void PaletteEditor::pickColor(int index) { - ColorPicker picker(this); - if (picker.exec() == QDialog::Accepted) { - QColor c = picker.getColor(); - this->setRgb(index, c.rgb()); - } - return; + this->refreshColorInputs(); } void PaletteEditor::on_spinBox_PaletteId_valueChanged(int paletteId) { - this->refreshColorUis(); + this->refreshColorInputs(); if (!this->palettesHistory[paletteId].current()) { this->commitEditHistory(paletteId); } @@ -338,8 +122,8 @@ void PaletteEditor::on_spinBox_PaletteId_valueChanged(int paletteId) { void PaletteEditor::commitEditHistory(int paletteId) { QList colors; - for (int i = 0; i < 16; i++) { - colors.append(qRgb(this->spinners[i][0]->value(), this->spinners[i][1]->value(), this->spinners[i][2]->value())); + for (int i = 0; i < this->numColors; i++) { + colors.append(this->colorInputs.at(i)->color()); } PaletteHistoryItem *commit = new PaletteHistoryItem(colors); this->palettesHistory[paletteId].push(commit); @@ -356,31 +140,16 @@ void PaletteEditor::on_actionUndo_triggered() { int paletteId = this->ui->spinBox_PaletteId->value(); PaletteHistoryItem *prev = this->palettesHistory[paletteId].back(); - this->setColorsFromHistory(prev, paletteId); + if (prev) + setPalette(paletteId, prev->colors); } void PaletteEditor::on_actionRedo_triggered() { int paletteId = this->ui->spinBox_PaletteId->value(); PaletteHistoryItem *next = this->palettesHistory[paletteId].next(); - this->setColorsFromHistory(next, paletteId); -} - -void PaletteEditor::setColorsFromHistory(PaletteHistoryItem *history, int paletteId) { - if (!history) return; - - for (int i = 0; i < 16; i++) { - if (paletteId < Project::getNumPalettesPrimary()) { - this->primaryTileset->palettes[paletteId][i] = history->colors.at(i); - this->primaryTileset->palettePreviews[paletteId][i] = history->colors.at(i); - } else { - this->secondaryTileset->palettes[paletteId][i] = history->colors.at(i); - this->secondaryTileset->palettePreviews[paletteId][i] = history->colors.at(i); - } - } - - this->refreshColorUis(); - emit this->changedPaletteColor(); + if (next) + setPalette(paletteId, next->colors); } void PaletteEditor::on_actionImport_Palette_triggered() @@ -407,10 +176,12 @@ void PaletteEditor::on_actionImport_Palette_triggered() return; } - if (palette.length() < 16) { + if (palette.length() < this->numColors) { QMessageBox msgBox(this); msgBox.setText("Failed to import palette."); - QString message = QString("The palette file has %1 colors, but it must have 16 colors.").arg(palette.length()); + QString message = QString("The palette file has %1 colors, but it must have %2 colors.") + .arg(palette.length()) + .arg(this->numColors); msgBox.setInformativeText(message); msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setIcon(QMessageBox::Icon::Critical); @@ -418,20 +189,9 @@ void PaletteEditor::on_actionImport_Palette_triggered() return; } - int paletteId = this->ui->spinBox_PaletteId->value(); - for (int i = 0; i < 16; i++) { - if (paletteId < Project::getNumPalettesPrimary()) { - this->primaryTileset->palettes[paletteId][i] = palette.at(i); - this->primaryTileset->palettePreviews[paletteId][i] = palette.at(i); - } else { - this->secondaryTileset->palettes[paletteId][i] = palette.at(i); - this->secondaryTileset->palettePreviews[paletteId][i] = palette.at(i); - } - } - - this->refreshColorUis(); - this->commitEditHistory(paletteId); - emit this->changedPaletteColor(); + const int paletteId = ui->spinBox_PaletteId->value(); + setPalette(paletteId, palette); + commitEditHistory(paletteId); } void PaletteEditor::closeEvent(QCloseEvent*) { From eefa46a2a2751dc454419e6cf0b2e94a76eb268e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 1 Oct 2024 10:19:40 -0400 Subject: [PATCH 7/8] Fix Qt 5.15 build --- include/ui/gridsettings.h | 8 ++++---- src/ui/gridsettings.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/ui/gridsettings.h b/include/ui/gridsettings.h index 0a966e4c..807a0685 100644 --- a/include/ui/gridsettings.h +++ b/include/ui/gridsettings.h @@ -23,16 +23,16 @@ public: int offsetY = 0; Style style = Style::Solid; QColor color = Qt::black; - QList getHorizontalDashPattern() const { return this->getDashPattern(this->width); } - QList getVerticalDashPattern() const { return this->getDashPattern(this->height); } + QVector getHorizontalDashPattern() const { return this->getDashPattern(this->width); } + QVector getVerticalDashPattern() const { return this->getDashPattern(this->height); } static QString getStyleName(Style style); static GridSettings::Style getStyleFromName(const QString &name); private: static const QMap styleToName; - QList getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const; - QList getDashPattern(uint length) const; + QVector getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const; + QVector getDashPattern(uint length) const; }; inline bool operator==(const GridSettings &a, const GridSettings &b) { diff --git a/src/ui/gridsettings.cpp b/src/ui/gridsettings.cpp index 96494e83..b4e180af 100644 --- a/src/ui/gridsettings.cpp +++ b/src/ui/gridsettings.cpp @@ -22,7 +22,7 @@ GridSettings::Style GridSettings::getStyleFromName(const QString &name) { // We do some extra work here to A: try and center the dashes away from the intersections, and B: keep the dash pattern's total // length equal to the length of a grid square. This keeps the patterns looking reasonable regardless of the grid size. // Otherwise, the dashes can start to intersect in weird ways and create grid patterns that don't look like a rectangular grid. -QList GridSettings::getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const { +QVector GridSettings::getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const { const qreal minEdgesLength = 0.6*2; if (length <= dashLength + minEdgesLength) return {dashLength}; @@ -36,7 +36,7 @@ QList GridSettings::getCenteredDashPattern(uint length, qreal dashLength, const qreal edgeLength = (length - mainLength) / 2; // Fill the pattern - QList pattern = {0, edgeLength}; + QVector pattern = {0, edgeLength}; for (int i = 0; i < numDashes-1; i++) { pattern.append(dashLength); pattern.append(gapLength); @@ -47,7 +47,7 @@ QList GridSettings::getCenteredDashPattern(uint length, qreal dashLength, return pattern; } -QList GridSettings::getDashPattern(uint length) const { +QVector GridSettings::getDashPattern(uint length) const { switch (this->style) { // Equivalent to setting Qt::PenStyle::Solid with no dash pattern. From 4dc598455f58ce9addcfb9474f396f6955cac464 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 4 Oct 2024 13:36:50 -0400 Subject: [PATCH 8/8] Improve color slider edit history --- include/ui/colorinputwidget.h | 1 + include/ui/paletteeditor.h | 1 + src/ui/colorinputwidget.cpp | 15 +++++++++++++++ src/ui/paletteeditor.cpp | 10 +++++++--- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/include/ui/colorinputwidget.h b/include/ui/colorinputwidget.h index 5b414776..cd871e0b 100644 --- a/include/ui/colorinputwidget.h +++ b/include/ui/colorinputwidget.h @@ -25,6 +25,7 @@ public: signals: void colorChanged(QRgb color); void bitDepthChanged(int bits); + void editingFinished(); private: Ui::ColorInputWidget *ui; diff --git a/include/ui/paletteeditor.h b/include/ui/paletteeditor.h index 6aa9e131..63581eb1 100644 --- a/include/ui/paletteeditor.h +++ b/include/ui/paletteeditor.h @@ -39,6 +39,7 @@ private: Tileset* getTileset(int paletteId); void refreshColorInputs(); + void commitEditHistory(); void commitEditHistory(int paletteId); void restoreWindowState(); void closeEvent(QCloseEvent*); diff --git a/src/ui/colorinputwidget.cpp b/src/ui/colorinputwidget.cpp index bbd6f764..8b40be27 100644 --- a/src/ui/colorinputwidget.cpp +++ b/src/ui/colorinputwidget.cpp @@ -34,6 +34,7 @@ ColorInputWidget::ColorInputWidget(const QString &title, QWidget *parent) : void ColorInputWidget::init() { ui->setupUi(this); + // Connect color change signals connect(ui->slider_Red, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); connect(ui->slider_Green, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); connect(ui->slider_Blue, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); @@ -46,6 +47,19 @@ void ColorInputWidget::init() { ui->lineEdit_Hex->setValidator(&hexValidator); connect(ui->lineEdit_Hex, &QLineEdit::textEdited, this, &ColorInputWidget::setRgbFromHexString); + // We have separate signals for when color input editing finishes. + // This is mostly useful for external commit histories, esp. for the sliders which can rapidly emit color change signals. + connect(ui->slider_Red, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished); + connect(ui->slider_Green, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished); + connect(ui->slider_Blue, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished); + + connect(ui->spinBox_Red, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished); + connect(ui->spinBox_Green, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished); + connect(ui->spinBox_Blue, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished); + + connect(ui->lineEdit_Hex, &QLineEdit::editingFinished, this, &ColorInputWidget::editingFinished); + + // Connect color picker connect(ui->button_Eyedrop, &QToolButton::clicked, this, &ColorInputWidget::pickColor); setBitDepth(24); @@ -210,5 +224,6 @@ void ColorInputWidget::pickColor() { if (picker.exec() == QDialog::Accepted) { QColor c = picker.getColor(); setColor(c.rgb()); + emit editingFinished(); } } diff --git a/src/ui/paletteeditor.cpp b/src/ui/paletteeditor.cpp index 456d1f99..393f3a6e 100644 --- a/src/ui/paletteeditor.cpp +++ b/src/ui/paletteeditor.cpp @@ -24,6 +24,7 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset for (int i = 0; i < this->numColors; i++) { auto colorInput = new ColorInputWidget(QString("Color %1").arg(i)); connect(colorInput, &ColorInputWidget::colorChanged, [this, i](QRgb color) { setRgb(i, color); }); + connect(colorInput, &ColorInputWidget::editingFinished, [this] { commitEditHistory(); }); this->colorInputs.append(colorInput); ui->layout_Colors->addWidget(colorInput, i / numColorsPerRow, i % numColorsPerRow); } @@ -46,7 +47,7 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset connect(this->ui->bit_depth_24, &QRadioButton::toggled, [this](bool checked){ if (checked) this->setBitDepth(24); }); this->setPaletteId(paletteId); - this->commitEditHistory(this->ui->spinBox_PaletteId->value()); + this->commitEditHistory(); this->restoreWindowState(); } @@ -75,8 +76,7 @@ void PaletteEditor::setRgb(int colorIndex, QRgb rgb) { Tileset *tileset = getTileset(paletteId); tileset->palettes[paletteId][colorIndex] = rgb; tileset->palettePreviews[paletteId][colorIndex] = rgb; - - commitEditHistory(paletteId); + emit changedPaletteColor(); } @@ -120,6 +120,10 @@ void PaletteEditor::on_spinBox_PaletteId_valueChanged(int paletteId) { emit this->changedPalette(paletteId); } +void PaletteEditor::commitEditHistory() { + commitEditHistory(ui->spinBox_PaletteId->value()); +} + void PaletteEditor::commitEditHistory(int paletteId) { QList colors; for (int i = 0; i < this->numColors; i++) {