From 9f06dcf9ace607e5dd2077963f07dd068da7bee1 Mon Sep 17 00:00:00 2001 From: vinnydiehl Date: Thu, 11 May 2023 23:55:26 -0400 Subject: [PATCH 01/34] Include `cstdint` in `lexer.h` Build was failing due to missing `uint32_t` type. --- include/lib/fex/lexer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/lib/fex/lexer.h b/include/lib/fex/lexer.h index b888e86b4..9b22976d8 100644 --- a/include/lib/fex/lexer.h +++ b/include/lib/fex/lexer.h @@ -1,6 +1,7 @@ #ifndef INCLUDE_CORE_LEXER_H #define INCLUDE_CORE_LEXER_H +#include #include #include From 4ec5238abbec211e9308f1c033607af191d0155e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 29 May 2023 19:18:38 -0400 Subject: [PATCH 02/34] Fix deleting connections by clearing text --- CHANGELOG.md | 1 + src/mainwindow.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 781f63f28..0ee96b8d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ### Fixed - Fix text boxes in the Palette Editor calculating color incorrectly. - Fix default object sprites retaining dimensions and transparency of the previous sprite. +- Fix connections not being deleted when the map name text box is cleared. ## [5.1.1] - 2023-02-20 ### Added diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 519ec32b9..4775d15b1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2490,7 +2490,7 @@ void MainWindow::on_spinBox_ConnectionOffset_valueChanged(int offset) void MainWindow::on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName) { - if (editor->project->mapNames.contains(mapName)) { + if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { editor->setConnectionMap(mapName); markMapEdited(); } @@ -2522,7 +2522,7 @@ void MainWindow::on_pushButton_ConfigureEncountersJSON_clicked() { void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) { - if (editor->project->mapNames.contains(mapName)) { + if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { editor->updateDiveMap(mapName); markMapEdited(); } @@ -2530,7 +2530,7 @@ void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName) { - if (editor->project->mapNames.contains(mapName)) { + if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) { editor->updateEmergeMap(mapName); markMapEdited(); } From cdf4556e23977589548ef4d427cbc310e9bca81e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 30 Jun 2023 00:51:18 -0400 Subject: [PATCH 03/34] Fix border not updating when tileset is changed --- CHANGELOG.md | 1 + src/editor.cpp | 2 ++ src/mainwindow.cpp | 4 +--- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ee96b8d2..914008209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix text boxes in the Palette Editor calculating color incorrectly. - Fix default object sprites retaining dimensions and transparency of the previous sprite. - Fix connections not being deleted when the map name text box is cleared. +- Fix the map border not updating when a tileset is changed. ## [5.1.1] - 2023-02-20 ### Added diff --git a/src/editor.cpp b/src/editor.cpp index 76124324a..23234b871 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1918,6 +1918,7 @@ void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) { map->layout->tileset_primary_label = tilesetLabel; map->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad); + map->clearBorderCache(); } } @@ -1927,6 +1928,7 @@ void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad) { map->layout->tileset_secondary_label = tilesetLabel; map->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad); + map->clearBorderCache(); } } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4775d15b1..52f210aad 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2385,10 +2385,8 @@ void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryT } else { this->editor->project->getTileset(secondaryTilesetLabel, true); } - if (updated) { - this->editor->map->clearBorderCache(); + if (updated) redrawMapScene(); - } } void MainWindow::onWildMonDataChanged() { From ff6a51ffa4855a35d01dc43f37085d420c66ae3a Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 16 Jun 2023 04:39:32 -0700 Subject: [PATCH 04/34] Support 8BPP tileset tile images --- CHANGELOG.md | 3 +++ include/core/tileset.h | 2 ++ include/ui/imageproviders.h | 1 + include/ui/tilemaptileselector.h | 6 ++---- src/core/tileset.cpp | 3 ++- src/mainwindow.cpp | 3 ++- src/project.cpp | 12 ++++++++++-- src/ui/imageproviders.cpp | 9 +++++++++ src/ui/tileseteditor.cpp | 28 ++++++++++------------------ 9 files changed, 41 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ee96b8d2..6ae18d8c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project somewhat adheres to [Semantic Versioning](https://semver.org/sp The **"Breaking Changes"** listed below are changes that have been made in the decompilation projects (e.g. pokeemerald), which porymap requires in order to work properly. It also includes changes to the scripting API that may change the behavior of existing porymap scripts. If porymap is used with a project or API script that is not up-to-date with the breaking changes, then porymap will likely break or behave improperly. ## [Unreleased] +### Added +- Support for 8BPP tileset tile images. + ### Changed - The Palette Editor now remembers the Bit Depth setting. diff --git a/include/core/tileset.h b/include/core/tileset.h index 3f50f41bd..b120b2c5a 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -38,6 +38,8 @@ class Tileset QList> palettes; QList> palettePreviews; + bool hasUnsavedTilesImage; + static Tileset* getMetatileTileset(int, Tileset*, Tileset*); static Tileset* getTileTileset(int, Tileset*, Tileset*); static Metatile* getMetatile(int, Tileset*, Tileset*); diff --git a/include/ui/imageproviders.h b/include/ui/imageproviders.h index db04bdb2b..fefa5546e 100644 --- a/include/ui/imageproviders.h +++ b/include/ui/imageproviders.h @@ -13,6 +13,7 @@ QImage getMetatileImage(Metatile*, Tileset*, Tileset*, QList, QList, QImage getTileImage(uint16_t, Tileset*, Tileset*); QImage getPalettedTileImage(uint16_t, Tileset*, Tileset*, int, bool useTruePalettes = false); QImage getGreyscaleTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset); +void flattenTo4bppImage(QImage * image); static QList greyscalePalette({ qRgb(0, 0, 0), diff --git a/include/ui/tilemaptileselector.h b/include/ui/tilemaptileselector.h index 9d419d63a..867f63024 100644 --- a/include/ui/tilemaptileselector.h +++ b/include/ui/tilemaptileselector.h @@ -4,6 +4,7 @@ #include "selectablepixmapitem.h" #include "paletteutil.h" +#include "imageproviders.h" #include using std::shared_ptr; @@ -127,10 +128,7 @@ class TilemapTileSelector: public SelectablePixmapItem { this->tileset = QImage(tilesetFilepath); this->format = format; if (this->tileset.format() == QImage::Format::Format_Indexed8 && this->format == TilemapFormat::BPP_4) { - // Squash pixel data to fit 4BPP. Allows project repo to use 8BPP images for 4BPP tilemaps - uchar * pixel = this->tileset.bits(); - for (int i = 0; i < this->tileset.sizeInBytes(); i++, pixel++) - *pixel %= 16; + flattenTo4bppImage(&this->tileset); } bool err; if (!palFilepath.isEmpty()) { diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index 4809ba6da..31d623d5a 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -22,7 +22,8 @@ Tileset::Tileset(const Tileset &other) palettePaths(other.palettePaths), metatileLabels(other.metatileLabels), palettes(other.palettes), - palettePreviews(other.palettePreviews) + palettePreviews(other.palettePreviews), + hasUnsavedTilesImage(false) { for (auto tile : other.tiles) { tiles.append(tile.copy()); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4775d15b1..36c5b8024 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -18,6 +18,7 @@ #include "mapparser.h" #include "prefab.h" #include "montabwidget.h" +#include "imageexport.h" #include #include @@ -1280,7 +1281,7 @@ void MainWindow::on_actionNew_Tileset_triggered() { } newSet.palettes[0][1] = qRgb(255,0,255); newSet.palettePreviews[0][1] = qRgb(255,0,255); - editor->project->saveTilesetTilesImage(&newSet); + exportIndexed4BPPPng(newSet.tilesImage, newSet.tilesImagePath); editor->project->saveTilesetMetatiles(&newSet); editor->project->saveTilesetMetatileAttributes(&newSet); editor->project->saveTilesetPalettes(&newSet); diff --git a/src/project.cpp b/src/project.cpp index b0e3d43ce..92a71e2ff 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -6,7 +6,6 @@ #include "paletteutil.h" #include "tile.h" #include "tileset.h" -#include "imageexport.h" #include "map.h" #include "orderedjson.h" @@ -1008,7 +1007,15 @@ void Project::saveTilesetMetatiles(Tileset *tileset) { } void Project::saveTilesetTilesImage(Tileset *tileset) { - exportIndexed4BPPPng(tileset->tilesImage, tileset->tilesImagePath); + // Only write the tiles image if it was changed. + // Porymap will only ever change an existing tiles image by importing a new one. + if (tileset->hasUnsavedTilesImage) { + if (!tileset->tilesImage.save(tileset->tilesImagePath, "PNG")) { + logError(QString("Failed to save tiles image '%1'").arg(tileset->tilesImagePath)); + return; + } + tileset->hasUnsavedTilesImage = false; + } } void Project::saveTilesetPalettes(Tileset *tileset) { @@ -1350,6 +1357,7 @@ void Project::loadTilesetAssets(Tileset* tileset) { QImage image; if (QFile::exists(tileset->tilesImagePath)) { image = QImage(tileset->tilesImagePath).convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither); + flattenTo4bppImage(&image); } else { image = QImage(8, 8, QImage::Format_Indexed8); } diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index 838f4db76..891cfbba6 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -169,3 +169,12 @@ QImage getPalettedTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *s QImage getGreyscaleTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset) { return getColoredTileImage(tileId, primaryTileset, secondaryTileset, greyscalePalette); } + +// gbagfx allows 4bpp image data to be represented with 8bpp .png files by considering only the lower 4 bits of each pixel. +// Reproduce that here to support this type of image use. +void flattenTo4bppImage(QImage * image) { + if (!image) return; + uchar * pixel = image->bits(); + for (int i = 0; i < image->sizeInBytes(); i++, pixel++) + *pixel %= 16; +} diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index c16aeaf40..d8a9b740a 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -701,15 +701,6 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) { msgBox.setIcon(QMessageBox::Icon::Critical); msgBox.exec(); return; - } else if (palette.length() != 16) { - QMessageBox msgBox(this); - msgBox.setText("Failed to import palette."); - QString message = QString("The palette must have exactly 16 colors, but it has %1.").arg(palette.length()); - msgBox.setInformativeText(message); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.setIcon(QMessageBox::Icon::Critical); - msgBox.exec(); - return; } QVector colorTable = palette.toVector(); @@ -717,20 +708,21 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) { } // Validate image is properly indexed to 16 colors. - if (image.colorCount() != 16) { - QMessageBox msgBox(this); - msgBox.setText("Failed to import tiles."); - msgBox.setInformativeText(QString("The image must be indexed and contain 16 total colors, or it must be un-indexed. The provided image has %1 indexed colors.") - .arg(image.colorCount())); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.setIcon(QMessageBox::Icon::Critical); - msgBox.exec(); - return; + int colorCount = image.colorCount(); + if (colorCount > 16) { + flattenTo4bppImage(&image); + } else if (colorCount < 16) { + QVector colorTable = image.colorTable(); + for (int i = colorTable.length(); i < 16; i++) { + colorTable.append(Qt::black); + } + image.setColorTable(colorTable); } this->project->loadTilesetTiles(tileset, image); this->refresh(); this->hasUnsavedChanges = true; + tileset->hasUnsavedTilesImage = true; } void TilesetEditor::closeEvent(QCloseEvent *event) From 0b293d2af043c352a5f49b5a7e4ff40c98bc19fe Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 28 Feb 2023 14:45:38 -0500 Subject: [PATCH 05/34] Stop tileset editor from scrolling to map's selection when saving --- CHANGELOG.md | 1 + include/ui/tileseteditor.h | 1 + src/ui/tileseteditor.cpp | 12 ++++++------ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 914008209..23bfb9b33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix default object sprites retaining dimensions and transparency of the previous sprite. - Fix connections not being deleted when the map name text box is cleared. - Fix the map border not updating when a tileset is changed. +- Stop the Tileset Editor from scrolling to the initially selected metatile when saving. ## [5.1.1] - 2023-02-20 ### Added diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index b03964b51..09a828c3a 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -164,6 +164,7 @@ private slots: QGraphicsScene *selectedTileScene = nullptr; QGraphicsPixmapItem *selectedTilePixmapItem = nullptr; QGraphicsScene *metatileLayersScene = nullptr; + bool lockSelection = false; signals: void tilesetsSaved(QString, QString); diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index c16aeaf40..9240d0d16 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -68,7 +68,8 @@ void TilesetEditor::updateTilesets(QString primaryTilesetLabel, QString secondar } bool TilesetEditor::selectMetatile(uint16_t metatileId) { - if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) return false; + if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset) || this->lockSelection) + return false; this->metatileSelector->select(metatileId); QPoint pos = this->metatileSelector->getMetatileIdCoordsOnWidget(metatileId); this->ui->scrollArea_Metatiles->ensureVisible(pos.x(), pos.y()); @@ -592,18 +593,17 @@ void TilesetEditor::on_comboBox_terrainType_activated(int terrainType) void TilesetEditor::on_actionSave_Tileset_triggered() { - // need this temporary metatile ID to reset selection after saving - // when the tilesetsSaved signal is sent, it will be reset to the current map metatile - uint16_t reselectMetatileID = this->metatileSelector->getSelectedMetatileId(); - + // Need this temporary flag to stop selection resetting after saving. + // This is a workaround; redrawing the map's metatile selector shouldn't emit the same signal as when it's selected. + this->lockSelection = true; this->project->saveTilesets(this->primaryTileset, this->secondaryTileset); emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name); - this->metatileSelector->select(reselectMetatileID); if (this->paletteEditor) { this->paletteEditor->setTilesets(this->primaryTileset, this->secondaryTileset); } this->ui->statusbar->showMessage(QString("Saved primary and secondary Tilesets!"), 5000); this->hasUnsavedChanges = false; + this->lockSelection = false; } void TilesetEditor::on_actionImport_Primary_Tiles_triggered() From 1ecb2cc3698872491903c037df51343bf0c79085 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 31 Jul 2023 14:55:53 -0400 Subject: [PATCH 06/34] Automatically adjust min/max encounter levels --- CHANGELOG.md | 1 + src/ui/encountertabledelegates.cpp | 6 +----- src/ui/encountertablemodel.cpp | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23bfb9b33..6de13cb4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ## [Unreleased] ### Changed - The Palette Editor now remembers the Bit Depth setting. +- The min/max levels on the Wild Pokémon tab will now adjust automatically if they invalidate each other. ### Fixed - Fix text boxes in the Palette Editor calculating color incorrectly. diff --git a/src/ui/encountertabledelegates.cpp b/src/ui/encountertabledelegates.cpp index c381fcae2..44229822c 100644 --- a/src/ui/encountertabledelegates.cpp +++ b/src/ui/encountertabledelegates.cpp @@ -61,12 +61,8 @@ QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewIt editor->setFrame(false); int col = index.column(); - if (col == EncounterTableModel::ColumnType::MinLevel) { + if (col == EncounterTableModel::ColumnType::MinLevel || col == EncounterTableModel::ColumnType::MaxLevel) { editor->setMinimum(this->project->miscConstants.value("min_level_define").toInt()); - editor->setMaximum(index.siblingAtColumn(EncounterTableModel::ColumnType::MaxLevel).data(Qt::EditRole).toInt()); - } - else if (col == EncounterTableModel::ColumnType::MaxLevel) { - editor->setMinimum(index.siblingAtColumn(EncounterTableModel::ColumnType::MinLevel).data(Qt::EditRole).toInt()); editor->setMaximum(this->project->miscConstants.value("max_level_define").toInt()); } else if (col == EncounterTableModel::ColumnType::EncounterRate) { diff --git a/src/ui/encountertablemodel.cpp b/src/ui/encountertablemodel.cpp index 51658ff7a..b38529af2 100644 --- a/src/ui/encountertablemodel.cpp +++ b/src/ui/encountertablemodel.cpp @@ -155,13 +155,21 @@ bool EncounterTableModel::setData(const QModelIndex &index, const QVariant &valu this->monInfo.wildPokemon[row].species = value.toString(); break; - case ColumnType::MinLevel: - this->monInfo.wildPokemon[row].minLevel = value.toInt(); + case ColumnType::MinLevel: { + int minLevel = value.toInt(); + this->monInfo.wildPokemon[row].minLevel = minLevel; + if (minLevel > this->monInfo.wildPokemon[row].maxLevel) + this->monInfo.wildPokemon[row].maxLevel = minLevel; break; + } - case ColumnType::MaxLevel: - this->monInfo.wildPokemon[row].maxLevel = value.toInt(); + case ColumnType::MaxLevel: { + int maxLevel = value.toInt(); + this->monInfo.wildPokemon[row].maxLevel = maxLevel; + if (maxLevel < this->monInfo.wildPokemon[row].minLevel) + this->monInfo.wildPokemon[row].minLevel = maxLevel; break; + } case ColumnType::EncounterRate: this->monInfo.encounterRate = value.toInt(); From a366c7cffe263740107e06592b88301c7e0e8cb3 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 9 Aug 2023 14:42:03 -0400 Subject: [PATCH 07/34] Stop misleading error when recent project doesn't exist --- CHANGELOG.md | 1 + src/mainwindow.cpp | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6de13cb4e..4cc36103b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ### Changed - The Palette Editor now remembers the Bit Depth setting. - The min/max levels on the Wild Pokémon tab will now adjust automatically if they invalidate each other. +- If the recent project directory doesn't exist Porymap will open an empty project instead of failing with a misleading error message. ### Fixed - Fix text boxes in the Palette Editor calculating color incorrectly. diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 52f210aad..c9aad46e6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -483,12 +483,18 @@ bool MainWindow::openRecentProject() { return false; QString default_dir = porymapConfig.getRecentProject(); - if (!default_dir.isNull() && default_dir.length() > 0) { - logInfo(QString("Opening recent project: '%1'").arg(default_dir)); - return openProject(default_dir); + if (default_dir.isNull() || default_dir.length() <= 0) + return false; + + if (!QDir(default_dir).exists()) { + QString message = QString("Recent project directory '%1' doesn't exist.").arg(QDir::toNativeSeparators(default_dir)); + logWarn(message); + this->statusBar()->showMessage(message); + return false; } - return false; + logInfo(QString("Opening recent project: '%1'").arg(default_dir)); + return openProject(default_dir); } bool MainWindow::openProject(QString dir) { From ae68ab3a6fee00b1030bb792077941499045bb08 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sat, 19 Aug 2023 00:06:21 -0400 Subject: [PATCH 08/34] Stop single tile mode on prefab tab --- CHANGELOG.md | 1 + src/mainwindow.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62d2b68ec..febe1cacd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix connections not being deleted when the map name text box is cleared. - Fix the map border not updating when a tileset is changed. - Stop the Tileset Editor from scrolling to the initially selected metatile when saving. +- Fix the selection outline sticking in single-tile mode on the Prefab tab. ## [5.1.1] - 2023-02-20 ### Added diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 02ea47d39..707e647f9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2206,7 +2206,7 @@ void MainWindow::on_toolButton_Paint_clicked() editor->settings->mapCursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10); // do not stop single tile mode when editing collision - if (ui->mapViewTab->currentIndex() == 0) + if (ui->mapViewTab->currentIndex() != 1) editor->cursorMapTileRect->stopSingleTileMode(); ui->graphicsView_Map->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); From 4d8f5ef150ef463858fb53374be341244bfdfcde Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 23 Aug 2023 02:32:32 -0400 Subject: [PATCH 09/34] Add project settings window --- forms/mainwindow.ui | 6 + forms/projectsettingseditor.ui | 486 +++++++++++++++++++++++++++++ forms/tileseteditor.ui | 6 +- include/config.h | 4 + include/mainwindow.h | 3 + include/ui/noscrollcombobox.h | 2 + include/ui/projectsettingseditor.h | 41 +++ include/ui/tileseteditor.h | 1 - porymap.pro | 5 +- src/config.cpp | 52 ++- src/mainwindow.cpp | 17 + src/ui/noscrollcombobox.cpp | 27 +- src/ui/projectsettingseditor.cpp | 177 +++++++++++ src/ui/tileseteditor.cpp | 29 +- 14 files changed, 809 insertions(+), 47 deletions(-) create mode 100644 forms/projectsettingseditor.ui create mode 100644 include/ui/projectsettingseditor.h create mode 100644 src/ui/projectsettingseditor.cpp diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 52772b99d..d9e19dcc8 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -3017,6 +3017,7 @@ + @@ -3326,6 +3327,11 @@ Import Map from Advance Map 1.92... + + + Edit Project Settings... + + diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui new file mode 100644 index 000000000..442291dc2 --- /dev/null +++ b/forms/projectsettingseditor.ui @@ -0,0 +1,486 @@ + + + ProjectSettingsEditor + + + + 0 + 0 + 570 + 1041 + + + + Project Settings + + + + + 9 + + + + + true + + + + + 0 + 0 + 544 + 994 + + + + + + + User config + + + + + + + + + Use Poryscript + + + + + + + Show Wild Encounter Tables + + + + + + + + + + Default Tilesets + + + + + + + New Map Defaults + + + + + + The default metatile value that will be used to fill new maps + + + Fill Metatile + + + + + + + The default elevation that will be used to fill new maps + + + Elevation + + + + + + + A comma-separated list of metatile values that will be used to fill new map borders + + + Border Metatiles + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Whether a separate text.inc or text.pory file will be created for new maps, alongside the scripts file + + + Create separate text file + + + + + + + + + + Prefabs + + + + + + Prefabs Path + + + + + + + Prefab import prompted + + + + + + + + + + + + + Qt::Horizontal + + + + + + + + 12 + 75 + true + + + + <html><head/><body><p><span style=" font-size:13pt; color:#d7000c;">WARNING: </span><span style=" font-weight:400;">The settings from this point below require project changes to function properly. Do not modify these settings without the necessary changes. </span></p></body></html> + + + true + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Tilesets / Metatiles + + + + + + The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. + + + Behavior mask + + + + + + + The number of bytes used per metatile for metatile attributes + + + Attributes size (in bytes) + + + + + + + The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. + + + Layer Type mask + + + + + + + The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. + + + Terrain Type mask + + + + + + + Enable Triple Layer Metatiles + + + + + + + Qt::Vertical + + + + 20 + 15 + + + + + + + + + + + + + + The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. + + + Encounter Type mask + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Whether the C data outputted for new tilesets will include the "callback" field + + + Output 'callback' field + + + + + + + Whether the C data outputted for new tilesets will include the "isCompressed" field + + + Output 'isCompressed' field + + + + + + + + + + Events + + + + + + Enable 'Requires Itemfinder' for Hidden Items + + + + + + + Enable 'Quantity' for Hidden Items + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Enable Secret Bases + + + + + + + Enable Weather Triggers + + + + + + + Enable Clone Objects + + + + + + + Enable 'Respawn Map/NPC' for Heal Locations + + + + + + + + + + Maps + + + + + + Whether "Allow Running", "Allow Biking" and "Allow Dig & Escape Rope" are default options for Map Headers + + + Enable 'Allow Running/Biking/Escaping' + + + + + + + Whether "Floor Number" is a default option for Map Headers + + + Enable 'Floor Number' + + + + + + + Whether the dimensions of the border can be changed. If not set, all borders are 2x2 + + + Enable Custom Border Size + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + + + + + + + + + diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index df04f720a..36e475124 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -289,7 +289,7 @@ - + @@ -299,10 +299,10 @@ - + - + diff --git a/include/config.h b/include/config.h index e99b535c7..cb927caa2 100644 --- a/include/config.h +++ b/include/config.h @@ -225,6 +225,7 @@ class ProjectConfig: public KeyValueConfigBase this->filePaths.clear(); this->readKeys.clear(); } + static const QStringList baseGameVersions; void setBaseGameVersion(BaseGameVersion baseGameVersion); BaseGameVersion getBaseGameVersion(); QString getBaseGameVersionString(); @@ -256,10 +257,12 @@ class ProjectConfig: public KeyValueConfigBase int getNumTilesInMetatile(); void setNewMapMetatileId(int metatileId); int getNewMapMetatileId(); + QString getNewMapMetatileIdString(); void setNewMapElevation(int elevation); int getNewMapElevation(); void setNewMapBorderMetatileIds(QList metatileIds); QList getNewMapBorderMetatileIds(); + QString getNewMapBorderMetatileIdsString(); QString getDefaultPrimaryTileset(); QString getDefaultSecondaryTileset(); void setFilePath(ProjectFilePath pathId, QString path); @@ -277,6 +280,7 @@ class ProjectConfig: public KeyValueConfigBase uint32_t getMetatileTerrainTypeMask(); uint32_t getMetatileEncounterTypeMask(); uint32_t getMetatileLayerTypeMask(); + static QString getMaskString(uint32_t mask); bool getMapAllowFlagsEnabled(); protected: virtual QString getConfigFilepath() override; diff --git a/include/mainwindow.h b/include/mainwindow.h index 87ea30aa5..c6c30b42e 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -25,6 +25,7 @@ #include "newtilesetdialog.h" #include "shortcutseditor.h" #include "preferenceeditor.h" +#include "projectsettingseditor.h" @@ -286,6 +287,7 @@ private slots: void on_actionRegion_Map_Editor_triggered(); void on_actionEdit_Preferences_triggered(); void togglePreferenceSpecificUi(); + void on_actionEdit_Project_Settings_triggered(); public: Ui::MainWindow *ui; @@ -299,6 +301,7 @@ private slots: QPointer mapImageExporter = nullptr; QPointer newMapPrompt = nullptr; QPointer preferenceEditor = nullptr; + QPointer projectSettingsEditor = nullptr; FilterChildrenProxyModel *mapListProxyModel; QStandardItemModel *mapListModel; QList *mapGroupItemsList; diff --git a/include/ui/noscrollcombobox.h b/include/ui/noscrollcombobox.h index 5f4d73e7b..98cacf704 100644 --- a/include/ui/noscrollcombobox.h +++ b/include/ui/noscrollcombobox.h @@ -11,8 +11,10 @@ class NoScrollComboBox : public QComboBox explicit NoScrollComboBox(QWidget *parent = nullptr); void wheelEvent(QWheelEvent *event); void setTextItem(const QString &text); + void setNumberItem(int value); private: + void setItem(int index, const QString &text); }; #endif // NOSCROLLCOMBOBOX_H diff --git a/include/ui/projectsettingseditor.h b/include/ui/projectsettingseditor.h new file mode 100644 index 000000000..16b28b0b2 --- /dev/null +++ b/include/ui/projectsettingseditor.h @@ -0,0 +1,41 @@ +#ifndef PROJECTSETTINGSEDITOR_H +#define PROJECTSETTINGSEDITOR_H + +#include +#include "project.h" + +class NoScrollComboBox; +class QAbstractButton; + + +namespace Ui { +class ProjectSettingsEditor; +} + +class ProjectSettingsEditor : public QMainWindow +{ + Q_OBJECT + +public: + explicit ProjectSettingsEditor(QWidget *parent = nullptr, Project *project = nullptr); + ~ProjectSettingsEditor(); + +signals: + void saved(); + +private: + Ui::ProjectSettingsEditor *ui; + Project *project; + NoScrollComboBox *combo_defaultPrimaryTileset; + NoScrollComboBox *combo_defaultSecondaryTileset; + NoScrollComboBox *combo_baseGameVersion; + NoScrollComboBox *combo_attributesSize; + + void initUi(); + void saveFields(); + +private slots: + void dialogButtonClicked(QAbstractButton *button); +}; + +#endif // PROJECTSETTINGSEDITOR_H diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 09a828c3a..204a0c5fb 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -138,7 +138,6 @@ private slots: void copyMetatile(bool cut); void pasteMetatile(const Metatile * toPaste, QString label); bool replaceMetatile(uint16_t metatileId, const Metatile * src, QString label); - void setComboValue(QComboBox * combo, int value); void commitMetatileChange(Metatile * prevMetatile); void commitMetatileAndLabelChange(Metatile * prevMetatile, QString prevLabel); diff --git a/porymap.pro b/porymap.pro index 8d2d0ba4b..4728f1779 100644 --- a/porymap.pro +++ b/porymap.pro @@ -49,6 +49,7 @@ SOURCES += src/core/block.cpp \ src/ui/currentselectedmetatilespixmapitem.cpp \ src/ui/overlay.cpp \ src/ui/prefab.cpp \ + src/ui/projectsettingseditor.cpp \ src/ui/regionmaplayoutpixmapitem.cpp \ src/ui/regionmapentriespixmapitem.cpp \ src/ui/cursortilerect.cpp \ @@ -134,6 +135,7 @@ HEADERS += include/core/block.h \ include/ui/connectionpixmapitem.h \ include/ui/currentselectedmetatilespixmapitem.h \ include/ui/prefabframe.h \ + include/ui/projectsettingseditor.h \ include/ui/regionmaplayoutpixmapitem.h \ include/ui/regionmapentriespixmapitem.h \ include/ui/cursortilerect.h \ @@ -201,7 +203,8 @@ FORMS += forms/mainwindow.ui \ forms/shortcutseditor.ui \ forms/preferenceeditor.ui \ forms/regionmappropertiesdialog.ui \ - forms/colorpicker.ui + forms/colorpicker.ui \ + forms/projectsettingseditor.ui RESOURCES += \ resources/images.qrc \ diff --git a/src/config.cpp b/src/config.cpp index 7ece2555f..9419a7b44 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -513,16 +513,22 @@ int PorymapConfig::getPaletteEditorBitDepth() { return this->paletteEditorBitDepth; } +const QStringList ProjectConfig::baseGameVersions = { + "pokeruby", + "pokefirered", + "pokeemerald", +}; + const QMap baseGameVersionMap = { - {BaseGameVersion::pokeruby, "pokeruby"}, - {BaseGameVersion::pokefirered, "pokefirered"}, - {BaseGameVersion::pokeemerald, "pokeemerald"}, + {BaseGameVersion::pokeruby, ProjectConfig::baseGameVersions[0]}, + {BaseGameVersion::pokefirered, ProjectConfig::baseGameVersions[1]}, + {BaseGameVersion::pokeemerald, ProjectConfig::baseGameVersions[2]}, }; const QMap baseGameVersionReverseMap = { - {"pokeruby", BaseGameVersion::pokeruby}, - {"pokefirered", BaseGameVersion::pokefirered}, - {"pokeemerald", BaseGameVersion::pokeemerald}, + {ProjectConfig::baseGameVersions[0], BaseGameVersion::pokeruby}, + {ProjectConfig::baseGameVersions[1], BaseGameVersion::pokefirered}, + {ProjectConfig::baseGameVersions[2], BaseGameVersion::pokeemerald}, }; ProjectConfig projectConfig; @@ -578,6 +584,7 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { int metatileId = getConfigInteger(key, metatileIds.at(i), 0, 1023, 0); this->newMapBorderMetatileIds.append(metatileId); } + // TODO: If insufficient metatiles are provided, it should loop the provided metatiles instead. for (; i < maxSize; i++) { // Set any metatiles not provided to 0 this->newMapBorderMetatileIds.append(0); @@ -657,7 +664,7 @@ void ProjectConfig::setUnreadKeys() { if (!readKeys.contains("metatile_behavior_mask")) this->metatileBehaviorMask = Metatile::getBehaviorMask(this->baseGameVersion); if (!readKeys.contains("metatile_terrain_type_mask")) this->metatileTerrainTypeMask = Metatile::getTerrainTypeMask(this->baseGameVersion); if (!readKeys.contains("metatile_encounter_type_mask")) this->metatileEncounterTypeMask = Metatile::getEncounterTypeMask(this->baseGameVersion); - if (!readKeys.contains("metatile_layer_type_mask")) this-> metatileLayerTypeMask = Metatile::getLayerTypeMask(this->baseGameVersion); + if (!readKeys.contains("metatile_layer_type_mask")) this->metatileLayerTypeMask = Metatile::getLayerTypeMask(this->baseGameVersion); if (!readKeys.contains("enable_map_allow_flags")) this->enableMapAllowFlags = (this->baseGameVersion != BaseGameVersion::pokeruby); } @@ -675,12 +682,9 @@ QMap ProjectConfig::getKeyValueMap() { map.insert("enable_floor_number", QString::number(this->enableFloorNumber)); map.insert("create_map_text_file", QString::number(this->createMapTextFile)); map.insert("enable_triple_layer_metatiles", QString::number(this->enableTripleLayerMetatiles)); - map.insert("new_map_metatile", QString::number(this->newMapMetatileId)); + map.insert("new_map_metatile", this->getNewMapMetatileIdString()); map.insert("new_map_elevation", QString::number(this->newMapElevation)); - QStringList metatiles; - for (auto metatile : this->newMapBorderMetatileIds) - metatiles << QString::number(metatile); - map.insert("new_map_border_metatiles", metatiles.join(",")); + map.insert("new_map_border_metatiles", this->getNewMapBorderMetatileIdsString()); map.insert("default_primary_tileset", this->defaultPrimaryTileset); map.insert("default_secondary_tileset", this->defaultSecondaryTileset); map.insert("prefabs_filepath", this->prefabFilepath); @@ -691,10 +695,10 @@ QMap ProjectConfig::getKeyValueMap() { map.insert("tilesets_have_callback", QString::number(this->tilesetsHaveCallback)); map.insert("tilesets_have_is_compressed", QString::number(this->tilesetsHaveIsCompressed)); map.insert("metatile_attributes_size", QString::number(this->metatileAttributesSize)); - map.insert("metatile_behavior_mask", "0x" + QString::number(this->metatileBehaviorMask, 16).toUpper()); - map.insert("metatile_terrain_type_mask", "0x" + QString::number(this->metatileTerrainTypeMask, 16).toUpper()); - map.insert("metatile_encounter_type_mask", "0x" + QString::number(this->metatileEncounterTypeMask, 16).toUpper()); - map.insert("metatile_layer_type_mask", "0x" + QString::number(this->metatileLayerTypeMask, 16).toUpper()); + map.insert("metatile_behavior_mask", getMaskString(this->metatileBehaviorMask)); + map.insert("metatile_terrain_type_mask", getMaskString(this->metatileTerrainTypeMask)); + map.insert("metatile_encounter_type_mask", getMaskString(this->metatileEncounterTypeMask)); + map.insert("metatile_layer_type_mask", getMaskString(this->metatileLayerTypeMask)); map.insert("enable_map_allow_flags", QString::number(this->enableMapAllowFlags)); return map; } @@ -880,6 +884,10 @@ int ProjectConfig::getNewMapMetatileId() { return this->newMapMetatileId; } +QString ProjectConfig::getNewMapMetatileIdString() { + return "0x" + QString::number(this->newMapMetatileId, 16).toUpper(); +} + void ProjectConfig::setNewMapElevation(int elevation) { this->newMapElevation = elevation; this->save(); @@ -898,6 +906,14 @@ QList ProjectConfig::getNewMapBorderMetatileIds() { return this->newMapBorderMetatileIds; } +QString ProjectConfig::getNewMapBorderMetatileIdsString() { + QStringList metatiles; + for (auto metatileId : this->newMapBorderMetatileIds){ + metatiles << ("0x" + QString::number(metatileId, 16).toUpper()); + } + return metatiles.join(","); +} + QString ProjectConfig::getDefaultPrimaryTileset() { return this->defaultPrimaryTileset; } @@ -965,6 +981,10 @@ uint32_t ProjectConfig::getMetatileLayerTypeMask() { return this->metatileLayerTypeMask; } +QString ProjectConfig::getMaskString(uint32_t mask) { + return "0x" + QString::number(mask, 16).toUpper(); +} + bool ProjectConfig::getMapAllowFlagsEnabled() { return this->enableMapAllowFlags; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index aa5c5296c..9ceb9b94b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2751,6 +2751,23 @@ void MainWindow::togglePreferenceSpecificUi() { ui->actionOpen_Project_in_Text_Editor->setEnabled(true); } +void MainWindow::on_actionEdit_Project_Settings_triggered() { + if (!this->projectSettingsEditor) { + this->projectSettingsEditor = new ProjectSettingsEditor(this, this->editor->project); + connect(this->projectSettingsEditor, &ProjectSettingsEditor::saved, + this, &MainWindow::togglePreferenceSpecificUi); + } + + if (!this->projectSettingsEditor->isVisible()) { + this->projectSettingsEditor->show(); + } else if (this->projectSettingsEditor->isMinimized()) { + this->projectSettingsEditor->showNormal(); + } else { + this->projectSettingsEditor->raise(); + this->projectSettingsEditor->activateWindow(); + } +} + void MainWindow::on_pushButton_AddCustomHeaderField_clicked() { bool ok; diff --git a/src/ui/noscrollcombobox.cpp b/src/ui/noscrollcombobox.cpp index f0e89e4cd..ecf2ba3ae 100644 --- a/src/ui/noscrollcombobox.cpp +++ b/src/ui/noscrollcombobox.cpp @@ -29,11 +29,30 @@ void NoScrollComboBox::wheelEvent(QWheelEvent *event) QComboBox::wheelEvent(event); } -void NoScrollComboBox::setTextItem(const QString &text) +void NoScrollComboBox::setItem(int index, const QString &text) { - int index = this->findText(text); - if (index >= 0) + if (index >= 0) { + // Valid item this->setCurrentIndex(index); - else + } else if (this->isEditable()) { + // Invalid item in editable box, just display the text this->setCurrentText(text); + } else { + // Invalid item in uneditable box, display text as placeholder + // On Qt < 5.15 this will display an empty box +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + this->setPlaceholderText(text); +#endif + this->setCurrentIndex(index); + } +} + +void NoScrollComboBox::setTextItem(const QString &text) +{ + this->setItem(this->findText(text), text); +} + +void NoScrollComboBox::setNumberItem(int value) +{ + this->setItem(this->findData(value), QString::number(value)); } diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp new file mode 100644 index 000000000..c6f2ef6af --- /dev/null +++ b/src/ui/projectsettingseditor.cpp @@ -0,0 +1,177 @@ +#include "projectsettingseditor.h" +#include "ui_projectsettingseditor.h" +#include "config.h" +#include "noscrollcombobox.h" + +#include +#include + +/* + Editor for the settings in a user's porymap.project.cfg and porymap.user.cfg files. +*/ + +ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) : + QMainWindow(parent), + ui(new Ui::ProjectSettingsEditor), + project(project), + combo_defaultPrimaryTileset(nullptr), + combo_defaultSecondaryTileset(nullptr), + combo_baseGameVersion(nullptr), + combo_attributesSize(nullptr) +{ + ui->setupUi(this); + initUi(); + setAttribute(Qt::WA_DeleteOnClose); + connect(ui->buttonBox, &QDialogButtonBox::clicked, + this, &ProjectSettingsEditor::dialogButtonClicked); +} + +ProjectSettingsEditor::~ProjectSettingsEditor() +{ + delete ui; +} + +void ProjectSettingsEditor::initUi() { + // Block signals while setting initial UI states + const QSignalBlocker blocker0(combo_defaultPrimaryTileset); + const QSignalBlocker blocker1(combo_defaultSecondaryTileset); + const QSignalBlocker blocker2(combo_baseGameVersion); + const QSignalBlocker blocker3(combo_attributesSize); + const QSignalBlocker blocker4(ui->checkBox_UsePoryscript); + const QSignalBlocker blocker5(ui->checkBox_ShowWildEncounterTables); + const QSignalBlocker blocker6(ui->checkBox_CreateTextFile); + const QSignalBlocker blocker7(ui->checkBox_PrefabImportPrompted); + const QSignalBlocker blocker8(ui->checkBox_EnableTripleLayerMetatiles); + const QSignalBlocker blocker9(ui->checkBox_EnableRequiresItemfinder); + const QSignalBlocker blockerA(ui->checkBox_EnableQuantity); + const QSignalBlocker blockerB(ui->checkBox_EnableCloneObjects); + const QSignalBlocker blockerC(ui->checkBox_EnableWeatherTriggers); + const QSignalBlocker blockerD(ui->checkBox_EnableSecretBases); + const QSignalBlocker blockerE(ui->checkBox_EnableRespawn); + const QSignalBlocker blockerF(ui->checkBox_EnableAllowFlags); + const QSignalBlocker blocker10(ui->checkBox_EnableFloorNumber); + const QSignalBlocker blocker11(ui->checkBox_EnableCustomBorderSize); + const QSignalBlocker blocker12(ui->checkBox_OutputCallback); + const QSignalBlocker blocker13(ui->checkBox_OutputIsCompressed); + const QSignalBlocker blocker14(ui->spinBox_Elevation); + const QSignalBlocker blocker15(ui->lineEdit_BorderMetatiles); + const QSignalBlocker blocker16(ui->lineEdit_FillMetatile); + const QSignalBlocker blocker17(ui->lineEdit_PrefabsPath); + const QSignalBlocker blocker18(ui->lineEdit_BehaviorMask); + const QSignalBlocker blocker19(ui->lineEdit_EncounterTypeMask); + const QSignalBlocker blocker1A(ui->lineEdit_LayerTypeMask); + const QSignalBlocker blocker1B(ui->lineEdit_TerrainTypeMask); + + // Create Default Tilesets combo boxes + auto *defaultTilesetsLayout = new QFormLayout(ui->groupBox_DefaultTilesets); + combo_defaultPrimaryTileset = new NoScrollComboBox(ui->groupBox_DefaultTilesets); + combo_defaultSecondaryTileset = new NoScrollComboBox(ui->groupBox_DefaultTilesets); + if (project) combo_defaultPrimaryTileset->addItems(project->primaryTilesetLabels); + if (project) combo_defaultSecondaryTileset->addItems(project->secondaryTilesetLabels); + combo_defaultPrimaryTileset->setTextItem(projectConfig.getDefaultPrimaryTileset()); + combo_defaultSecondaryTileset->setTextItem(projectConfig.getDefaultSecondaryTileset()); + defaultTilesetsLayout->addRow("Primary Tileset", combo_defaultPrimaryTileset); + defaultTilesetsLayout->addRow("Secondary Tileset", combo_defaultSecondaryTileset); + + // Create Base game version combo box + combo_baseGameVersion = new NoScrollComboBox(ui->widget_BaseGameVersion); + combo_baseGameVersion->addItems(ProjectConfig::baseGameVersions); + combo_baseGameVersion->setTextItem(projectConfig.getBaseGameVersionString()); + combo_baseGameVersion->setEditable(false); + ui->layout_BaseGameVersion->insertRow(0, "Base game version", combo_baseGameVersion); + + // Create Attributes size combo box + auto *attributesSizeLayout = new QFormLayout(ui->widget_SizeDropdown); + combo_attributesSize = new NoScrollComboBox(ui->widget_SizeDropdown); + combo_attributesSize->addItems({"1", "2", "4"}); + combo_attributesSize->setTextItem(QString::number(projectConfig.getMetatileAttributesSize())); + combo_attributesSize->setEditable(false); + attributesSizeLayout->addRow("", combo_attributesSize); + + // Init check boxes + ui->checkBox_UsePoryscript->setChecked(projectConfig.getUsePoryScript()); + ui->checkBox_ShowWildEncounterTables->setChecked(userConfig.getEncounterJsonActive()); + ui->checkBox_CreateTextFile->setChecked(projectConfig.getCreateMapTextFileEnabled()); + ui->checkBox_PrefabImportPrompted->setChecked(projectConfig.getPrefabImportPrompted()); + ui->checkBox_EnableTripleLayerMetatiles->setChecked(projectConfig.getTripleLayerMetatilesEnabled()); + ui->checkBox_EnableRequiresItemfinder->setChecked(projectConfig.getHiddenItemRequiresItemfinderEnabled()); + ui->checkBox_EnableQuantity->setChecked(projectConfig.getHiddenItemQuantityEnabled()); + ui->checkBox_EnableCloneObjects->setChecked(projectConfig.getEventCloneObjectEnabled()); + ui->checkBox_EnableWeatherTriggers->setChecked(projectConfig.getEventWeatherTriggerEnabled()); + ui->checkBox_EnableSecretBases->setChecked(projectConfig.getEventSecretBaseEnabled()); + ui->checkBox_EnableRespawn->setChecked(projectConfig.getHealLocationRespawnDataEnabled()); + ui->checkBox_EnableAllowFlags->setChecked(projectConfig.getMapAllowFlagsEnabled()); + ui->checkBox_EnableFloorNumber->setChecked(projectConfig.getFloorNumberEnabled()); + ui->checkBox_EnableCustomBorderSize->setChecked(projectConfig.getUseCustomBorderSize()); + ui->checkBox_OutputCallback->setChecked(projectConfig.getTilesetsHaveCallback()); + ui->checkBox_OutputIsCompressed->setChecked(projectConfig.getTilesetsHaveIsCompressed()); + + // Init spinners + ui->spinBox_Elevation->setRange(0, 15); + ui->spinBox_Elevation->setValue(projectConfig.getNewMapElevation()); + + // Init text boxes + // TODO: Validator for Border Metatiles and Fill Metatile + ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString()); + ui->lineEdit_FillMetatile->setText(projectConfig.getNewMapMetatileIdString()); + ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath(false)); + QString mask = ProjectConfig::getMaskString(projectConfig.getMetatileBehaviorMask()); + ui->lineEdit_BehaviorMask->setText(mask); + mask = ProjectConfig::getMaskString(projectConfig.getMetatileEncounterTypeMask()); + ui->lineEdit_EncounterTypeMask->setText(mask); + mask = ProjectConfig::getMaskString(projectConfig.getMetatileLayerTypeMask()); + ui->lineEdit_LayerTypeMask->setText(mask); + mask = ProjectConfig::getMaskString(projectConfig.getMetatileTerrainTypeMask()); + ui->lineEdit_TerrainTypeMask->setText(mask); +} + +void ProjectSettingsEditor::saveFields() { + // TODO + /* + TODO combo_defaultPrimaryTileset + TODO combo_defaultSecondaryTileset + setBaseGameVersion combo_baseGameVersion + TODO combo_attributesSize + setUsePoryScript ui->checkBox_UsePoryscript + userConfig.setEncounterJsonActive ui->checkBox_ShowWildEncounterTables + setCreateMapTextFileEnabled ui->checkBox_CreateTextFile + setPrefabImportPrompted ui->checkBox_PrefabImportPrompted + setTripleLayerMetatilesEnabled ui->checkBox_EnableTripleLayerMetatiles + setHiddenItemRequiresItemfinderEnabled ui->checkBox_EnableRequiresItemfinder + setHiddenItemQuantityEnabled ui->checkBox_EnableQuantity + setEventCloneObjectEnabled ui->checkBox_EnableCloneObjects + setEventWeatherTriggerEnabled ui->checkBox_EnableWeatherTriggers + setEventSecretBaseEnabled ui->checkBox_EnableSecretBases + setHealLocationRespawnDataEnabled ui->checkBox_EnableRespawn + TODO ui->checkBox_EnableAllowFlags + setFloorNumberEnabled ui->checkBox_EnableFloorNumber + setUseCustomBorderSize ui->checkBox_EnableCustomBorderSize + setTilesetsHaveCallback ui->checkBox_OutputCallback + setTilesetsHaveIsCompressed ui->checkBox_OutputIsCompressed + setNewMapElevation ui->spinBox_Elevation + setPrefabFilepath ui->lineEdit_PrefabsPath + TODO ui->lineEdit_BehaviorMask + TODO ui->lineEdit_EncounterTypeMask + TODO ui->lineEdit_LayerTypeMask + TODO ui->lineEdit_TerrainTypeMask + setNewMapMetatileId ui->lineEdit_FillMetatile + setNewMapBorderMetatileIds ui->lineEdit_BorderMetatiles + */ + emit saved(); +} + +void ProjectSettingsEditor::dialogButtonClicked(QAbstractButton *button) { + auto buttonRole = ui->buttonBox->buttonRole(button); + if (buttonRole == QDialogButtonBox::AcceptRole) { + // TODO: Prompt for unsaved changes + saveFields(); + close(); + } else if (buttonRole == QDialogButtonBox::ResetRole) { + // TODO + } else if (buttonRole == QDialogButtonBox::ApplyRole) { + saveFields(); + } else if (buttonRole == QDialogButtonBox::RejectRole) { + close(); + } + // TODO: Save geometry on close +} diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index e5ca4b67c..e8fc6be51 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -128,6 +128,7 @@ void TilesetEditor::setAttributesUi() { this->ui->comboBox_terrainType->addItem("Grass", TERRAIN_GRASS); this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER); this->ui->comboBox_terrainType->addItem("Waterfall", TERRAIN_WATERFALL); + this->ui->comboBox_terrainType->setEditable(false); } else { this->ui->comboBox_terrainType->setVisible(false); this->ui->label_terrainType->setVisible(false); @@ -138,6 +139,7 @@ void TilesetEditor::setAttributesUi() { this->ui->comboBox_encounterType->addItem("None", ENCOUNTER_NONE); this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND); this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER); + this->ui->comboBox_encounterType->setEditable(false); } else { this->ui->comboBox_encounterType->setVisible(false); this->ui->label_encounterType->setVisible(false); @@ -148,6 +150,7 @@ void TilesetEditor::setAttributesUi() { this->ui->comboBox_layerType->addItem("Normal - Middle/Top", METATILE_LAYER_MIDDLE_TOP); this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE); this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP); + this->ui->comboBox_layerType->setEditable(false); if (!Metatile::getLayerTypeMask()) { // User doesn't have triple layer metatiles, but has no layer type attribute. // Porymap is still using the layer type value to render metatiles, and with @@ -357,24 +360,6 @@ void TilesetEditor::onHoveredMetatileCleared() { this->ui->statusbar->clearMessage(); } -void TilesetEditor::setComboValue(QComboBox * combo, int value) { - int index = combo->findData(value); - if (index >= 0) { - // Valid item - combo->setCurrentIndex(index); - } else if (combo->isEditable()) { - // Invalid item in editable box, just display the text - combo->setCurrentText(QString::number(value)); - } else { - // Invalid item in uneditable box, display text as placeholder - // On Qt < 5.15 this will display an empty box -#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) - combo->setPlaceholderText(QString::number(value)); -#endif - combo->setCurrentIndex(index); - } -} - void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->metatile = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset); this->metatileLayersItem->setMetatile(metatile); @@ -385,10 +370,10 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->ui->lineEdit_metatileLabel->setText(labels.owned); this->ui->lineEdit_metatileLabel->setPlaceholderText(labels.shared); - setComboValue(this->ui->comboBox_metatileBehaviors, this->metatile->behavior); - setComboValue(this->ui->comboBox_layerType, this->metatile->layerType); - setComboValue(this->ui->comboBox_encounterType, this->metatile->encounterType); - setComboValue(this->ui->comboBox_terrainType, this->metatile->terrainType); + this->ui->comboBox_metatileBehaviors->setNumberItem(this->metatile->behavior); + this->ui->comboBox_layerType->setNumberItem(this->metatile->layerType); + this->ui->comboBox_encounterType->setNumberItem(this->metatile->encounterType); + this->ui->comboBox_terrainType->setNumberItem(this->metatile->terrainType); } void TilesetEditor::onHoveredTileChanged(uint16_t tile) { From 9bed66ecfcfb4c3e21583672e36a00409746276f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 23 Aug 2023 21:07:13 -0400 Subject: [PATCH 10/34] Write config with project settings editor --- forms/mainwindow.ui | 18 --- forms/projectsettingseditor.ui | 211 ++++++++++++++----------- include/config.h | 44 +++--- include/core/metatile.h | 1 + include/mainwindow.h | 2 - include/ui/projectsettingseditor.h | 6 + src/config.cpp | 128 ++++++++++----- src/editor.cpp | 3 +- src/mainwindow.cpp | 16 -- src/project.cpp | 25 +-- src/ui/projectsettingseditor.cpp | 242 +++++++++++++++++++---------- src/ui/tileseteditor.cpp | 3 +- 12 files changed, 421 insertions(+), 278 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index d9e19dcc8..f153538ca 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -3012,9 +3012,7 @@ Options - - @@ -3065,14 +3063,6 @@ Ctrl+S - - - true - - - Show Wild Encounter Tables - - true @@ -3081,14 +3071,6 @@ Monitor Project Files - - - true - - - Use Poryscript - - true diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index 442291dc2..529992eac 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -72,15 +72,8 @@ New Map Defaults - - - - The default metatile value that will be used to fill new maps - - - Fill Metatile - - + + @@ -92,19 +85,6 @@ - - - - A comma-separated list of metatile values that will be used to fill new map borders - - - Border Metatiles - - - - - - @@ -118,12 +98,6 @@ - - - - - - @@ -134,6 +108,52 @@ + + + + + + + The default metatile value that will be used to fill new maps + + + Fill Metatile + + + + + + + A comma-separated list of metatile values that will be used to fill new map borders + + + Border Metatiles + + + + + + + 0x + + + 16 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -217,16 +237,6 @@ Tilesets / Metatiles - - - - The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. - - - Behavior mask - - - @@ -237,15 +247,18 @@ - - - - The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. + + + + Qt::Vertical - - Layer Type mask + + + 20 + 15 + - + @@ -264,32 +277,16 @@ - - - - Qt::Vertical - - - - 20 - 15 - - - - - - - - - + + - - + + - The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. + Whether the C data outputted for new tilesets will include the "isCompressed" field - Encounter Type mask + Output 'isCompressed' field @@ -306,27 +303,35 @@ - - - - - + + + + 0x + + + 16 + + - - + + + + 0x + + + 16 + + - - - - Qt::Horizontal + + + + The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. - - - 40 - 20 - + + Encounter Type mask - + @@ -338,13 +343,43 @@ - - + + - Whether the C data outputted for new tilesets will include the "isCompressed" field + The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. - Output 'isCompressed' field + Behavior mask + + + + + + + The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. + + + Layer Type mask + + + + + + + 0x + + + 16 + + + + + + + 0x + + + 16 diff --git a/include/config.h b/include/config.h index cb927caa2..72d42bbf5 100644 --- a/include/config.h +++ b/include/config.h @@ -10,8 +10,8 @@ #include // In both versions the default new map border is a generic tree -#define DEFAULT_BORDER_RSE (QList{468, 469, 476, 477}) -#define DEFAULT_BORDER_FRLG (QList{20, 21, 28, 29}) +#define DEFAULT_BORDER_RSE (QList{0x1D4, 0x1D5, 0x1DC, 0x1DD}) +#define DEFAULT_BORDER_FRLG (QList{0x14, 0x15, 0x1C, 0x1D}) #define CONFIG_BACKWARDS_COMPATABILITY @@ -26,6 +26,7 @@ class KeyValueConfigBase public: void save(); void load(); + void setSaveDisabled(bool disabled); virtual ~KeyValueConfigBase(); virtual void reset() = 0; protected: @@ -37,6 +38,8 @@ class KeyValueConfigBase bool getConfigBool(QString key, QString value); int getConfigInteger(QString key, QString value, int min, int max, int defaultValue); uint32_t getConfigUint32(QString key, QString value, uint32_t min, uint32_t max, uint32_t defaultValue); +private: + bool saveDisabled = false; }; class PorymapConfig: public KeyValueConfigBase @@ -203,20 +206,11 @@ class ProjectConfig: public KeyValueConfigBase } virtual void reset() override { this->baseGameVersion = BaseGameVersion::pokeemerald; - this->useCustomBorderSize = false; - this->enableEventWeatherTrigger = true; - this->enableEventSecretBase = true; - this->enableHiddenItemQuantity = false; - this->enableHiddenItemRequiresItemfinder = false; - this->enableHealLocationRespawnData = false; - this->enableEventCloneObject = false; - this->enableFloorNumber = false; - this->createMapTextFile = false; + // Reset non-version-specific settings this->usePoryScript = false; this->enableTripleLayerMetatiles = false; this->newMapMetatileId = 1; this->newMapElevation = 3; - this->newMapBorderMetatileIds = DEFAULT_BORDER_RSE; this->defaultPrimaryTileset = "gTileset_General"; this->prefabFilepath = QString(); this->prefabImportPrompted = false; @@ -225,10 +219,12 @@ class ProjectConfig: public KeyValueConfigBase this->filePaths.clear(); this->readKeys.clear(); } - static const QStringList baseGameVersions; + static const QStringList versionStrings; + void reset(BaseGameVersion baseGameVersion); void setBaseGameVersion(BaseGameVersion baseGameVersion); BaseGameVersion getBaseGameVersion(); QString getBaseGameVersionString(); + BaseGameVersion stringToBaseGameVersion(QString string, bool * ok = nullptr); void setUsePoryScript(bool usePoryScript); bool getUsePoryScript(); void setProjectDir(QString projectDir); @@ -255,16 +251,17 @@ class ProjectConfig: public KeyValueConfigBase bool getTripleLayerMetatilesEnabled(); int getNumLayersInMetatile(); int getNumTilesInMetatile(); - void setNewMapMetatileId(int metatileId); - int getNewMapMetatileId(); - QString getNewMapMetatileIdString(); + void setNewMapMetatileId(uint16_t metatileId); + uint16_t getNewMapMetatileId(); void setNewMapElevation(int elevation); int getNewMapElevation(); - void setNewMapBorderMetatileIds(QList metatileIds); - QList getNewMapBorderMetatileIds(); + void setNewMapBorderMetatileIds(QList metatileIds); + QList getNewMapBorderMetatileIds(); QString getNewMapBorderMetatileIdsString(); QString getDefaultPrimaryTileset(); QString getDefaultSecondaryTileset(); + void setDefaultPrimaryTileset(QString tilesetName); + void setDefaultSecondaryTileset(QString tilesetName); void setFilePath(ProjectFilePath pathId, QString path); QString getFilePath(ProjectFilePath pathId); void setPrefabFilepath(QString filepath); @@ -276,12 +273,17 @@ class ProjectConfig: public KeyValueConfigBase void setTilesetsHaveIsCompressed(bool has); bool getTilesetsHaveIsCompressed(); int getMetatileAttributesSize(); + void setMetatileAttributesSize(int size); uint32_t getMetatileBehaviorMask(); uint32_t getMetatileTerrainTypeMask(); uint32_t getMetatileEncounterTypeMask(); uint32_t getMetatileLayerTypeMask(); - static QString getMaskString(uint32_t mask); + void setMetatileBehaviorMask(uint32_t mask); + void setMetatileTerrainTypeMask(uint32_t mask); + void setMetatileEncounterTypeMask(uint32_t mask); + void setMetatileLayerTypeMask(uint32_t mask); bool getMapAllowFlagsEnabled(); + void setMapAllowFlagsEnabled(bool enabled); protected: virtual QString getConfigFilepath() override; virtual void parseConfigKeyValue(QString key, QString value) override; @@ -303,9 +305,9 @@ class ProjectConfig: public KeyValueConfigBase bool enableFloorNumber; bool createMapTextFile; bool enableTripleLayerMetatiles; - int newMapMetatileId; + uint16_t newMapMetatileId; int newMapElevation; - QList newMapBorderMetatileIds; + QList newMapBorderMetatileIds; QString defaultPrimaryTileset; QString defaultSecondaryTileset; QStringList readKeys; diff --git a/include/core/metatile.h b/include/core/metatile.h index 49fb5c7b1..c3bda046c 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -93,6 +93,7 @@ class Metatile static QPoint coordFromPixmapCoord(const QPointF &pixelCoord); static int getDefaultAttributesSize(BaseGameVersion version); static void setCustomLayout(Project*); + static QString getMetatileIdString(uint16_t metatileId) { return "0x" + QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper(); }; private: // Stores how each attribute should be laid out for all metatiles, according to the user's config diff --git a/include/mainwindow.h b/include/mainwindow.h index c6c30b42e..32bb03eb8 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -198,9 +198,7 @@ private slots: void on_checkBox_AllowBiking_stateChanged(int selected); void on_checkBox_AllowEscaping_stateChanged(int selected); void on_spinBox_FloorNumber_valueChanged(int offset); - void on_actionUse_Encounter_Json_triggered(bool checked); void on_actionMonitor_Project_Files_triggered(bool checked); - void on_actionUse_Poryscript_triggered(bool checked); void on_actionOpen_Recent_Project_On_Launch_triggered(bool checked); void on_actionEdit_Shortcuts_triggered(); diff --git a/include/ui/projectsettingseditor.h b/include/ui/projectsettingseditor.h index 16b28b0b2..6e1f7ed58 100644 --- a/include/ui/projectsettingseditor.h +++ b/include/ui/projectsettingseditor.h @@ -31,11 +31,17 @@ class ProjectSettingsEditor : public QMainWindow NoScrollComboBox *combo_baseGameVersion; NoScrollComboBox *combo_attributesSize; + bool hasUnsavedChanges = false; + void initUi(); void saveFields(); + void connectSignals(); + void refresh(); + bool prompt(const QString &text); private slots: void dialogButtonClicked(QAbstractButton *button); + void markEdited(); }; #endif // PROJECTSETTINGSEDITOR_H diff --git a/src/config.cpp b/src/config.cpp index 9419a7b44..037511ee9 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -119,6 +119,9 @@ void KeyValueConfigBase::load() { } void KeyValueConfigBase::save() { + if (this->saveDisabled) + return; + QString text = ""; QMap map = this->getKeyValueMap(); for (QMap::iterator it = map.begin(); it != map.end(); it++) { @@ -163,6 +166,11 @@ uint32_t KeyValueConfigBase::getConfigUint32(QString key, QString value, uint32_ return qMin(max, qMax(min, result)); } +// For temporarily disabling saving during frequent config changes. +void KeyValueConfigBase::setSaveDisabled(bool disabled) { + this->saveDisabled = disabled; +} + const QMap mapSortOrderMap = { {MapSortOrder::Group, "group"}, {MapSortOrder::Layout, "layout"}, @@ -513,24 +521,34 @@ int PorymapConfig::getPaletteEditorBitDepth() { return this->paletteEditorBitDepth; } -const QStringList ProjectConfig::baseGameVersions = { +const QStringList ProjectConfig::versionStrings = { "pokeruby", "pokefirered", "pokeemerald", }; const QMap baseGameVersionMap = { - {BaseGameVersion::pokeruby, ProjectConfig::baseGameVersions[0]}, - {BaseGameVersion::pokefirered, ProjectConfig::baseGameVersions[1]}, - {BaseGameVersion::pokeemerald, ProjectConfig::baseGameVersions[2]}, + {BaseGameVersion::pokeruby, ProjectConfig::versionStrings[0]}, + {BaseGameVersion::pokefirered, ProjectConfig::versionStrings[1]}, + {BaseGameVersion::pokeemerald, ProjectConfig::versionStrings[2]}, }; const QMap baseGameVersionReverseMap = { - {ProjectConfig::baseGameVersions[0], BaseGameVersion::pokeruby}, - {ProjectConfig::baseGameVersions[1], BaseGameVersion::pokefirered}, - {ProjectConfig::baseGameVersions[2], BaseGameVersion::pokeemerald}, + {ProjectConfig::versionStrings[0], BaseGameVersion::pokeruby}, + {ProjectConfig::versionStrings[1], BaseGameVersion::pokefirered}, + {ProjectConfig::versionStrings[2], BaseGameVersion::pokeemerald}, }; +BaseGameVersion ProjectConfig::stringToBaseGameVersion(QString string, bool * ok) { + if (baseGameVersionReverseMap.contains(string)) { + if (ok) *ok = true; + return baseGameVersionReverseMap.value(string); + } else { + if (ok) *ok = false; + return BaseGameVersion::pokeemerald; + } +} + ProjectConfig projectConfig; QString ProjectConfig::getConfigFilepath() { @@ -540,13 +558,10 @@ QString ProjectConfig::getConfigFilepath() { void ProjectConfig::parseConfigKeyValue(QString key, QString value) { if (key == "base_game_version") { - QString baseGameVersion = value.toLower(); - if (baseGameVersionReverseMap.contains(baseGameVersion)) { - this->baseGameVersion = baseGameVersionReverseMap.value(baseGameVersion); - } else { - this->baseGameVersion = BaseGameVersion::pokeemerald; + bool ok; + this->baseGameVersion = this->stringToBaseGameVersion(value.toLower(), &ok); + if (!ok) logWarn(QString("Invalid config value for base_game_version: '%1'. Must be 'pokeruby', 'pokefirered' or 'pokeemerald'.").arg(value)); - } } else if (key == "use_poryscript") { this->usePoryScript = getConfigBool(key, value); } else if (key == "use_custom_border_size") { @@ -571,24 +586,18 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { } else if (key == "enable_triple_layer_metatiles") { this->enableTripleLayerMetatiles = getConfigBool(key, value); } else if (key == "new_map_metatile") { - this->newMapMetatileId = getConfigInteger(key, value, 0, 1023, 0); + this->newMapMetatileId = getConfigUint32(key, value, 0, 1023, 0); } else if (key == "new_map_elevation") { this->newMapElevation = getConfigInteger(key, value, 0, 15, 3); } else if (key == "new_map_border_metatiles") { this->newMapBorderMetatileIds.clear(); QList metatileIds = value.split(","); - const int maxSize = DEFAULT_BORDER_WIDTH * DEFAULT_BORDER_HEIGHT; - const int size = qMin(metatileIds.size(), maxSize); - int i; - for (i = 0; i < size; i++) { - int metatileId = getConfigInteger(key, metatileIds.at(i), 0, 1023, 0); + for (int i = 0; i < metatileIds.size(); i++) { + // TODO: The max of 1023 here should eventually reflect Project::num_metatiles_total-1, + // but the config is parsed well before that constant is. + int metatileId = getConfigUint32(key, metatileIds.at(i), 0, 1023, 0); this->newMapBorderMetatileIds.append(metatileId); } - // TODO: If insufficient metatiles are provided, it should loop the provided metatiles instead. - for (; i < maxSize; i++) { - // Set any metatiles not provided to 0 - this->newMapBorderMetatileIds.append(0); - } } else if (key == "default_primary_tileset") { this->defaultPrimaryTileset = value; } else if (key == "default_secondary_tileset") { @@ -646,6 +655,13 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { readKeys.append(key); } +// Restore config to version-specific defaults +void::ProjectConfig::reset(BaseGameVersion baseGameVersion) { + this->reset(); + this->setBaseGameVersion(baseGameVersion); + this->setUnreadKeys(); +} + void ProjectConfig::setUnreadKeys() { // Set game-version specific defaults for any config field that wasn't read bool isPokefirered = this->baseGameVersion == BaseGameVersion::pokefirered; @@ -682,7 +698,7 @@ QMap ProjectConfig::getKeyValueMap() { map.insert("enable_floor_number", QString::number(this->enableFloorNumber)); map.insert("create_map_text_file", QString::number(this->createMapTextFile)); map.insert("enable_triple_layer_metatiles", QString::number(this->enableTripleLayerMetatiles)); - map.insert("new_map_metatile", this->getNewMapMetatileIdString()); + map.insert("new_map_metatile", Metatile::getMetatileIdString(this->newMapMetatileId)); map.insert("new_map_elevation", QString::number(this->newMapElevation)); map.insert("new_map_border_metatiles", this->getNewMapBorderMetatileIdsString()); map.insert("default_primary_tileset", this->defaultPrimaryTileset); @@ -695,10 +711,10 @@ QMap ProjectConfig::getKeyValueMap() { map.insert("tilesets_have_callback", QString::number(this->tilesetsHaveCallback)); map.insert("tilesets_have_is_compressed", QString::number(this->tilesetsHaveIsCompressed)); map.insert("metatile_attributes_size", QString::number(this->metatileAttributesSize)); - map.insert("metatile_behavior_mask", getMaskString(this->metatileBehaviorMask)); - map.insert("metatile_terrain_type_mask", getMaskString(this->metatileTerrainTypeMask)); - map.insert("metatile_encounter_type_mask", getMaskString(this->metatileEncounterTypeMask)); - map.insert("metatile_layer_type_mask", getMaskString(this->metatileLayerTypeMask)); + map.insert("metatile_behavior_mask", "0x" + QString::number(this->metatileBehaviorMask, 16).toUpper()); + map.insert("metatile_terrain_type_mask", "0x" + QString::number(this->metatileTerrainTypeMask, 16).toUpper()); + map.insert("metatile_encounter_type_mask", "0x" + QString::number(this->metatileEncounterTypeMask, 16).toUpper()); + map.insert("metatile_layer_type_mask", "0x" + QString::number(this->metatileLayerTypeMask, 16).toUpper()); map.insert("enable_map_allow_flags", QString::number(this->enableMapAllowFlags)); return map; } @@ -875,19 +891,15 @@ int ProjectConfig::getNumTilesInMetatile() { return this->enableTripleLayerMetatiles ? 12 : 8; } -void ProjectConfig::setNewMapMetatileId(int metatileId) { +void ProjectConfig::setNewMapMetatileId(uint16_t metatileId) { this->newMapMetatileId = metatileId; this->save(); } -int ProjectConfig::getNewMapMetatileId() { +uint16_t ProjectConfig::getNewMapMetatileId() { return this->newMapMetatileId; } -QString ProjectConfig::getNewMapMetatileIdString() { - return "0x" + QString::number(this->newMapMetatileId, 16).toUpper(); -} - void ProjectConfig::setNewMapElevation(int elevation) { this->newMapElevation = elevation; this->save(); @@ -897,19 +909,19 @@ int ProjectConfig::getNewMapElevation() { return this->newMapElevation; } -void ProjectConfig::setNewMapBorderMetatileIds(QList metatileIds) { +void ProjectConfig::setNewMapBorderMetatileIds(QList metatileIds) { this->newMapBorderMetatileIds = metatileIds; this->save(); } -QList ProjectConfig::getNewMapBorderMetatileIds() { +QList ProjectConfig::getNewMapBorderMetatileIds() { return this->newMapBorderMetatileIds; } QString ProjectConfig::getNewMapBorderMetatileIdsString() { QStringList metatiles; for (auto metatileId : this->newMapBorderMetatileIds){ - metatiles << ("0x" + QString::number(metatileId, 16).toUpper()); + metatiles << Metatile::getMetatileIdString(metatileId); } return metatiles.join(","); } @@ -922,6 +934,16 @@ QString ProjectConfig::getDefaultSecondaryTileset() { return this->defaultSecondaryTileset; } +void ProjectConfig::setDefaultPrimaryTileset(QString tilesetName) { + this->defaultPrimaryTileset = tilesetName; + this->save(); +} + +void ProjectConfig::setDefaultSecondaryTileset(QString tilesetName) { + this->defaultSecondaryTileset = tilesetName; + this->save(); +} + void ProjectConfig::setPrefabFilepath(QString filepath) { this->prefabFilepath = filepath; this->save(); @@ -965,6 +987,11 @@ int ProjectConfig::getMetatileAttributesSize() { return this->metatileAttributesSize; } +void ProjectConfig::setMetatileAttributesSize(int size) { + this->metatileAttributesSize = size; + this->save(); +} + uint32_t ProjectConfig::getMetatileBehaviorMask() { return this->metatileBehaviorMask; } @@ -981,14 +1008,35 @@ uint32_t ProjectConfig::getMetatileLayerTypeMask() { return this->metatileLayerTypeMask; } -QString ProjectConfig::getMaskString(uint32_t mask) { - return "0x" + QString::number(mask, 16).toUpper(); +void ProjectConfig::setMetatileBehaviorMask(uint32_t mask) { + this->metatileBehaviorMask = mask; + this->save(); +} + +void ProjectConfig::setMetatileTerrainTypeMask(uint32_t mask) { + this->metatileTerrainTypeMask = mask; + this->save(); +} + +void ProjectConfig::setMetatileEncounterTypeMask(uint32_t mask) { + this->metatileEncounterTypeMask = mask; + this->save(); +} + +void ProjectConfig::setMetatileLayerTypeMask(uint32_t mask) { + this->metatileLayerTypeMask = mask; + this->save(); } bool ProjectConfig::getMapAllowFlagsEnabled() { return this->enableMapAllowFlags; } +void ProjectConfig::setMapAllowFlagsEnabled(bool enabled) { + this->enableMapAllowFlags = enabled; + this->save(); +} + UserConfig userConfig; diff --git a/src/editor.cpp b/src/editor.cpp index 23234b871..9996460e4 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -933,8 +933,7 @@ void Editor::onHoveredMovementPermissionCleared() { QString Editor::getMetatileDisplayMessage(uint16_t metatileId) { Metatile *metatile = Tileset::getMetatile(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary); QString label = Tileset::getMetatileLabel(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary); - QString hexString = QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper(); - QString message = QString("Metatile: 0x%1").arg(hexString); + QString message = QString("Metatile: %1").arg(Metatile::getMetatileIdString(metatileId)); if (label.size()) message += QString(" \"%1\"").arg(label); if (metatile && metatile->behavior) // Skip MB_NORMAL diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9ceb9b94b..b40f5ef0f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -369,13 +369,11 @@ void MainWindow::markMapEdited() { } void MainWindow::setWildEncountersUIEnabled(bool enabled) { - ui->actionUse_Encounter_Json->setChecked(enabled); ui->mainTabBar->setTabEnabled(4, enabled); } void MainWindow::setProjectSpecificUIVisibility() { - ui->actionUse_Poryscript->setChecked(projectConfig.getUsePoryScript()); this->setWildEncountersUIEnabled(userConfig.getEncounterJsonActive()); bool hasFlags = projectConfig.getMapAllowFlagsEnabled(); @@ -1757,25 +1755,11 @@ void MainWindow::on_actionCursor_Tile_Outline_triggered() } } -void MainWindow::on_actionUse_Encounter_Json_triggered(bool checked) -{ - QMessageBox warning(this); - warning.setText("You must reload the project for this setting to take effect."); - warning.setIcon(QMessageBox::Information); - warning.exec(); - userConfig.setEncounterJsonActive(checked); -} - void MainWindow::on_actionMonitor_Project_Files_triggered(bool checked) { porymapConfig.setMonitorFiles(checked); } -void MainWindow::on_actionUse_Poryscript_triggered(bool checked) -{ - projectConfig.setUsePoryScript(checked); -} - void MainWindow::on_actionOpen_Recent_Project_On_Launch_triggered(bool checked) { porymapConfig.setReopenOnLaunch(checked); diff --git a/src/project.cpp b/src/project.cpp index 92a71e2ff..66e5aba8f 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -957,9 +957,9 @@ void Project::saveTilesetMetatileLabels(Tileset *primaryTileset, Tileset *second } for (QString defineName : definesOut.keys()) { int value = defines[defineName]; - QString line = QString("#define %1 0x%2\n") + QString line = QString("#define %1 %2\n") .arg(defineName, -1 * longestLength) - .arg(QString("%1").arg(value, 3, 16, QChar('0')).toUpper()); + .arg(Metatile::getMetatileIdString(value)); outputText += line; } i += j; @@ -1142,16 +1142,21 @@ void Project::setNewMapBorder(Map *map) { map->layout->border.clear(); int width = map->getBorderWidth(); int height = map->getBorderHeight(); - if (width != DEFAULT_BORDER_WIDTH || height != DEFAULT_BORDER_HEIGHT) { + + const QList configMetatileIds = projectConfig.getNewMapBorderMetatileIds(); + if (configMetatileIds.length() != width * height) { + // Border size doesn't match the number of default border metatiles. + // Fill the border with empty metatiles. for (int i = 0; i < width * height; i++) { map->layout->border.append(0); } } else { - QList metatileIds = projectConfig.getNewMapBorderMetatileIds(); - for (int i = 0; i < DEFAULT_BORDER_WIDTH * DEFAULT_BORDER_HEIGHT; i++) { - map->layout->border.append(qint16(metatileIds.at(i))); + // Fill the border with the default metatiles from the config. + for (int i = 0; i < width * height; i++) { + map->layout->border.append(configMetatileIds.at(i)); } } + map->layout->lastCommitBlocks.border = map->layout->border; map->layout->lastCommitBlocks.borderDimensions = QSize(width, height); } @@ -2174,8 +2179,8 @@ bool Project::readCoordEventWeatherNames() { fileWatcher.addPath(root + "/" + filename); coordEventWeatherNames = parser.readCDefinesSorted(filename, prefixes); if (coordEventWeatherNames.isEmpty()) { - logError(QString("Failed to read coord event weather constants from %1").arg(filename)); - return false; + logWarn(QString("Failed to read coord event weather constants from %1. Disabling Weather Trigger events.").arg(filename)); + projectConfig.setEventWeatherTriggerEnabled(false); } return true; } @@ -2189,8 +2194,8 @@ bool Project::readSecretBaseIds() { fileWatcher.addPath(root + "/" + filename); secretBaseIds = parser.readCDefinesSorted(filename, prefixes); if (secretBaseIds.isEmpty()) { - logError(QString("Failed to read secret base id constants from %1").arg(filename)); - return false; + logWarn(QString("Failed to read secret base id constants from '%1'. Disabling Secret Base events.").arg(filename)); + projectConfig.setEventSecretBaseEnabled(false); } return true; } diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index c6f2ef6af..5aeb9debc 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -22,8 +22,8 @@ ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) ui->setupUi(this); initUi(); setAttribute(Qt::WA_DeleteOnClose); - connect(ui->buttonBox, &QDialogButtonBox::clicked, - this, &ProjectSettingsEditor::dialogButtonClicked); + connectSignals(); + refresh(); } ProjectSettingsEditor::~ProjectSettingsEditor() @@ -31,8 +31,76 @@ ProjectSettingsEditor::~ProjectSettingsEditor() delete ui; } +void ProjectSettingsEditor::connectSignals() { + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked); + + // Connect combo boxes + QList combos = ui->centralwidget->findChildren(); + foreach(auto i, combos) + connect(i, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited); + + // Connect check boxes + QList checkboxes = ui->centralwidget->findChildren(); + foreach(auto i, checkboxes) + connect(i, &QCheckBox::stateChanged, this, &ProjectSettingsEditor::markEdited); + + // Connect spin boxes + QList spinBoxes = ui->centralwidget->findChildren(); + foreach(auto i, spinBoxes) + connect(i, QOverload::of(&QSpinBox::valueChanged), [this](int) { this->markEdited(); }); + + // Connect line edits + QList lineEdits = ui->centralwidget->findChildren(); + foreach(auto i, lineEdits) + connect(i, &QLineEdit::textEdited, this, &ProjectSettingsEditor::markEdited); +} + +void ProjectSettingsEditor::markEdited() { + this->hasUnsavedChanges = true; +} + void ProjectSettingsEditor::initUi() { - // Block signals while setting initial UI states + // Create Default Tilesets combo boxes + auto *defaultTilesetsLayout = new QFormLayout(ui->groupBox_DefaultTilesets); + combo_defaultPrimaryTileset = new NoScrollComboBox(ui->groupBox_DefaultTilesets); + combo_defaultSecondaryTileset = new NoScrollComboBox(ui->groupBox_DefaultTilesets); + if (project) combo_defaultPrimaryTileset->addItems(project->primaryTilesetLabels); + if (project) combo_defaultSecondaryTileset->addItems(project->secondaryTilesetLabels); + defaultTilesetsLayout->addRow("Primary Tileset", combo_defaultPrimaryTileset); + defaultTilesetsLayout->addRow("Secondary Tileset", combo_defaultSecondaryTileset); + + // Create Base game version combo box + combo_baseGameVersion = new NoScrollComboBox(ui->widget_BaseGameVersion); + combo_baseGameVersion->addItems(ProjectConfig::versionStrings); + combo_baseGameVersion->setEditable(false); + ui->layout_BaseGameVersion->insertRow(0, "Base game version", combo_baseGameVersion); + + // Create Attributes size combo box + auto *attributesSizeLayout = new QFormLayout(ui->widget_SizeDropdown); + combo_attributesSize = new NoScrollComboBox(ui->widget_SizeDropdown); + combo_attributesSize->addItems({"1", "2", "4"}); + combo_attributesSize->setEditable(false); + attributesSizeLayout->addRow("", combo_attributesSize); + + // Validate that the border metatiles text is a comma-separated list of hex values + static const QRegularExpression expression("^((0[xX])?[A-Fa-f0-9]+,)*(0[xX])?[A-Fa-f0-9]$"); + QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression); + ui->lineEdit_BorderMetatiles->setValidator(validator); + + ui->spinBox_Elevation->setMaximum(15); + ui->spinBox_FillMetatile->setMaximum(Project::getNumMetatilesTotal() - 1); + + // TODO: These need to be subclassed to handle larger values + ui->spinBox_BehaviorMask->setMaximum(INT_MAX); + ui->spinBox_EncounterTypeMask->setMaximum(INT_MAX); + ui->spinBox_LayerTypeMask->setMaximum(INT_MAX); + ui->spinBox_TerrainTypeMask->setMaximum(INT_MAX); + + // TODO: File picker for prefabs? +} + +// Set UI states using config data +void ProjectSettingsEditor::refresh() { const QSignalBlocker blocker0(combo_defaultPrimaryTileset); const QSignalBlocker blocker1(combo_defaultSecondaryTileset); const QSignalBlocker blocker2(combo_baseGameVersion); @@ -54,41 +122,21 @@ void ProjectSettingsEditor::initUi() { const QSignalBlocker blocker12(ui->checkBox_OutputCallback); const QSignalBlocker blocker13(ui->checkBox_OutputIsCompressed); const QSignalBlocker blocker14(ui->spinBox_Elevation); - const QSignalBlocker blocker15(ui->lineEdit_BorderMetatiles); - const QSignalBlocker blocker16(ui->lineEdit_FillMetatile); - const QSignalBlocker blocker17(ui->lineEdit_PrefabsPath); - const QSignalBlocker blocker18(ui->lineEdit_BehaviorMask); - const QSignalBlocker blocker19(ui->lineEdit_EncounterTypeMask); - const QSignalBlocker blocker1A(ui->lineEdit_LayerTypeMask); - const QSignalBlocker blocker1B(ui->lineEdit_TerrainTypeMask); + const QSignalBlocker blocker15(ui->spinBox_FillMetatile); + const QSignalBlocker blocker16(ui->spinBox_BehaviorMask); + const QSignalBlocker blocker17(ui->spinBox_EncounterTypeMask); + const QSignalBlocker blocker18(ui->spinBox_LayerTypeMask); + const QSignalBlocker blocker19(ui->spinBox_TerrainTypeMask); + const QSignalBlocker blocker1A(ui->lineEdit_BorderMetatiles); + const QSignalBlocker blocker1B(ui->lineEdit_PrefabsPath); - // Create Default Tilesets combo boxes - auto *defaultTilesetsLayout = new QFormLayout(ui->groupBox_DefaultTilesets); - combo_defaultPrimaryTileset = new NoScrollComboBox(ui->groupBox_DefaultTilesets); - combo_defaultSecondaryTileset = new NoScrollComboBox(ui->groupBox_DefaultTilesets); - if (project) combo_defaultPrimaryTileset->addItems(project->primaryTilesetLabels); - if (project) combo_defaultSecondaryTileset->addItems(project->secondaryTilesetLabels); + // Set combo box texts combo_defaultPrimaryTileset->setTextItem(projectConfig.getDefaultPrimaryTileset()); combo_defaultSecondaryTileset->setTextItem(projectConfig.getDefaultSecondaryTileset()); - defaultTilesetsLayout->addRow("Primary Tileset", combo_defaultPrimaryTileset); - defaultTilesetsLayout->addRow("Secondary Tileset", combo_defaultSecondaryTileset); - - // Create Base game version combo box - combo_baseGameVersion = new NoScrollComboBox(ui->widget_BaseGameVersion); - combo_baseGameVersion->addItems(ProjectConfig::baseGameVersions); combo_baseGameVersion->setTextItem(projectConfig.getBaseGameVersionString()); - combo_baseGameVersion->setEditable(false); - ui->layout_BaseGameVersion->insertRow(0, "Base game version", combo_baseGameVersion); - - // Create Attributes size combo box - auto *attributesSizeLayout = new QFormLayout(ui->widget_SizeDropdown); - combo_attributesSize = new NoScrollComboBox(ui->widget_SizeDropdown); - combo_attributesSize->addItems({"1", "2", "4"}); combo_attributesSize->setTextItem(QString::number(projectConfig.getMetatileAttributesSize())); - combo_attributesSize->setEditable(false); - attributesSizeLayout->addRow("", combo_attributesSize); - // Init check boxes + // Set check box states ui->checkBox_UsePoryscript->setChecked(projectConfig.getUsePoryScript()); ui->checkBox_ShowWildEncounterTables->setChecked(userConfig.getEncounterJsonActive()); ui->checkBox_CreateTextFile->setChecked(projectConfig.getCreateMapTextFileEnabled()); @@ -106,71 +154,107 @@ void ProjectSettingsEditor::initUi() { ui->checkBox_OutputCallback->setChecked(projectConfig.getTilesetsHaveCallback()); ui->checkBox_OutputIsCompressed->setChecked(projectConfig.getTilesetsHaveIsCompressed()); - // Init spinners - ui->spinBox_Elevation->setRange(0, 15); + // Set spin box values ui->spinBox_Elevation->setValue(projectConfig.getNewMapElevation()); + ui->spinBox_FillMetatile->setValue(projectConfig.getNewMapMetatileId()); + ui->spinBox_BehaviorMask->setValue(projectConfig.getMetatileBehaviorMask()); + ui->spinBox_EncounterTypeMask->setValue(projectConfig.getMetatileEncounterTypeMask()); + ui->spinBox_LayerTypeMask->setValue(projectConfig.getMetatileLayerTypeMask()); + ui->spinBox_TerrainTypeMask->setValue(projectConfig.getMetatileTerrainTypeMask()); - // Init text boxes - // TODO: Validator for Border Metatiles and Fill Metatile + // Set line edit texts ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString()); - ui->lineEdit_FillMetatile->setText(projectConfig.getNewMapMetatileIdString()); ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath(false)); - QString mask = ProjectConfig::getMaskString(projectConfig.getMetatileBehaviorMask()); - ui->lineEdit_BehaviorMask->setText(mask); - mask = ProjectConfig::getMaskString(projectConfig.getMetatileEncounterTypeMask()); - ui->lineEdit_EncounterTypeMask->setText(mask); - mask = ProjectConfig::getMaskString(projectConfig.getMetatileLayerTypeMask()); - ui->lineEdit_LayerTypeMask->setText(mask); - mask = ProjectConfig::getMaskString(projectConfig.getMetatileTerrainTypeMask()); - ui->lineEdit_TerrainTypeMask->setText(mask); } +// TODO: Certain setting changes may require project reload + void ProjectSettingsEditor::saveFields() { - // TODO - /* - TODO combo_defaultPrimaryTileset - TODO combo_defaultSecondaryTileset - setBaseGameVersion combo_baseGameVersion - TODO combo_attributesSize - setUsePoryScript ui->checkBox_UsePoryscript - userConfig.setEncounterJsonActive ui->checkBox_ShowWildEncounterTables - setCreateMapTextFileEnabled ui->checkBox_CreateTextFile - setPrefabImportPrompted ui->checkBox_PrefabImportPrompted - setTripleLayerMetatilesEnabled ui->checkBox_EnableTripleLayerMetatiles - setHiddenItemRequiresItemfinderEnabled ui->checkBox_EnableRequiresItemfinder - setHiddenItemQuantityEnabled ui->checkBox_EnableQuantity - setEventCloneObjectEnabled ui->checkBox_EnableCloneObjects - setEventWeatherTriggerEnabled ui->checkBox_EnableWeatherTriggers - setEventSecretBaseEnabled ui->checkBox_EnableSecretBases - setHealLocationRespawnDataEnabled ui->checkBox_EnableRespawn - TODO ui->checkBox_EnableAllowFlags - setFloorNumberEnabled ui->checkBox_EnableFloorNumber - setUseCustomBorderSize ui->checkBox_EnableCustomBorderSize - setTilesetsHaveCallback ui->checkBox_OutputCallback - setTilesetsHaveIsCompressed ui->checkBox_OutputIsCompressed - setNewMapElevation ui->spinBox_Elevation - setPrefabFilepath ui->lineEdit_PrefabsPath - TODO ui->lineEdit_BehaviorMask - TODO ui->lineEdit_EncounterTypeMask - TODO ui->lineEdit_LayerTypeMask - TODO ui->lineEdit_TerrainTypeMask - setNewMapMetatileId ui->lineEdit_FillMetatile - setNewMapBorderMetatileIds ui->lineEdit_BorderMetatiles - */ + if (!this->hasUnsavedChanges) + return; + + // Prevent a call to save() for each of the config settings + projectConfig.setSaveDisabled(true); + userConfig.setSaveDisabled(true); + + projectConfig.setDefaultPrimaryTileset(combo_defaultPrimaryTileset->currentText()); + projectConfig.setDefaultSecondaryTileset(combo_defaultSecondaryTileset->currentText()); + projectConfig.setBaseGameVersion(projectConfig.stringToBaseGameVersion(combo_baseGameVersion->currentText())); + projectConfig.setMetatileAttributesSize(combo_attributesSize->currentText().toInt()); + projectConfig.setUsePoryScript(ui->checkBox_UsePoryscript->isChecked()); + userConfig.setEncounterJsonActive(ui->checkBox_ShowWildEncounterTables->isChecked()); + projectConfig.setCreateMapTextFileEnabled(ui->checkBox_CreateTextFile->isChecked()); + projectConfig.setPrefabImportPrompted(ui->checkBox_PrefabImportPrompted->isChecked()); + projectConfig.setTripleLayerMetatilesEnabled(ui->checkBox_EnableTripleLayerMetatiles->isChecked()); + projectConfig.setHiddenItemRequiresItemfinderEnabled(ui->checkBox_EnableRequiresItemfinder->isChecked()); + projectConfig.setHiddenItemQuantityEnabled(ui->checkBox_EnableQuantity->isChecked()); + projectConfig.setEventCloneObjectEnabled(ui->checkBox_EnableCloneObjects->isChecked()); + projectConfig.setEventWeatherTriggerEnabled(ui->checkBox_EnableWeatherTriggers->isChecked()); + projectConfig.setEventSecretBaseEnabled(ui->checkBox_EnableSecretBases->isChecked()); + projectConfig.setHealLocationRespawnDataEnabled(ui->checkBox_EnableRespawn->isChecked()); + projectConfig.setMapAllowFlagsEnabled(ui->checkBox_EnableAllowFlags->isChecked()); + projectConfig.setFloorNumberEnabled(ui->checkBox_EnableFloorNumber->isChecked()); + projectConfig.setUseCustomBorderSize(ui->checkBox_EnableCustomBorderSize->isChecked()); + projectConfig.setTilesetsHaveCallback(ui->checkBox_OutputCallback->isChecked()); + projectConfig.setTilesetsHaveIsCompressed(ui->checkBox_OutputIsCompressed->isChecked()); + projectConfig.setNewMapElevation(ui->spinBox_Elevation->value()); + projectConfig.setNewMapMetatileId(ui->spinBox_FillMetatile->value()); + projectConfig.setMetatileBehaviorMask(ui->spinBox_BehaviorMask->value()); + projectConfig.setMetatileTerrainTypeMask(ui->spinBox_EncounterTypeMask->value()); + projectConfig.setMetatileEncounterTypeMask(ui->spinBox_LayerTypeMask->value()); + projectConfig.setMetatileLayerTypeMask(ui->spinBox_TerrainTypeMask->value()); + projectConfig.setPrefabFilepath(ui->lineEdit_PrefabsPath->text()); + + // Parse border metatile list + QList metatileIdStrings = ui->lineEdit_BorderMetatiles->text().split(","); + QList metatileIds; + for (auto s : metatileIdStrings) { + uint16_t metatileId = s.toUInt(nullptr, 0); + metatileIds.append(qMin(metatileId, static_cast(Project::getNumMetatilesTotal() - 1))); + } + projectConfig.setNewMapBorderMetatileIds(metatileIds); + + projectConfig.setSaveDisabled(false); + projectConfig.save(); + userConfig.setSaveDisabled(false); + userConfig.save(); + + this->hasUnsavedChanges = false; emit saved(); } +// TODO: Standard prompt replacement? +bool ProjectSettingsEditor::prompt(const QString &text) { + QMessageBox messageBox(this); + messageBox.setText(text); + messageBox.setIcon(QMessageBox::Question); + messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); // TODO: Cancel + return messageBox.exec() == QMessageBox::Yes; +} + void ProjectSettingsEditor::dialogButtonClicked(QAbstractButton *button) { auto buttonRole = ui->buttonBox->buttonRole(button); if (buttonRole == QDialogButtonBox::AcceptRole) { - // TODO: Prompt for unsaved changes saveFields(); close(); - } else if (buttonRole == QDialogButtonBox::ResetRole) { - // TODO } else if (buttonRole == QDialogButtonBox::ApplyRole) { saveFields(); + } else if (buttonRole == QDialogButtonBox::ResetRole) { + // Restore Defaults + // TODO: Confirm dialogue? + const QString versionText = combo_baseGameVersion->currentText(); + if (!prompt(QString("Restore default config settings for %1?").arg(versionText))) + return; + projectConfig.reset(projectConfig.stringToBaseGameVersion(versionText)); + projectConfig.save(); + userConfig.reset(); + userConfig.save(); + refresh(); } else if (buttonRole == QDialogButtonBox::RejectRole) { + if (this->hasUnsavedChanges && !prompt(QString("Discard unsaved changes?"))) { + // TODO: + // Unsaved changes prompt + } close(); } // TODO: Save geometry on close diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index e8fc6be51..8c4d67e15 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -348,8 +348,7 @@ void TilesetEditor::drawSelectedTiles() { void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) { QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset); - QString hexString = QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper(); - QString message = QString("Metatile: 0x%1").arg(hexString); + QString message = QString("Metatile: %1").arg(Metatile::getMetatileIdString(metatileId)); if (label.size() != 0) { message += QString(" \"%1\"").arg(label); } From 871a6ed9b7072b64a319c8f8fbcb505c61921047 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 28 Aug 2023 21:02:52 -0400 Subject: [PATCH 11/34] Add prompts to project settings editor --- forms/projectsettingseditor.ui | 207 +++++++++++++++---------- include/config.h | 4 + include/ui/projectsettingseditor.h | 17 ++- src/config.cpp | 23 ++- src/mainwindow.cpp | 4 +- src/ui/projectsettingseditor.cpp | 232 ++++++++++++++++------------- 6 files changed, 299 insertions(+), 188 deletions(-) diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index 529992eac..ed152444b 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -29,7 +29,7 @@ 0 0 544 - 994 + 1096 @@ -64,6 +64,28 @@ Default Tilesets + + + + + Primary Tileset + + + + + + + + + + Secondary Tileset + + + + + + + @@ -163,6 +185,16 @@ Prefabs + + + + + + + Prefab import prompted + + + @@ -170,16 +202,17 @@ - - + + - Prefab import prompted + ... + + + + :/icons/folder.ico:/icons/folder.ico - - - @@ -208,11 +241,20 @@ - + - - + + + Base game version + + + + + + + false + @@ -237,39 +279,19 @@ Tilesets / Metatiles - - - - The number of bytes used per metatile for metatile attributes - - - Attributes size (in bytes) - - - - - + + Qt::Vertical 20 - 15 + 10 - - - - The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. - - - Terrain Type mask - - - @@ -277,44 +299,68 @@ - - + + + + 0x + + + 16 + + - - + + - Whether the C data outputted for new tilesets will include the "isCompressed" field + The number of bytes used per metatile for metatile attributes - Output 'isCompressed' field + Attributes size (in bytes) - + + + The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. + + + Terrain Type mask + + + + + + + false + + + + + Qt::Vertical 20 - 10 + 15 - - - - 0x + + + + The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. - - 16 + + Behavior mask - - + + 0x @@ -323,58 +369,58 @@ - - + + - The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. + Whether the C data outputted for new tilesets will include the "callback" field - Encounter Type mask + Output 'callback' field - - + + - Whether the C data outputted for new tilesets will include the "callback" field + Whether the C data outputted for new tilesets will include the "isCompressed" field - Output 'callback' field + Output 'isCompressed' field - - - - The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. + + + + 0x - - Behavior mask + + 16 - + - The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. + The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. - Layer Type mask + Encounter Type mask - - - - 0x + + + + The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. - - 16 + + Layer Type mask - - + + 0x @@ -509,13 +555,22 @@ - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults - + + + NoScrollComboBox + QComboBox +
noscrollcombobox.h
+
+
+ + + diff --git a/include/config.h b/include/config.h index 72d42bbf5..86650d227 100644 --- a/include/config.h +++ b/include/config.h @@ -73,6 +73,7 @@ class PorymapConfig: public KeyValueConfigBase void setTilesetEditorGeometry(QByteArray, QByteArray); void setPaletteEditorGeometry(QByteArray, QByteArray); void setRegionMapEditorGeometry(QByteArray, QByteArray); + void setProjectSettingsEditorGeometry(QByteArray, QByteArray); void setCollisionOpacity(int opacity); void setMetatilesZoom(int zoom); void setShowPlayerView(bool enabled); @@ -93,6 +94,7 @@ class PorymapConfig: public KeyValueConfigBase QMap getTilesetEditorGeometry(); QMap getPaletteEditorGeometry(); QMap getRegionMapEditorGeometry(); + QMap getProjectSettingsEditorGeometry(); int getCollisionOpacity(); int getMetatilesZoom(); bool getShowPlayerView(); @@ -129,6 +131,8 @@ class PorymapConfig: public KeyValueConfigBase QByteArray paletteEditorState; QByteArray regionMapEditorGeometry; QByteArray regionMapEditorState; + QByteArray projectSettingsEditorGeometry; + QByteArray projectSettingsEditorState; int collisionOpacity; int metatilesZoom; bool showPlayerView; diff --git a/include/ui/projectsettingseditor.h b/include/ui/projectsettingseditor.h index 6e1f7ed58..180fb3667 100644 --- a/include/ui/projectsettingseditor.h +++ b/include/ui/projectsettingseditor.h @@ -21,26 +21,29 @@ class ProjectSettingsEditor : public QMainWindow ~ProjectSettingsEditor(); signals: - void saved(); + void reloadProject(); private: Ui::ProjectSettingsEditor *ui; Project *project; - NoScrollComboBox *combo_defaultPrimaryTileset; - NoScrollComboBox *combo_defaultSecondaryTileset; - NoScrollComboBox *combo_baseGameVersion; - NoScrollComboBox *combo_attributesSize; bool hasUnsavedChanges = false; + bool projectNeedsReload = false; + bool refreshing = false; void initUi(); - void saveFields(); void connectSignals(); + void restoreWindowState(); + void save(); void refresh(); - bool prompt(const QString &text); + void closeEvent(QCloseEvent*); + int prompt(const QString &, QMessageBox::StandardButton = QMessageBox::Yes); + bool promptSaveChanges(); + bool promptRestoreDefaults(); private slots: void dialogButtonClicked(QAbstractButton *button); + void choosePrefabsFileClicked(bool); void markEdited(); }; diff --git a/src/config.cpp b/src/config.cpp index 037511ee9..89fff4799 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -234,6 +234,10 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->regionMapEditorGeometry = bytesFromString(value); } else if (key == "region_map_editor_state") { this->regionMapEditorState = bytesFromString(value); + } else if (key == "project_settings_editor_geometry") { + this->projectSettingsEditorGeometry = bytesFromString(value); + } else if (key == "project_settings_editor_state") { + this->projectSettingsEditorState = bytesFromString(value); } else if (key == "metatiles_zoom") { this->metatilesZoom = getConfigInteger(key, value, 10, 100, 30); } else if (key == "show_player_view") { @@ -280,6 +284,8 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("palette_editor_state", stringFromByteArray(this->paletteEditorState)); map.insert("region_map_editor_geometry", stringFromByteArray(this->regionMapEditorGeometry)); map.insert("region_map_editor_state", stringFromByteArray(this->regionMapEditorState)); + map.insert("project_settings_editor_geometry", stringFromByteArray(this->projectSettingsEditorGeometry)); + map.insert("project_settings_editor_state", stringFromByteArray(this->projectSettingsEditorState)); map.insert("collision_opacity", QString("%1").arg(this->collisionOpacity)); map.insert("metatiles_zoom", QString("%1").arg(this->metatilesZoom)); map.insert("show_player_view", this->showPlayerView ? "1" : "0"); @@ -370,6 +376,12 @@ void PorymapConfig::setRegionMapEditorGeometry(QByteArray regionMapEditorGeometr this->save(); } +void PorymapConfig::setProjectSettingsEditorGeometry(QByteArray projectSettingsEditorGeometry_, QByteArray projectSettingsEditorState_) { + this->projectSettingsEditorGeometry = projectSettingsEditorGeometry_; + this->projectSettingsEditorState = projectSettingsEditorState_; + this->save(); +} + void PorymapConfig::setCollisionOpacity(int opacity) { this->collisionOpacity = opacity; // don't auto-save here because this can be called very frequently. @@ -473,6 +485,15 @@ QMap PorymapConfig::getRegionMapEditorGeometry() { return geometry; } +QMap PorymapConfig::getProjectSettingsEditorGeometry() { + QMap geometry; + + geometry.insert("project_settings_editor_geometry", this->projectSettingsEditorGeometry); + geometry.insert("project_settings_editor_state", this->projectSettingsEditorState); + + return geometry; +} + int PorymapConfig::getCollisionOpacity() { return this->collisionOpacity; } @@ -658,7 +679,7 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { // Restore config to version-specific defaults void::ProjectConfig::reset(BaseGameVersion baseGameVersion) { this->reset(); - this->setBaseGameVersion(baseGameVersion); + this->baseGameVersion = baseGameVersion; this->setUnreadKeys(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b40f5ef0f..92186032d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2738,8 +2738,8 @@ void MainWindow::togglePreferenceSpecificUi() { void MainWindow::on_actionEdit_Project_Settings_triggered() { if (!this->projectSettingsEditor) { this->projectSettingsEditor = new ProjectSettingsEditor(this, this->editor->project); - connect(this->projectSettingsEditor, &ProjectSettingsEditor::saved, - this, &MainWindow::togglePreferenceSpecificUi); + connect(this->projectSettingsEditor, &ProjectSettingsEditor::reloadProject, + this, &MainWindow::on_action_Reload_Project_triggered); } if (!this->projectSettingsEditor->isVisible()) { diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index 5aeb9debc..a492c9eb8 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -13,17 +13,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) : QMainWindow(parent), ui(new Ui::ProjectSettingsEditor), - project(project), - combo_defaultPrimaryTileset(nullptr), - combo_defaultSecondaryTileset(nullptr), - combo_baseGameVersion(nullptr), - combo_attributesSize(nullptr) + project(project) { ui->setupUi(this); - initUi(); setAttribute(Qt::WA_DeleteOnClose); - connectSignals(); - refresh(); + this->initUi(); + this->connectSignals(); + this->refresh(); + this->restoreWindowState(); } ProjectSettingsEditor::~ProjectSettingsEditor() @@ -31,13 +28,17 @@ ProjectSettingsEditor::~ProjectSettingsEditor() delete ui; } +// TODO: Move tool tips to editable areas + void ProjectSettingsEditor::connectSignals() { connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked); + connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked); // Connect combo boxes QList combos = ui->centralwidget->findChildren(); foreach(auto i, combos) connect(i, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited); + connect(ui->comboBox_BaseGameVersion, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::promptRestoreDefaults); // Connect check boxes QList checkboxes = ui->centralwidget->findChildren(); @@ -56,85 +57,50 @@ void ProjectSettingsEditor::connectSignals() { } void ProjectSettingsEditor::markEdited() { - this->hasUnsavedChanges = true; + // Don't treat signals emitted while the UI is refreshing as edits + if (!this->refreshing) + this->hasUnsavedChanges = true; } void ProjectSettingsEditor::initUi() { - // Create Default Tilesets combo boxes - auto *defaultTilesetsLayout = new QFormLayout(ui->groupBox_DefaultTilesets); - combo_defaultPrimaryTileset = new NoScrollComboBox(ui->groupBox_DefaultTilesets); - combo_defaultSecondaryTileset = new NoScrollComboBox(ui->groupBox_DefaultTilesets); - if (project) combo_defaultPrimaryTileset->addItems(project->primaryTilesetLabels); - if (project) combo_defaultSecondaryTileset->addItems(project->secondaryTilesetLabels); - defaultTilesetsLayout->addRow("Primary Tileset", combo_defaultPrimaryTileset); - defaultTilesetsLayout->addRow("Secondary Tileset", combo_defaultSecondaryTileset); - - // Create Base game version combo box - combo_baseGameVersion = new NoScrollComboBox(ui->widget_BaseGameVersion); - combo_baseGameVersion->addItems(ProjectConfig::versionStrings); - combo_baseGameVersion->setEditable(false); - ui->layout_BaseGameVersion->insertRow(0, "Base game version", combo_baseGameVersion); - - // Create Attributes size combo box - auto *attributesSizeLayout = new QFormLayout(ui->widget_SizeDropdown); - combo_attributesSize = new NoScrollComboBox(ui->widget_SizeDropdown); - combo_attributesSize->addItems({"1", "2", "4"}); - combo_attributesSize->setEditable(false); - attributesSizeLayout->addRow("", combo_attributesSize); - - // Validate that the border metatiles text is a comma-separated list of hex values - static const QRegularExpression expression("^((0[xX])?[A-Fa-f0-9]+,)*(0[xX])?[A-Fa-f0-9]$"); + // Populate combo boxes + if (project) ui->comboBox_DefaultPrimaryTileset->addItems(project->primaryTilesetLabels); + if (project) ui->comboBox_DefaultSecondaryTileset->addItems(project->secondaryTilesetLabels); + ui->comboBox_BaseGameVersion->addItems(ProjectConfig::versionStrings); + ui->comboBox_AttributesSize->addItems({"1", "2", "4"}); + + // Validate that the border metatiles text is a comma-separated list of metatile values + const QString regex_Hex = "(0[xX])?[A-Fa-f0-9]+"; + static const QRegularExpression expression(QString("^(%1,)*%1$").arg(regex_Hex)); // Comma-separated list of hex values QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression); ui->lineEdit_BorderMetatiles->setValidator(validator); ui->spinBox_Elevation->setMaximum(15); ui->spinBox_FillMetatile->setMaximum(Project::getNumMetatilesTotal() - 1); - // TODO: These need to be subclassed to handle larger values + // TODO: These need to be subclassed (or changed to line edits) to handle larger values ui->spinBox_BehaviorMask->setMaximum(INT_MAX); ui->spinBox_EncounterTypeMask->setMaximum(INT_MAX); ui->spinBox_LayerTypeMask->setMaximum(INT_MAX); ui->spinBox_TerrainTypeMask->setMaximum(INT_MAX); +} - // TODO: File picker for prefabs? +void ProjectSettingsEditor::restoreWindowState() { + logInfo("Restoring project settings editor geometry from previous session."); + const QMap geometry = porymapConfig.getProjectSettingsEditorGeometry(); + this->restoreGeometry(geometry.value("project_settings_editor_geometry")); + this->restoreState(geometry.value("project_settings_editor_state")); } // Set UI states using config data void ProjectSettingsEditor::refresh() { - const QSignalBlocker blocker0(combo_defaultPrimaryTileset); - const QSignalBlocker blocker1(combo_defaultSecondaryTileset); - const QSignalBlocker blocker2(combo_baseGameVersion); - const QSignalBlocker blocker3(combo_attributesSize); - const QSignalBlocker blocker4(ui->checkBox_UsePoryscript); - const QSignalBlocker blocker5(ui->checkBox_ShowWildEncounterTables); - const QSignalBlocker blocker6(ui->checkBox_CreateTextFile); - const QSignalBlocker blocker7(ui->checkBox_PrefabImportPrompted); - const QSignalBlocker blocker8(ui->checkBox_EnableTripleLayerMetatiles); - const QSignalBlocker blocker9(ui->checkBox_EnableRequiresItemfinder); - const QSignalBlocker blockerA(ui->checkBox_EnableQuantity); - const QSignalBlocker blockerB(ui->checkBox_EnableCloneObjects); - const QSignalBlocker blockerC(ui->checkBox_EnableWeatherTriggers); - const QSignalBlocker blockerD(ui->checkBox_EnableSecretBases); - const QSignalBlocker blockerE(ui->checkBox_EnableRespawn); - const QSignalBlocker blockerF(ui->checkBox_EnableAllowFlags); - const QSignalBlocker blocker10(ui->checkBox_EnableFloorNumber); - const QSignalBlocker blocker11(ui->checkBox_EnableCustomBorderSize); - const QSignalBlocker blocker12(ui->checkBox_OutputCallback); - const QSignalBlocker blocker13(ui->checkBox_OutputIsCompressed); - const QSignalBlocker blocker14(ui->spinBox_Elevation); - const QSignalBlocker blocker15(ui->spinBox_FillMetatile); - const QSignalBlocker blocker16(ui->spinBox_BehaviorMask); - const QSignalBlocker blocker17(ui->spinBox_EncounterTypeMask); - const QSignalBlocker blocker18(ui->spinBox_LayerTypeMask); - const QSignalBlocker blocker19(ui->spinBox_TerrainTypeMask); - const QSignalBlocker blocker1A(ui->lineEdit_BorderMetatiles); - const QSignalBlocker blocker1B(ui->lineEdit_PrefabsPath); + this->refreshing = true; // Block signals // Set combo box texts - combo_defaultPrimaryTileset->setTextItem(projectConfig.getDefaultPrimaryTileset()); - combo_defaultSecondaryTileset->setTextItem(projectConfig.getDefaultSecondaryTileset()); - combo_baseGameVersion->setTextItem(projectConfig.getBaseGameVersionString()); - combo_attributesSize->setTextItem(QString::number(projectConfig.getMetatileAttributesSize())); + ui->comboBox_DefaultPrimaryTileset->setTextItem(projectConfig.getDefaultPrimaryTileset()); + ui->comboBox_DefaultSecondaryTileset->setTextItem(projectConfig.getDefaultSecondaryTileset()); + ui->comboBox_BaseGameVersion->setTextItem(projectConfig.getBaseGameVersionString()); + ui->comboBox_AttributesSize->setTextItem(QString::number(projectConfig.getMetatileAttributesSize())); // Set check box states ui->checkBox_UsePoryscript->setChecked(projectConfig.getUsePoryScript()); @@ -165,11 +131,11 @@ void ProjectSettingsEditor::refresh() { // Set line edit texts ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString()); ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath(false)); -} -// TODO: Certain setting changes may require project reload + this->refreshing = false; // Allow signals +} -void ProjectSettingsEditor::saveFields() { +void ProjectSettingsEditor::save() { if (!this->hasUnsavedChanges) return; @@ -177,10 +143,10 @@ void ProjectSettingsEditor::saveFields() { projectConfig.setSaveDisabled(true); userConfig.setSaveDisabled(true); - projectConfig.setDefaultPrimaryTileset(combo_defaultPrimaryTileset->currentText()); - projectConfig.setDefaultSecondaryTileset(combo_defaultSecondaryTileset->currentText()); - projectConfig.setBaseGameVersion(projectConfig.stringToBaseGameVersion(combo_baseGameVersion->currentText())); - projectConfig.setMetatileAttributesSize(combo_attributesSize->currentText().toInt()); + projectConfig.setDefaultPrimaryTileset(ui->comboBox_DefaultPrimaryTileset->currentText()); + projectConfig.setDefaultSecondaryTileset(ui->comboBox_DefaultSecondaryTileset->currentText()); + projectConfig.setBaseGameVersion(projectConfig.stringToBaseGameVersion(ui->comboBox_BaseGameVersion->currentText())); + projectConfig.setMetatileAttributesSize(ui->comboBox_AttributesSize->currentText().toInt()); projectConfig.setUsePoryScript(ui->checkBox_UsePoryscript->isChecked()); userConfig.setEncounterJsonActive(ui->checkBox_ShowWildEncounterTables->isChecked()); projectConfig.setCreateMapTextFileEnabled(ui->checkBox_CreateTextFile->isChecked()); @@ -200,9 +166,9 @@ void ProjectSettingsEditor::saveFields() { projectConfig.setNewMapElevation(ui->spinBox_Elevation->value()); projectConfig.setNewMapMetatileId(ui->spinBox_FillMetatile->value()); projectConfig.setMetatileBehaviorMask(ui->spinBox_BehaviorMask->value()); - projectConfig.setMetatileTerrainTypeMask(ui->spinBox_EncounterTypeMask->value()); - projectConfig.setMetatileEncounterTypeMask(ui->spinBox_LayerTypeMask->value()); - projectConfig.setMetatileLayerTypeMask(ui->spinBox_TerrainTypeMask->value()); + projectConfig.setMetatileTerrainTypeMask(ui->spinBox_TerrainTypeMask->value()); + projectConfig.setMetatileEncounterTypeMask(ui->spinBox_EncounterTypeMask->value()); + projectConfig.setMetatileLayerTypeMask(ui->spinBox_LayerTypeMask->value()); projectConfig.setPrefabFilepath(ui->lineEdit_PrefabsPath->text()); // Parse border metatile list @@ -218,44 +184,106 @@ void ProjectSettingsEditor::saveFields() { projectConfig.save(); userConfig.setSaveDisabled(false); userConfig.save(); - this->hasUnsavedChanges = false; - emit saved(); + + // Technically, a reload is not required for several of the config settings. + // For simplicity we prompt the user to reload when any setting is changed regardless. + this->projectNeedsReload = true; +} + +void ProjectSettingsEditor::choosePrefabsFileClicked(bool) { + QString startPath = this->project->importExportPath; + QFileInfo fileInfo(ui->lineEdit_PrefabsPath->text()); + if (fileInfo.exists() && fileInfo.isFile() && fileInfo.suffix() == "json") { + // Current setting is a valid JSON file. Start the file dialog there + startPath = fileInfo.dir().absolutePath(); + } + QString filepath = QFileDialog::getOpenFileName(this, "Choose Prefabs File", startPath, "JSON Files (*.json)"); + if (filepath.isEmpty()) + return; + this->project->setImportExportPath(filepath); + ui->lineEdit_PrefabsPath->setText(filepath); + ui->checkBox_PrefabImportPrompted->setChecked(true); + this->hasUnsavedChanges = true; } -// TODO: Standard prompt replacement? -bool ProjectSettingsEditor::prompt(const QString &text) { +int ProjectSettingsEditor::prompt(const QString &text, QMessageBox::StandardButton defaultButton) { QMessageBox messageBox(this); messageBox.setText(text); messageBox.setIcon(QMessageBox::Question); - messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); // TODO: Cancel - return messageBox.exec() == QMessageBox::Yes; + messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | defaultButton); + messageBox.setDefaultButton(defaultButton); + return messageBox.exec(); +} + +bool ProjectSettingsEditor::promptSaveChanges() { + if (!this->hasUnsavedChanges) + return true; + + int result = this->prompt("Settings have been modified, save changes?", QMessageBox::Cancel); + if (result == QMessageBox::Cancel) + return false; + + if (result == QMessageBox::Yes) + this->save(); + else if (result == QMessageBox::No) + this->hasUnsavedChanges = false; // Discarding changes + + return true; +} + +bool ProjectSettingsEditor::promptRestoreDefaults() { + if (this->refreshing) + return false; + + const QString versionText = ui->comboBox_BaseGameVersion->currentText(); + if (this->prompt(QString("Restore default config settings for %1?").arg(versionText)) == QMessageBox::No) + return false; + + // Restore defaults by resetting config in memory, refreshing the UI, then restoring the config. + // Don't want to save changes until user accepts them. + ProjectConfig tempProject = projectConfig; + UserConfig tempUser = userConfig; + projectConfig.reset(projectConfig.stringToBaseGameVersion(versionText)); + userConfig.reset(); + this->refresh(); + projectConfig = tempProject; + userConfig = tempUser; + + this->hasUnsavedChanges = true; + return true; } void ProjectSettingsEditor::dialogButtonClicked(QAbstractButton *button) { auto buttonRole = ui->buttonBox->buttonRole(button); if (buttonRole == QDialogButtonBox::AcceptRole) { - saveFields(); + // "OK" button + this->save(); close(); - } else if (buttonRole == QDialogButtonBox::ApplyRole) { - saveFields(); - } else if (buttonRole == QDialogButtonBox::ResetRole) { - // Restore Defaults - // TODO: Confirm dialogue? - const QString versionText = combo_baseGameVersion->currentText(); - if (!prompt(QString("Restore default config settings for %1?").arg(versionText))) - return; - projectConfig.reset(projectConfig.stringToBaseGameVersion(versionText)); - projectConfig.save(); - userConfig.reset(); - userConfig.save(); - refresh(); } else if (buttonRole == QDialogButtonBox::RejectRole) { - if (this->hasUnsavedChanges && !prompt(QString("Discard unsaved changes?"))) { - // TODO: - // Unsaved changes prompt - } + // "Cancel" button + if (!this->promptSaveChanges()) + return; close(); + } else if (buttonRole == QDialogButtonBox::ResetRole) { + // "Restore Defaults" button + this->promptRestoreDefaults(); } - // TODO: Save geometry on close +} + +void ProjectSettingsEditor::closeEvent(QCloseEvent* event) { + if (!this->promptSaveChanges()) { + event->ignore(); + return; + } + + if (this->projectNeedsReload) { + if (this->prompt("Settings changed, reload project to apply changes?") == QMessageBox::Yes) + emit this->reloadProject(); + } + + porymapConfig.setProjectSettingsEditorGeometry( + this->saveGeometry(), + this->saveState() + ); } From 143e5cf79be6b5cbad201fb5686e07b30f41b119 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 31 Aug 2023 13:47:13 -0400 Subject: [PATCH 12/34] Add button to import default prefabs --- forms/projectsettingseditor.ui | 34 +++++++------- include/config.h | 3 +- include/ui/prefab.h | 2 +- include/ui/projectsettingseditor.h | 1 + src/config.cpp | 14 ++++-- src/mainwindow.cpp | 7 ++- src/ui/prefab.cpp | 73 ++++++++++++++++++------------ src/ui/projectsettingseditor.cpp | 18 ++++++-- 8 files changed, 94 insertions(+), 58 deletions(-) diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index ed152444b..f2e86018f 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -29,7 +29,7 @@ 0 0 544 - 1096 + 1107 @@ -185,31 +185,31 @@ Prefabs - - - - - + + - Prefab import prompted + ... + + + + :/icons/folder.ico:/icons/folder.ico - - + + - Prefabs Path + Import Defaults - - + + + + + - ... - - - - :/icons/folder.ico:/icons/folder.ico + Prefabs Path diff --git a/include/config.h b/include/config.h index 86650d227..7ffcca38c 100644 --- a/include/config.h +++ b/include/config.h @@ -228,6 +228,7 @@ class ProjectConfig: public KeyValueConfigBase void setBaseGameVersion(BaseGameVersion baseGameVersion); BaseGameVersion getBaseGameVersion(); QString getBaseGameVersionString(); + QString getBaseGameVersionString(BaseGameVersion version); BaseGameVersion stringToBaseGameVersion(QString string, bool * ok = nullptr); void setUsePoryScript(bool usePoryScript); bool getUsePoryScript(); @@ -269,7 +270,7 @@ class ProjectConfig: public KeyValueConfigBase void setFilePath(ProjectFilePath pathId, QString path); QString getFilePath(ProjectFilePath pathId); void setPrefabFilepath(QString filepath); - QString getPrefabFilepath(bool setIfEmpty); + QString getPrefabFilepath(); void setPrefabImportPrompted(bool prompted); bool getPrefabImportPrompted(); void setTilesetsHaveCallback(bool has); diff --git a/include/ui/prefab.h b/include/ui/prefab.h index 00b2d7144..7bd9e0b24 100644 --- a/include/ui/prefab.h +++ b/include/ui/prefab.h @@ -23,7 +23,7 @@ class Prefab void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map); void addPrefab(MetatileSelection selection, Map *map, QString name); void updatePrefabUi(Map *map); - void tryImportDefaultPrefabs(Map *map); + bool tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath = ""); private: MetatileSelector *selector; diff --git a/include/ui/projectsettingseditor.h b/include/ui/projectsettingseditor.h index 180fb3667..03b3d14d7 100644 --- a/include/ui/projectsettingseditor.h +++ b/include/ui/projectsettingseditor.h @@ -44,6 +44,7 @@ class ProjectSettingsEditor : public QMainWindow private slots: void dialogButtonClicked(QAbstractButton *button); void choosePrefabsFileClicked(bool); + void importDefaultPrefabsClicked(bool); void markEdited(); }; diff --git a/src/config.cpp b/src/config.cpp index 89fff4799..7541a8949 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -801,8 +801,15 @@ BaseGameVersion ProjectConfig::getBaseGameVersion() { return this->baseGameVersion; } +QString ProjectConfig::getBaseGameVersionString(BaseGameVersion version) { + if (!baseGameVersionMap.contains(version)) { + version = BaseGameVersion::pokeemerald; + } + return baseGameVersionMap.value(version); +} + QString ProjectConfig::getBaseGameVersionString() { - return baseGameVersionMap.value(this->baseGameVersion); + return this->getBaseGameVersionString(this->baseGameVersion); } void ProjectConfig::setUsePoryScript(bool usePoryScript) { @@ -970,10 +977,7 @@ void ProjectConfig::setPrefabFilepath(QString filepath) { this->save(); } -QString ProjectConfig::getPrefabFilepath(bool setIfEmpty) { - if (setIfEmpty && this->prefabFilepath.isEmpty()) { - this->setPrefabFilepath("prefabs.json"); - } +QString ProjectConfig::getPrefabFilepath() { return this->prefabFilepath; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 92186032d..71283bc6c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1678,7 +1678,12 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index) editor->setEditingCollision(); } else if (index == 2) { editor->setEditingMap(); - prefab.tryImportDefaultPrefabs(this->editor->map); + if (projectConfig.getPrefabFilepath().isEmpty() && !projectConfig.getPrefabImportPrompted()) { + // User hasn't set up prefabs and hasn't been prompted before. + // Ask if they'd like to import the default prefabs file. + if (prefab.tryImportDefaultPrefabs(this, projectConfig.getBaseGameVersion())) + prefab.updatePrefabUi(this->editor->map); + } } editor->setCursorRectVisible(false); } diff --git a/src/ui/prefab.cpp b/src/ui/prefab.cpp index 87bae5181..9ad154f25 100644 --- a/src/ui/prefab.cpp +++ b/src/ui/prefab.cpp @@ -19,9 +19,11 @@ using OrderedJson = poryjson::Json; using OrderedJsonDoc = poryjson::JsonDoc; +const QString defaultFilepath = "prefabs.json"; + void Prefab::loadPrefabs() { this->items.clear(); - QString filepath = projectConfig.getPrefabFilepath(false); + QString filepath = projectConfig.getPrefabFilepath(); if (filepath.isEmpty()) return; ParseUtil parser; @@ -85,8 +87,11 @@ void Prefab::loadPrefabs() { } void Prefab::savePrefabs() { - QString filepath = projectConfig.getPrefabFilepath(true); - if (filepath.isEmpty()) return; + QString filepath = projectConfig.getPrefabFilepath(); + if (filepath.isEmpty()) { + filepath = defaultFilepath; + projectConfig.setPrefabFilepath(filepath); + } QFileInfo info(filepath); if (info.isRelative()) { @@ -269,48 +274,58 @@ void Prefab::addPrefab(MetatileSelection selection, Map *map, QString name) { this->updatePrefabUi(map); } -void Prefab::tryImportDefaultPrefabs(Map *map) { - BaseGameVersion version = projectConfig.getBaseGameVersion(); +bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath) { // Ensure we have default prefabs for the project's game version. if (version != BaseGameVersion::pokeruby && version != BaseGameVersion::pokeemerald && version != BaseGameVersion::pokefirered) - return; - - // Exit early if the user has already setup prefabs. - if (!projectConfig.getPrefabFilepath(false).isEmpty()) - return; + return false; + + if (filepath.isEmpty()) + filepath = defaultFilepath; + + // Get the absolute filepath for writing/warnings + QString absFilepath; + QFileInfo fileInfo(filepath); + if (fileInfo.suffix().isEmpty()) + filepath += ".json"; + if (fileInfo.isRelative()) { + absFilepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath); + } else { + absFilepath = filepath; + } - // Exit early if the user has already gone through this import prompt before. - if (projectConfig.getPrefabImportPrompted()) - return; + // The warning message when importing defaults changes if there's a pre-existing file. + QString fileWarning; + if (!QFileInfo::exists(absFilepath)) { + fileWarning = QString("This will create a file called '%1'").arg(absFilepath); + } else { + fileWarning = QString("This will overwrite any existing prefabs in '%1'").arg(absFilepath); + } // Display a dialog box to the user, asking if the default prefabs should be imported // into their project. QMessageBox::StandardButton prompt = - QMessageBox::question(nullptr, + QMessageBox::question(parent, "Import Default Prefabs", - QString("Would you like to import the default prefabs for %1? This will create a file called 'prefabs.json' in your project directory.") - .arg(projectConfig.getBaseGameVersionString()), + QString("Would you like to import the default prefabs for %1? %2.") + .arg(projectConfig.getBaseGameVersionString(version)) + .arg(fileWarning), QMessageBox::Yes | QMessageBox::No); - if (prompt == QMessageBox::Yes) { + bool acceptedImport = (prompt == QMessageBox::Yes); + if (acceptedImport) { // Sets up the default prefabs.json filepath. - QString filepath = projectConfig.getPrefabFilepath(true); - - QFileInfo info(filepath); - if (info.isRelative()) { - filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath); - } - QFile prefabsFile(filepath); + projectConfig.setPrefabFilepath(filepath); + QFile prefabsFile(absFilepath); if (!prefabsFile.open(QIODevice::WriteOnly)) { projectConfig.setPrefabFilepath(QString()); - logError(QString("Error: Could not open %1 for writing").arg(filepath)); - QMessageBox messageBox; + logError(QString("Error: Could not open %1 for writing").arg(absFilepath)); + QMessageBox messageBox(parent); messageBox.setText("Failed to import default prefabs file!"); - messageBox.setInformativeText(QString("Could not open \"%1\" for writing").arg(filepath)); + messageBox.setInformativeText(QString("Could not open \"%1\" for writing").arg(absFilepath)); messageBox.setIcon(QMessageBox::Warning); messageBox.exec(); - return; + return false; } ParseUtil parser; @@ -330,10 +345,10 @@ void Prefab::tryImportDefaultPrefabs(Map *map) { prefabsFile.write(content.toUtf8()); prefabsFile.close(); this->loadPrefabs(); - this->updatePrefabUi(map); } projectConfig.setPrefabImportPrompted(true); + return acceptedImport; } Prefab prefab; diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index a492c9eb8..48428624a 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -2,6 +2,7 @@ #include "ui_projectsettingseditor.h" #include "config.h" #include "noscrollcombobox.h" +#include "prefab.h" #include #include @@ -31,8 +32,10 @@ ProjectSettingsEditor::~ProjectSettingsEditor() // TODO: Move tool tips to editable areas void ProjectSettingsEditor::connectSignals() { + // Connect buttons connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked); connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked); + connect(ui->button_ImportDefaultPrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::importDefaultPrefabsClicked); // Connect combo boxes QList combos = ui->centralwidget->findChildren(); @@ -106,7 +109,6 @@ void ProjectSettingsEditor::refresh() { ui->checkBox_UsePoryscript->setChecked(projectConfig.getUsePoryScript()); ui->checkBox_ShowWildEncounterTables->setChecked(userConfig.getEncounterJsonActive()); ui->checkBox_CreateTextFile->setChecked(projectConfig.getCreateMapTextFileEnabled()); - ui->checkBox_PrefabImportPrompted->setChecked(projectConfig.getPrefabImportPrompted()); ui->checkBox_EnableTripleLayerMetatiles->setChecked(projectConfig.getTripleLayerMetatilesEnabled()); ui->checkBox_EnableRequiresItemfinder->setChecked(projectConfig.getHiddenItemRequiresItemfinderEnabled()); ui->checkBox_EnableQuantity->setChecked(projectConfig.getHiddenItemQuantityEnabled()); @@ -130,7 +132,7 @@ void ProjectSettingsEditor::refresh() { // Set line edit texts ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString()); - ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath(false)); + ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath()); this->refreshing = false; // Allow signals } @@ -150,7 +152,6 @@ void ProjectSettingsEditor::save() { projectConfig.setUsePoryScript(ui->checkBox_UsePoryscript->isChecked()); userConfig.setEncounterJsonActive(ui->checkBox_ShowWildEncounterTables->isChecked()); projectConfig.setCreateMapTextFileEnabled(ui->checkBox_CreateTextFile->isChecked()); - projectConfig.setPrefabImportPrompted(ui->checkBox_PrefabImportPrompted->isChecked()); projectConfig.setTripleLayerMetatilesEnabled(ui->checkBox_EnableTripleLayerMetatiles->isChecked()); projectConfig.setHiddenItemRequiresItemfinderEnabled(ui->checkBox_EnableRequiresItemfinder->isChecked()); projectConfig.setHiddenItemQuantityEnabled(ui->checkBox_EnableQuantity->isChecked()); @@ -203,10 +204,19 @@ void ProjectSettingsEditor::choosePrefabsFileClicked(bool) { return; this->project->setImportExportPath(filepath); ui->lineEdit_PrefabsPath->setText(filepath); - ui->checkBox_PrefabImportPrompted->setChecked(true); this->hasUnsavedChanges = true; } +void ProjectSettingsEditor::importDefaultPrefabsClicked(bool) { + // If the prompt is accepted the prefabs file will be created and its filepath will be saved in the config. + // No need to set hasUnsavedChanges here. + BaseGameVersion version = projectConfig.stringToBaseGameVersion(ui->comboBox_BaseGameVersion->currentText()); + if (prefab.tryImportDefaultPrefabs(this, version, ui->lineEdit_PrefabsPath->text())) { + ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath()); // Refresh with new filepath + this->projectNeedsReload = true; + } +} + int ProjectSettingsEditor::prompt(const QString &text, QMessageBox::StandardButton defaultButton) { QMessageBox messageBox(this); messageBox.setText(text); From d6d27ae8b33dbba6db661b875b4926dab64aa2c9 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 1 Sep 2023 14:00:09 -0400 Subject: [PATCH 13/34] Add Custom Scripts Editor window --- forms/customscriptseditor.ui | 164 ++++++++++++++++++++ forms/customscriptslistitem.ui | 87 +++++++++++ forms/mainwindow.ui | 6 + include/config.h | 6 +- include/editor.h | 8 +- include/mainwindow.h | 4 + include/ui/customscriptseditor.h | 60 ++++++++ include/ui/customscriptslistitem.h | 22 +++ porymap.pro | 8 +- resources/icons/edit_document.ico | Bin 0 -> 1675 bytes resources/icons/refresh.ico | Bin 0 -> 1664 bytes resources/images.qrc | 2 + src/config.cpp | 8 +- src/editor.cpp | 6 +- src/mainwindow.cpp | 81 ++++------ src/ui/customscriptseditor.cpp | 231 +++++++++++++++++++++++++++++ src/ui/customscriptslistitem.cpp | 14 ++ src/ui/projectsettingseditor.cpp | 38 ++--- 18 files changed, 651 insertions(+), 94 deletions(-) create mode 100644 forms/customscriptseditor.ui create mode 100644 forms/customscriptslistitem.ui create mode 100644 include/ui/customscriptseditor.h create mode 100644 include/ui/customscriptslistitem.h create mode 100755 resources/icons/edit_document.ico create mode 100755 resources/icons/refresh.ico create mode 100644 src/ui/customscriptseditor.cpp create mode 100644 src/ui/customscriptslistitem.cpp diff --git a/forms/customscriptseditor.ui b/forms/customscriptseditor.ui new file mode 100644 index 000000000..12acb3320 --- /dev/null +++ b/forms/customscriptseditor.ui @@ -0,0 +1,164 @@ + + + CustomScriptsEditor + + + + 0 + 0 + 374 + 355 + + + + Custom Scripts Editor + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Add New Script... + + + + :/icons/add.ico:/icons/add.ico + + + + + + + Reload Scripts + + + + :/icons/refresh.ico:/icons/refresh.ico + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + <html><head/><body><p><a href="https://huderlem.github.io/porymap/manual/scripting-capabilities.html"><span style=" text-decoration: underline; color:#0000ff;">What are custom scripts?</span></a></p></body></html> + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 20 + 5 + + + + + + + + Scripts + + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::NoDragDrop + + + Qt::IgnoreAction + + + QAbstractItemView::ExtendedSelection + + + Qt::ElideLeft + + + QListView::Free + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + + + diff --git a/forms/customscriptslistitem.ui b/forms/customscriptslistitem.ui new file mode 100644 index 000000000..5784b442f --- /dev/null +++ b/forms/customscriptslistitem.ui @@ -0,0 +1,87 @@ + + + CustomScriptsListItem + + + + 0 + 0 + 129 + 30 + + + + + 0 + 0 + + + + + 4 + + + 4 + + + + + + 1 + 0 + + + + + + + + + + + Choose a new filepath for this script + + + ... + + + + :/icons/folder.ico:/icons/folder.ico + + + + + + + Open this script file + + + ... + + + + :/icons/edit_document.ico:/icons/edit_document.ico + + + + + + + Remove this script + + + ... + + + + :/icons/delete.ico:/icons/delete.ico + + + + + + + + + + diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index f153538ca..f23028b69 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -3018,6 +3018,7 @@ + @@ -3314,6 +3315,11 @@ Edit Project Settings... + + + Custom Scripts... + + diff --git a/include/config.h b/include/config.h index 7ffcca38c..f715e36cd 100644 --- a/include/config.h +++ b/include/config.h @@ -348,8 +348,8 @@ class UserConfig: public KeyValueConfigBase bool getEncounterJsonActive(); void setProjectDir(QString projectDir); QString getProjectDir(); - void setCustomScripts(QList scripts); - QList getCustomScripts(); + void setCustomScripts(QStringList scripts); + QStringList getCustomScripts(); protected: virtual QString getConfigFilepath() override; virtual void parseConfigKeyValue(QString key, QString value) override; @@ -363,7 +363,7 @@ class UserConfig: public KeyValueConfigBase QString projectDir; QString recentMap; bool useEncounterJson; - QList customScripts; + QStringList customScripts; QStringList readKeys; }; diff --git a/include/editor.h b/include/editor.h index e28d91208..2282fba71 100644 --- a/include/editor.h +++ b/include/editor.h @@ -149,7 +149,7 @@ class Editor : public QObject void shouldReselectEvents(); void scaleMapView(int); - void openInTextEditor(const QString &path, int lineNum = 0) const; + static void openInTextEditor(const QString &path, int lineNum = 0); bool eventLimitReached(Event::Type type); public slots: @@ -179,9 +179,9 @@ public slots: void updateEncounterFields(EncounterFields newFields); QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMetatileDisplayMessage(uint16_t metatileId); - bool startDetachedProcess(const QString &command, - const QString &workingDirectory = QString(), - qint64 *pid = nullptr) const; + static bool startDetachedProcess(const QString &command, + const QString &workingDirectory = QString(), + qint64 *pid = nullptr); private slots: void onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); diff --git a/include/mainwindow.h b/include/mainwindow.h index 32bb03eb8..4ccaa6ff7 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -26,6 +26,7 @@ #include "shortcutseditor.h" #include "preferenceeditor.h" #include "projectsettingseditor.h" +#include "customscriptseditor.h" @@ -286,6 +287,7 @@ private slots: void on_actionEdit_Preferences_triggered(); void togglePreferenceSpecificUi(); void on_actionEdit_Project_Settings_triggered(); + void on_actionCustom_Scripts_triggered(); public: Ui::MainWindow *ui; @@ -300,6 +302,7 @@ private slots: QPointer newMapPrompt = nullptr; QPointer preferenceEditor = nullptr; QPointer projectSettingsEditor = nullptr; + QPointer customScriptsEditor = nullptr; FilterChildrenProxyModel *mapListProxyModel; QStandardItemModel *mapListModel; QList *mapGroupItemsList; @@ -343,6 +346,7 @@ private slots: bool loadProjectCombos(); bool populateMapList(); void sortMapList(); + void openSubWindow(QWidget * window); QString getExistingDirectory(QString); bool openProject(QString dir); QString getDefaultMap(); diff --git a/include/ui/customscriptseditor.h b/include/ui/customscriptseditor.h new file mode 100644 index 000000000..1d8b88c29 --- /dev/null +++ b/include/ui/customscriptseditor.h @@ -0,0 +1,60 @@ +#ifndef CUSTOMSCRIPTSEDITOR_H +#define CUSTOMSCRIPTSEDITOR_H + +#include +#include +#include +#include + +#include "customscriptslistitem.h" + +namespace Ui { +class CustomScriptsEditor; +} + + +class CustomScriptsEditor : public QMainWindow +{ + Q_OBJECT + +public: + explicit CustomScriptsEditor(QWidget *parent = nullptr); + ~CustomScriptsEditor(); + +signals: + void reloadScriptEngine(); + +private: + Ui::CustomScriptsEditor *ui; + + bool hasUnsavedChanges = false; + QString importDir; + const QString baseDir; + + void displayScript(const QString &filepath); + QString chooseScript(QString dir); + + void removeScript(QListWidgetItem * item); + void replaceScript(QListWidgetItem * item); + void openScript(QListWidgetItem * item); + + QString getListItemFilepath(QListWidgetItem * item) const; + void setListItemFilepath(QListWidgetItem * item, QString filepath) const; + + int prompt(const QString &text, QMessageBox::StandardButton defaultButton); + void save(); + void closeEvent(QCloseEvent*); + + void initShortcuts(); + QObjectList shortcutableObjects() const; + void applyUserShortcuts(); + +private slots: + void dialogButtonClicked(QAbstractButton *button); + void addNewScript(); + void reloadScripts(); + void removeSelectedScripts(); + void openSelectedScripts(); +}; + +#endif // CUSTOMSCRIPTSEDITOR_H diff --git a/include/ui/customscriptslistitem.h b/include/ui/customscriptslistitem.h new file mode 100644 index 000000000..d166db8a1 --- /dev/null +++ b/include/ui/customscriptslistitem.h @@ -0,0 +1,22 @@ +#ifndef CUSTOMSCRIPTSLISTITEM_H +#define CUSTOMSCRIPTSLISTITEM_H + +#include + +namespace Ui { +class CustomScriptsListItem; +} + +class CustomScriptsListItem : public QFrame +{ + Q_OBJECT + +public: + explicit CustomScriptsListItem(QWidget *parent = nullptr); + ~CustomScriptsListItem(); + +public: + Ui::CustomScriptsListItem *ui; +}; + +#endif // CUSTOMSCRIPTSLISTITEM_H diff --git a/porymap.pro b/porymap.pro index 4728f1779..4a2a20081 100644 --- a/porymap.pro +++ b/porymap.pro @@ -42,6 +42,8 @@ SOURCES += src/core/block.cpp \ src/scriptapi/apiutility.cpp \ src/scriptapi/scripting.cpp \ src/ui/aboutporymap.cpp \ + src/ui/customscriptseditor.cpp \ + src/ui/customscriptslistitem.cpp \ src/ui/draggablepixmapitem.cpp \ src/ui/bordermetatilespixmapitem.cpp \ src/ui/collisionpixmapitem.cpp \ @@ -129,6 +131,8 @@ HEADERS += include/core/block.h \ include/lib/orderedmap.h \ include/lib/orderedjson.h \ include/ui/aboutporymap.h \ + include/ui/customscriptseditor.h \ + include/ui/customscriptslistitem.h \ include/ui/draggablepixmapitem.h \ include/ui/bordermetatilespixmapitem.h \ include/ui/collisionpixmapitem.h \ @@ -204,7 +208,9 @@ FORMS += forms/mainwindow.ui \ forms/preferenceeditor.ui \ forms/regionmappropertiesdialog.ui \ forms/colorpicker.ui \ - forms/projectsettingseditor.ui + forms/projectsettingseditor.ui \ + forms/customscriptseditor.ui \ + forms/customscriptslistitem.ui RESOURCES += \ resources/images.qrc \ diff --git a/resources/icons/edit_document.ico b/resources/icons/edit_document.ico new file mode 100755 index 0000000000000000000000000000000000000000..cd4bb026137a915d7478de409c616f9952501e85 GIT binary patch literal 1675 zcmV;626Xv}P)6i>#fJ}@g}2A>p=fkB!F{b7BR_vF zispS>fu5v*D}Cn7e{JIZ`}c9Gyu9R%Idf*yqiKWhD?H?Nxt(}fpNvLNGn(8jh`v*U z=e~I}N~HzSj0Nnzb^8uELW<0OdUr_5U>qzg#Jst4F?rIY^rGUDyRXkmAIx2|r?AwU zHsUGt?Gumu1A8$|ei1D#Ug&-=e?3m-i)^>cvMfYVlrD+AUYsTM4u=!{`}fEAaTAjY z%1&PU>Eje{OmrN2#rMXIx|>Ms`#6f4%FyqRT8!E8?il`_8fp!<-rle)jjy+eH#V7K zVq;P7Xhu>(Ukol^l$y4D0n(C_vAy6NRDUzBU%w7BN=91lk_oi@9!awtzF~L7=5v&; zA+C2E&SfRx`DOEgq)ec46P6hZQFreFWIY<&H*MzNw>V`u3Bx=fN6Z0xed?3LQCNBc zPn=nd3E7K)flGj@4Zw|K~=EaI63C%H!yNhMyWFfBic(Y83i zJo?w*F%?|N8bFpWYy+<&aM{A{pHuM8&d$LF@k1X}MT4fsLQ|qhaaHuudOT+B=t;lv zIl1-RWtpNt)uBYkqjvQmOjy3K&Fyt%A{XUeN!niWirNd@Z=?JmNNr6l?hn7=Ng!&fp6W^8F&W;7%UuL z!SHI1gjmW^uWXfY^nC_D^P;Gz09USFCb>f3F(^55oWKVKzz2qc`;k+Xhz0qzVo%HP zK9a}@-xn7%-sQ-Bc5d<0aiAn;?N?r`w8_SeGnc)=_m50EakFcRv}DQWPYvs@KX5RK_yYtS{C z*L1jUUqtFlt6|(Nhtc98%Y6bo^FS?~87WB~ltL0z#0pH?q9H~nU@ew<4O73AaCS8V z5g&hEEyb`D$_2k41AFibs_Xtj-laq=C2+~0NFh%s!2;D)1=RMn)k4K8hAEpQoc@&h z4b-m+U*Noen?Y8D66mxcvnsSV6j@04H7`;ow zq`>zgd7|kbmyz@)8A8%0q72gYFV}|Ph1Bsd1vLJR7W&EjA2)t8X(sV^_T%3I3;>il V-yZDPnl}Id002ovPDHLkV1k)VA`Jil literal 0 HcmV?d00001 diff --git a/resources/icons/refresh.ico b/resources/icons/refresh.ico new file mode 100755 index 0000000000000000000000000000000000000000..fdf20e26cd11305fd5cb59a633da930067ee30eb GIT binary patch literal 1664 zcmV-`27md9P)+8^?#X=0li+or^58?{(eDn76k ztkFc+79S{&738tJ7FhN<({pF;D&j7?HKdbVc9%PI&v(9a&UelLV|#_HJqRWDOO(=g zDVPUzV+GQ%;I0Lfez_kY^IIXzM9Q2n1!pk3H zJt5yvkhu|dT|G=~-%vbh!$2PC1cV!6U=WQIei1so4!!m|)xgM0Ci>k@emJ3Sd#mf*8;X$3{2SToS7#f?=a7u1dQeG_W}r^ zWHL;e+Cv#{rDV_m%#O;$u`7qr--eT9`~ltfhQrY^(;DGYC{Ovr}0=NjtFN7V#p zeWk~yGU8zR6U;myvf+Xa86GW1!UIvidM9Sh-Gm#Pm*v427KtWH8Ec@>k-OwP9#SE@ z2k=KQ^MJ^P3N~D@A*13!5q#-6Gn%s>%bYfNNV*Hj$h(`Cufft;FXB$?kFa^H5cO&V zRJ!kX0d2Q%m@z4hYMlD`OLLH)k+ek}GT5;3%09IF>H%!FnmuzeVxuFmDj^fb&@kL> zFM-8&NA;XN!+L|Mg+O@V{QDHDnWjj7X(!_;^N^pFRDfH}N3c5KD}4RtT8g1WnJPTh z`(#IwT6walz~!-_YoHGITPomK82%}J@=$_OzGwNN;ct060zd?1~jmsB`@D|--_Qyb&K-tcQ2sTWxS-@*l z4wNv%lY$;nv!00=sY&@wqTYorGR`Erla>R1CRStIa;%UdI%bZa;L!wM&|<7(U_?L5 zJEVx}$OtM~$n;ztb&xAHlx+j3Dc^(Fx#zuJe|!Ou8Y)pO$724(7ce7wqDCz{n6+7I z#gGg>R)|(o?6Z@OzemzmRZH1!fy-Ql&#oQ9L2kTz_*^LX=?{@io>OPzaCR4R z0!XvM&tQF|kFS0nb0ygK0?%*|o*Ii5um=_Np)EO0000< KMNUMnLSTZocMvN8 literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index 4c739582b..2399cbe9d 100644 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -4,6 +4,7 @@ icons/collapse_all.ico icons/cursor.ico icons/delete.ico + icons/edit_document.ico icons/expand_all.ico icons/fill_color_cursor.ico icons/fill_color.ico @@ -24,6 +25,7 @@ icons/porymap-icon-1.ico icons/porymap-icon-2.ico icons/porymap.icns + icons/refresh.ico icons/shift_cursor.ico icons/shift.ico icons/sort_alphabet.ico diff --git a/src/config.cpp b/src/config.cpp index 7541a8949..d5e7e0fe5 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -647,7 +647,7 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { userConfig.useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { userConfig.customScripts.clear(); - QList paths = value.split(","); + QList paths = value.split(",", Qt::SkipEmptyParts); paths.removeDuplicates(); for (QString script : paths) { if (!script.isEmpty()) { @@ -1077,7 +1077,7 @@ void UserConfig::parseConfigKeyValue(QString key, QString value) { this->useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { this->customScripts.clear(); - QList paths = value.split(","); + QList paths = value.split(",", Qt::SkipEmptyParts); paths.removeDuplicates(); for (QString script : paths) { if (!script.isEmpty()) { @@ -1133,12 +1133,12 @@ bool UserConfig::getEncounterJsonActive() { return this->useEncounterJson; } -void UserConfig::setCustomScripts(QList scripts) { +void UserConfig::setCustomScripts(QStringList scripts) { this->customScripts = scripts; this->save(); } -QList UserConfig::getCustomScripts() { +QStringList UserConfig::getCustomScripts() { return this->customScripts; } diff --git a/src/editor.cpp b/src/editor.cpp index 9996460e4..4dc12885a 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -2146,7 +2146,7 @@ void Editor::openScript(const QString &scriptLabel) const { openInTextEditor(scriptPath, lineNum); } -void Editor::openInTextEditor(const QString &path, int lineNum) const { +void Editor::openInTextEditor(const QString &path, int lineNum) { QString command = porymapConfig.getTextEditorGotoLine(); if (command.isEmpty()) { // Open map scripts in the system's default editor. @@ -2159,7 +2159,7 @@ void Editor::openInTextEditor(const QString &path, int lineNum) const { } else { command += " \"" + path + '\"'; } - startDetachedProcess(command); + Editor::startDetachedProcess(command); } } @@ -2172,7 +2172,7 @@ void Editor::openProjectInTextEditor() const { startDetachedProcess(command); } -bool Editor::startDetachedProcess(const QString &command, const QString &workingDirectory, qint64 *pid) const { +bool Editor::startDetachedProcess(const QString &command, const QString &workingDirectory, qint64 *pid) { logInfo("Executing command: " + command); QProcess process; #ifdef Q_OS_WIN diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 71283bc6c..ef9f90c60 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -590,6 +590,19 @@ QString MainWindow::getDefaultMap() { return QString(); } +void MainWindow::openSubWindow(QWidget * window) { + if (!window) return; + + if (!window->isVisible()) { + window->show(); + } else if (window->isMinimized()) { + window->showNormal(); + } else { + window->raise(); + window->activateWindow(); + } +} + QString MainWindow::getExistingDirectory(QString dir) { return QFileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly); } @@ -1184,12 +1197,9 @@ void MainWindow::openNewMapPopupWindow() { if (!this->newMapPrompt) { this->newMapPrompt = new NewMapPopup(this, this->editor->project); } - if (!this->newMapPrompt->isVisible()) { - this->newMapPrompt->show(); - } else { - this->newMapPrompt->raise(); - this->newMapPrompt->activateWindow(); - } + + openSubWindow(this->newMapPrompt); + connect(this->newMapPrompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated); this->newMapPrompt->setAttribute(Qt::WA_DeleteOnClose); } @@ -1775,14 +1785,7 @@ void MainWindow::on_actionEdit_Shortcuts_triggered() if (!shortcutsEditor) initShortcutsEditor(); - if (shortcutsEditor->isHidden()) { - shortcutsEditor->show(); - } else if (shortcutsEditor->isMinimized()) { - shortcutsEditor->showNormal(); - } else { - shortcutsEditor->raise(); - shortcutsEditor->activateWindow(); - } + openSubWindow(shortcutsEditor); } void MainWindow::initShortcutsEditor() { @@ -2461,13 +2464,7 @@ void MainWindow::showExportMapImageWindow(ImageExporterMode mode) { this->mapImageExporter = new MapImageExporter(this, this->editor, mode); this->mapImageExporter->setAttribute(Qt::WA_DeleteOnClose); - if (!this->mapImageExporter->isVisible()) { - this->mapImageExporter->show(); - } else if (this->mapImageExporter->isMinimized()) { - this->mapImageExporter->showNormal(); - } else { - this->mapImageExporter->activateWindow(); - } + openSubWindow(this->mapImageExporter); } void MainWindow::on_comboBox_ConnectionDirection_currentTextChanged(const QString &direction) @@ -2663,14 +2660,7 @@ void MainWindow::on_actionTileset_Editor_triggered() initTilesetEditor(); } - if (!this->tilesetEditor->isVisible()) { - this->tilesetEditor->show(); - } else if (this->tilesetEditor->isMinimized()) { - this->tilesetEditor->showNormal(); - } else { - this->tilesetEditor->raise(); - this->tilesetEditor->activateWindow(); - } + openSubWindow(this->tilesetEditor); MetatileSelection selection = this->editor->metatile_selector_item->getMetatileSelection(); this->tilesetEditor->selectMetatile(selection.metatileItems.first().metatileId); @@ -2723,14 +2713,7 @@ void MainWindow::on_actionEdit_Preferences_triggered() { this, &MainWindow::togglePreferenceSpecificUi); } - if (!preferenceEditor->isVisible()) { - preferenceEditor->show(); - } else if (preferenceEditor->isMinimized()) { - preferenceEditor->showNormal(); - } else { - preferenceEditor->raise(); - preferenceEditor->activateWindow(); - } + openSubWindow(preferenceEditor); } void MainWindow::togglePreferenceSpecificUi() { @@ -2747,14 +2730,15 @@ void MainWindow::on_actionEdit_Project_Settings_triggered() { this, &MainWindow::on_action_Reload_Project_triggered); } - if (!this->projectSettingsEditor->isVisible()) { - this->projectSettingsEditor->show(); - } else if (this->projectSettingsEditor->isMinimized()) { - this->projectSettingsEditor->showNormal(); - } else { - this->projectSettingsEditor->raise(); - this->projectSettingsEditor->activateWindow(); + openSubWindow(this->projectSettingsEditor); +} + +void MainWindow::on_actionCustom_Scripts_triggered() { + if (!this->customScriptsEditor) { + this->customScriptsEditor = new CustomScriptsEditor(this); } + + openSubWindow(this->customScriptsEditor); } void MainWindow::on_pushButton_AddCustomHeaderField_clicked() @@ -2806,14 +2790,7 @@ void MainWindow::on_actionRegion_Map_Editor_triggered() { } } - if (!this->regionMapEditor->isVisible()) { - this->regionMapEditor->show(); - } else if (this->regionMapEditor->isMinimized()) { - this->regionMapEditor->showNormal(); - } else { - this->regionMapEditor->raise(); - this->regionMapEditor->activateWindow(); - } + openSubWindow(this->regionMapEditor); } void MainWindow::on_pushButton_CreatePrefab_clicked() { diff --git a/src/ui/customscriptseditor.cpp b/src/ui/customscriptseditor.cpp new file mode 100644 index 000000000..36babd51f --- /dev/null +++ b/src/ui/customscriptseditor.cpp @@ -0,0 +1,231 @@ +#include "customscriptseditor.h" +#include "ui_customscriptseditor.h" +#include "ui_customscriptslistitem.h" +#include "config.h" +#include "editor.h" +#include "shortcut.h" + +#include +#include + +// TODO: System for turning scripts on or off +// +// TODO: Better URL colors on dark themes +// TODO: Save window state + +CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::CustomScriptsEditor), + baseDir(userConfig.getProjectDir() + QDir::separator()) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + // This property seems to be reset if we don't set it programmatically + ui->list->setDragDropMode(QAbstractItemView::NoDragDrop); + + for (auto path : userConfig.getCustomScripts()) + this->displayScript(path); + + this->importDir = userConfig.getProjectDir(); + + connect(ui->button_AddNewScript, &QAbstractButton::clicked, this, &CustomScriptsEditor::addNewScript); + connect(ui->button_ReloadScripts, &QAbstractButton::clicked, this, &CustomScriptsEditor::reloadScripts); + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &CustomScriptsEditor::dialogButtonClicked); + + this->initShortcuts(); +} + +CustomScriptsEditor::~CustomScriptsEditor() +{ + ui->list->clear(); + delete ui; +} + +void CustomScriptsEditor::initShortcuts() { + auto *shortcut_remove = new Shortcut({QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(removeSelectedScripts())); + shortcut_remove->setObjectName("shortcut_remove"); + shortcut_remove->setWhatsThis("Remove Selected Scripts"); + + // TODO: Prevent ambiguity with MainWindow + auto *shortcut_open = new Shortcut(QKeySequence("Ctrl+O"), this, SLOT(openSelectedScripts())); + shortcut_open->setObjectName("shortcut_open"); + shortcut_open->setWhatsThis("Open Selected Scripts"); + + auto *shortcut_addNew = new Shortcut(QKeySequence(), this, SLOT(addNewScript())); + shortcut_addNew->setObjectName("shortcut_addNew"); + shortcut_addNew->setWhatsThis("Add New Script..."); + + auto *shortcut_reload = new Shortcut(QKeySequence(), this, SLOT(reloadScripts())); + shortcut_reload->setObjectName("shortcut_reload"); + shortcut_reload->setWhatsThis("Reload Scripts"); + + //connect(new QShortcut(QKeySequence("Backspace"), this), &QShortcut::activated, this, &CustomScriptsEditor::removeSelectedScripts); + //connect(new QShortcut(QKeySequence("Ctrl+O"), this), &QShortcut::activated, this, &CustomScriptsEditor::openSelectedScripts); + + shortcutsConfig.load(); + shortcutsConfig.setDefaultShortcuts(shortcutableObjects()); + applyUserShortcuts(); +} + +QObjectList CustomScriptsEditor::shortcutableObjects() const { + QObjectList shortcutable_objects; + + for (auto *action : findChildren()) + if (!action->objectName().isEmpty()) + shortcutable_objects.append(qobject_cast(action)); + for (auto *shortcut : findChildren()) + if (!shortcut->objectName().isEmpty()) + shortcutable_objects.append(qobject_cast(shortcut)); + + return shortcutable_objects; +} + +// TODO: Connect to shorcuts editor +void CustomScriptsEditor::applyUserShortcuts() { + for (auto *action : findChildren()) + if (!action->objectName().isEmpty()) + action->setShortcuts(shortcutsConfig.userShortcuts(action)); + for (auto *shortcut : findChildren()) + if (!shortcut->objectName().isEmpty()) + shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut)); +} + +void CustomScriptsEditor::displayScript(const QString &filepath) { + auto item = new QListWidgetItem(); + auto buttons = new CustomScriptsListItem(); + + buttons->ui->lineEdit_filepath->setText(filepath); + item->setSizeHint(buttons->sizeHint()); + + connect(buttons->ui->b_Choose, &QAbstractButton::clicked, [this, item](bool) { this->replaceScript(item); }); + connect(buttons->ui->b_Edit, &QAbstractButton::clicked, [this, item](bool) { this->openScript(item); }); + connect(buttons->ui->b_Delete, &QAbstractButton::clicked, [this, item](bool) { this->removeScript(item); }); + connect(buttons->ui->lineEdit_filepath, &QLineEdit::textEdited, [this](const QString&) { this->hasUnsavedChanges = true; }); + + // Per the Qt manual, for performance reasons QListWidget::setItemWidget shouldn't be used with non-static items. + // There's an assumption here that users won't have enough scripts for that to be a problem. + ui->list->addItem(item); + ui->list->setItemWidget(item, buttons); +} + +QString CustomScriptsEditor::getListItemFilepath(QListWidgetItem * item) const { + auto widget = dynamic_cast(ui->list->itemWidget(item)); + if (!widget) return QString(); + + QString path = widget->ui->lineEdit_filepath->text(); + QFileInfo fileInfo(path); + if (fileInfo.isRelative()) + path.prepend(this->baseDir); + return path; +} + +void CustomScriptsEditor::setListItemFilepath(QListWidgetItem * item, QString filepath) const { + auto widget = dynamic_cast(ui->list->itemWidget(item)); + if (!widget) return; + + if (filepath.startsWith(this->baseDir)) + filepath.remove(0, this->baseDir.length()); + widget->ui->lineEdit_filepath->setText(filepath); +} + +QString CustomScriptsEditor::chooseScript(QString dir) { + return QFileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)"); +} + +void CustomScriptsEditor::addNewScript() { + QString filepath = this->chooseScript(this->importDir); + if (filepath.isEmpty()) + return; + this->importDir = filepath; + if (filepath.startsWith(this->baseDir)) + filepath.remove(0, this->baseDir.length()); + this->displayScript(filepath); + this->hasUnsavedChanges = true; +} + +void CustomScriptsEditor::removeScript(QListWidgetItem * item) { + ui->list->takeItem(ui->list->row(item)); + this->hasUnsavedChanges = true; +} + +void CustomScriptsEditor::removeSelectedScripts() { + QList items = ui->list->selectedItems(); + if (items.length() == 0) + return; + for (auto item : items) + this->removeScript(item); +} + +void CustomScriptsEditor::replaceScript(QListWidgetItem * item) { + const QString filepath = this->chooseScript(this->getListItemFilepath(item)); + if (filepath.isEmpty()) + return; + this->setListItemFilepath(item, filepath); + this->hasUnsavedChanges = true; +} + +void CustomScriptsEditor::openScript(QListWidgetItem * item) { + const QString path = this->getListItemFilepath(item); + QFileInfo fileInfo(path); + if (!fileInfo.exists() || !fileInfo.isFile()){ + QMessageBox::warning(this, "", QString("Failed to open script '%1'").arg(path)); + return; + } + Editor::openInTextEditor(path); +} + +void CustomScriptsEditor::openSelectedScripts() { + for (auto item : ui->list->selectedItems()) + this->openScript(item); +} + +void CustomScriptsEditor::reloadScripts() { + if (this->hasUnsavedChanges) { + if (this->prompt("Scripts have been modified, save changes and reload the script engine?", QMessageBox::Yes) == QMessageBox::No) + return; + this->save(); + } + emit reloadScriptEngine(); // TODO: Catch this signal +} + +void CustomScriptsEditor::save() { + if (!this->hasUnsavedChanges) + return; + // TODO: Set new paths in config + this->hasUnsavedChanges = false; + this->reloadScripts(); +} + +int CustomScriptsEditor::prompt(const QString &text, QMessageBox::StandardButton defaultButton) { + QMessageBox messageBox(this); + messageBox.setText(text); + messageBox.setIcon(QMessageBox::Question); + messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | defaultButton); + messageBox.setDefaultButton(defaultButton); + return messageBox.exec(); +} + +void CustomScriptsEditor::dialogButtonClicked(QAbstractButton *button) { + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) + this->save(); + close(); // All buttons (OK and Cancel) close the window +} + +void CustomScriptsEditor::closeEvent(QCloseEvent* event) { + if (this->hasUnsavedChanges) { + int result = this->prompt("Scripts have been modified, save changes?", QMessageBox::Cancel); + if (result == QMessageBox::Cancel) { + event->ignore(); + return; + } + if (result == QMessageBox::Yes) + this->save(); + } +/* + // TODO + porymapConfig.setProjectSettingsEditorGeometry( + this->saveGeometry(), + this->saveState() + ); +*/ +} diff --git a/src/ui/customscriptslistitem.cpp b/src/ui/customscriptslistitem.cpp new file mode 100644 index 000000000..e14524253 --- /dev/null +++ b/src/ui/customscriptslistitem.cpp @@ -0,0 +1,14 @@ +#include "customscriptslistitem.h" +#include "ui_customscriptslistitem.h" + +CustomScriptsListItem::CustomScriptsListItem(QWidget *parent) : + QFrame(parent), + ui(new Ui::CustomScriptsListItem) +{ + ui->setupUi(this); +} + +CustomScriptsListItem::~CustomScriptsListItem() +{ + delete ui; +} diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index 48428624a..bf8d17aed 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -8,7 +8,7 @@ #include /* - Editor for the settings in a user's porymap.project.cfg and porymap.user.cfg files. + Editor for the settings in a user's porymap.project.cfg file (and 'use_encounter_json' in porymap.user.cfg). */ ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) : @@ -32,31 +32,20 @@ ProjectSettingsEditor::~ProjectSettingsEditor() // TODO: Move tool tips to editable areas void ProjectSettingsEditor::connectSignals() { - // Connect buttons connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked); connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked); connect(ui->button_ImportDefaultPrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::importDefaultPrefabsClicked); - - // Connect combo boxes - QList combos = ui->centralwidget->findChildren(); - foreach(auto i, combos) - connect(i, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited); connect(ui->comboBox_BaseGameVersion, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::promptRestoreDefaults); - // Connect check boxes - QList checkboxes = ui->centralwidget->findChildren(); - foreach(auto i, checkboxes) - connect(i, &QCheckBox::stateChanged, this, &ProjectSettingsEditor::markEdited); - - // Connect spin boxes - QList spinBoxes = ui->centralwidget->findChildren(); - foreach(auto i, spinBoxes) - connect(i, QOverload::of(&QSpinBox::valueChanged), [this](int) { this->markEdited(); }); - - // Connect line edits - QList lineEdits = ui->centralwidget->findChildren(); - foreach(auto i, lineEdits) - connect(i, &QLineEdit::textEdited, this, &ProjectSettingsEditor::markEdited); + // Record that there are unsaved changes if any of the settings are modified + for (auto combo : ui->centralwidget->findChildren()) + connect(combo, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited); + for (auto checkBox : ui->centralwidget->findChildren()) + connect(checkBox, &QCheckBox::stateChanged, this, &ProjectSettingsEditor::markEdited); + for (auto spinBox : ui->centralwidget->findChildren()) + connect(spinBox, QOverload::of(&QSpinBox::valueChanged), [this](int) { this->markEdited(); }); + for (auto lineEdit : ui->centralwidget->findChildren()) + connect(lineEdit, &QLineEdit::textEdited, this, &ProjectSettingsEditor::markEdited); } void ProjectSettingsEditor::markEdited() { @@ -143,7 +132,6 @@ void ProjectSettingsEditor::save() { // Prevent a call to save() for each of the config settings projectConfig.setSaveDisabled(true); - userConfig.setSaveDisabled(true); projectConfig.setDefaultPrimaryTileset(ui->comboBox_DefaultPrimaryTileset->currentText()); projectConfig.setDefaultSecondaryTileset(ui->comboBox_DefaultSecondaryTileset->currentText()); @@ -183,8 +171,6 @@ void ProjectSettingsEditor::save() { projectConfig.setSaveDisabled(false); projectConfig.save(); - userConfig.setSaveDisabled(false); - userConfig.save(); this->hasUnsavedChanges = false; // Technically, a reload is not required for several of the config settings. @@ -192,6 +178,7 @@ void ProjectSettingsEditor::save() { this->projectNeedsReload = true; } +// TODO: If the selected file is in the project directory use a relative path void ProjectSettingsEditor::choosePrefabsFileClicked(bool) { QString startPath = this->project->importExportPath; QFileInfo fileInfo(ui->lineEdit_PrefabsPath->text()); @@ -253,12 +240,9 @@ bool ProjectSettingsEditor::promptRestoreDefaults() { // Restore defaults by resetting config in memory, refreshing the UI, then restoring the config. // Don't want to save changes until user accepts them. ProjectConfig tempProject = projectConfig; - UserConfig tempUser = userConfig; projectConfig.reset(projectConfig.stringToBaseGameVersion(versionText)); - userConfig.reset(); this->refresh(); projectConfig = tempProject; - userConfig = tempUser; this->hasUnsavedChanges = true; return true; From 40e8824eca2fef428971ae63c62c65faaa75466a Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 5 Sep 2023 17:02:35 -0400 Subject: [PATCH 14/34] Add option to turn custom scripts on/off --- forms/customscriptslistitem.ui | 27 +++++++----- include/config.h | 9 ++-- include/ui/customscriptseditor.h | 9 ++-- src/config.cpp | 66 +++++++++++++++++++--------- src/scriptapi/apiutility.cpp | 2 +- src/scriptapi/scripting.cpp | 7 ++- src/ui/customscriptseditor.cpp | 74 +++++++++++++++++++++----------- 7 files changed, 127 insertions(+), 67 deletions(-) diff --git a/forms/customscriptslistitem.ui b/forms/customscriptslistitem.ui index 5784b442f..c6040aa11 100644 --- a/forms/customscriptslistitem.ui +++ b/forms/customscriptslistitem.ui @@ -7,7 +7,7 @@ 0 0 129 - 30 + 34 @@ -23,6 +23,20 @@ 4 + + + + Choose a new filepath for this script + + + ... + + + + :/icons/folder.ico:/icons/folder.ico + + + @@ -37,16 +51,9 @@ - - - Choose a new filepath for this script - + - ... - - - - :/icons/folder.ico:/icons/folder.ico + diff --git a/include/config.h b/include/config.h index f715e36cd..8ce5e2d28 100644 --- a/include/config.h +++ b/include/config.h @@ -348,8 +348,11 @@ class UserConfig: public KeyValueConfigBase bool getEncounterJsonActive(); void setProjectDir(QString projectDir); QString getProjectDir(); - void setCustomScripts(QStringList scripts); - QStringList getCustomScripts(); + void setCustomScripts(QStringList scripts, QList enabled); + QStringList getCustomScriptPaths(); + QList getCustomScriptsEnabled(); + void parseCustomScripts(QString input); + QString outputCustomScripts(); protected: virtual QString getConfigFilepath() override; virtual void parseConfigKeyValue(QString key, QString value) override; @@ -363,7 +366,7 @@ class UserConfig: public KeyValueConfigBase QString projectDir; QString recentMap; bool useEncounterJson; - QStringList customScripts; + QMap customScripts; QStringList readKeys; }; diff --git a/include/ui/customscriptseditor.h b/include/ui/customscriptseditor.h index 1d8b88c29..a2482fc31 100644 --- a/include/ui/customscriptseditor.h +++ b/include/ui/customscriptseditor.h @@ -31,16 +31,17 @@ class CustomScriptsEditor : public QMainWindow QString importDir; const QString baseDir; - void displayScript(const QString &filepath); + void displayScript(const QString &filepath, bool enabled); QString chooseScript(QString dir); void removeScript(QListWidgetItem * item); void replaceScript(QListWidgetItem * item); void openScript(QListWidgetItem * item); + QString getScriptFilepath(QListWidgetItem * item, bool absolutePath = true) const; + void setScriptFilepath(QListWidgetItem * item, QString filepath) const; + bool getScriptEnabled(QListWidgetItem * item) const; - QString getListItemFilepath(QListWidgetItem * item) const; - void setListItemFilepath(QListWidgetItem * item, QString filepath) const; - + void markEdited(); int prompt(const QString &text, QMessageBox::StandardButton defaultButton); void save(); void closeEvent(QCloseEvent*); diff --git a/src/config.cpp b/src/config.cpp index d5e7e0fe5..6e2193f2c 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -646,14 +646,7 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { } else if (key == "use_encounter_json") { userConfig.useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { - userConfig.customScripts.clear(); - QList paths = value.split(",", Qt::SkipEmptyParts); - paths.removeDuplicates(); - for (QString script : paths) { - if (!script.isEmpty()) { - userConfig.customScripts.append(script); - } - } + userConfig.parseCustomScripts(value); #endif } else if (key.startsWith("path/")) { auto k = reverseDefaultPaths(key.mid(5)); @@ -1076,14 +1069,7 @@ void UserConfig::parseConfigKeyValue(QString key, QString value) { } else if (key == "use_encounter_json") { this->useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { - this->customScripts.clear(); - QList paths = value.split(",", Qt::SkipEmptyParts); - paths.removeDuplicates(); - for (QString script : paths) { - if (!script.isEmpty()) { - this->customScripts.append(script); - } - } + this->parseCustomScripts(value); } else { logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); } @@ -1097,7 +1083,7 @@ QMap UserConfig::getKeyValueMap() { QMap map; map.insert("recent_map", this->recentMap); map.insert("use_encounter_json", QString::number(this->useEncounterJson)); - map.insert("custom_scripts", this->customScripts.join(",")); + map.insert("custom_scripts", this->outputCustomScripts()); return map; } @@ -1133,13 +1119,51 @@ bool UserConfig::getEncounterJsonActive() { return this->useEncounterJson; } -void UserConfig::setCustomScripts(QStringList scripts) { - this->customScripts = scripts; +// Read input from the config to get the script paths and whether each is enabled or disbled. +// The format is a comma-separated list of paths. Each path can be followed (before the comma) +// by a :0 or :1 to indicate whether it should be disabled or enabled, respectively. If neither +// follow, it's assumed the script should be enabled. +void UserConfig::parseCustomScripts(QString input) { + this->customScripts.clear(); + QList paths = input.split(",", Qt::SkipEmptyParts); + for (QString path : paths) { + // Read and remove suffix + bool enabled = !path.endsWith(":0"); + if (!enabled || path.endsWith(":1")) + path.chop(2); + + if (!path.isEmpty()) { + // If a path is repeated only its last instance will be considered. + this->customScripts.insert(path, enabled); + } + } +} + +// Inverse of UserConfig::parseCustomScripts +QString UserConfig::outputCustomScripts() { + QStringList list; + QMapIterator i(this->customScripts); + while (i.hasNext()) { + i.next(); + list.append(QString("%1:%2").arg(i.key()).arg(i.value() ? "1" : "0")); + } + return list.join(","); +} + +void UserConfig::setCustomScripts(QStringList scripts, QList enabled) { + this->customScripts.clear(); + size_t size = qMin(scripts.length(), enabled.length()); + for (size_t i = 0; i < size; i++) + this->customScripts.insert(scripts.at(i), enabled.at(i)); this->save(); } -QStringList UserConfig::getCustomScripts() { - return this->customScripts; +QStringList UserConfig::getCustomScriptPaths() { + return this->customScripts.keys(); +} + +QList UserConfig::getCustomScriptsEnabled() { + return this->customScripts.values(); } ShortcutsConfig shortcutsConfig; diff --git a/src/scriptapi/apiutility.cpp b/src/scriptapi/apiutility.cpp index baeb2017d..559e46afe 100644 --- a/src/scriptapi/apiutility.cpp +++ b/src/scriptapi/apiutility.cpp @@ -184,7 +184,7 @@ bool ScriptUtility::getSmartPathsEnabled() { } QList ScriptUtility::getCustomScripts() { - return userConfig.getCustomScripts(); + return userConfig.getCustomScriptPaths(); } QList ScriptUtility::getMetatileLayerOrder() { diff --git a/src/scriptapi/scripting.cpp b/src/scriptapi/scripting.cpp index 9aa6963cd..5ff90d37a 100644 --- a/src/scriptapi/scripting.cpp +++ b/src/scriptapi/scripting.cpp @@ -36,8 +36,11 @@ Scripting::Scripting(MainWindow *mainWindow) { this->mainWindow = mainWindow; this->engine = new QJSEngine(mainWindow); this->engine->installExtensions(QJSEngine::ConsoleExtension); - for (QString script : userConfig.getCustomScripts()) { - this->filepaths.append(script); + const QStringList paths = userConfig.getCustomScriptPaths(); + const QList enabled = userConfig.getCustomScriptsEnabled(); + for (int i = 0; i < paths.length(); i++) { + if (enabled.at(i)) + this->filepaths.append(paths.at(i)); } this->loadModules(this->filepaths); this->scriptUtility = new ScriptUtility(mainWindow); diff --git a/src/ui/customscriptseditor.cpp b/src/ui/customscriptseditor.cpp index 36babd51f..c54ec1c77 100644 --- a/src/ui/customscriptseditor.cpp +++ b/src/ui/customscriptseditor.cpp @@ -8,8 +8,6 @@ #include #include -// TODO: System for turning scripts on or off -// // TODO: Better URL colors on dark themes // TODO: Save window state @@ -23,8 +21,10 @@ CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) : // This property seems to be reset if we don't set it programmatically ui->list->setDragDropMode(QAbstractItemView::NoDragDrop); - for (auto path : userConfig.getCustomScripts()) - this->displayScript(path); + const QStringList paths = userConfig.getCustomScriptPaths(); + const QList enabled = userConfig.getCustomScriptsEnabled(); + for (int i = 0; i < paths.length(); i++) + this->displayScript(paths.at(i), enabled.at(i)); this->importDir = userConfig.getProjectDir(); @@ -90,36 +90,44 @@ void CustomScriptsEditor::applyUserShortcuts() { shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut)); } -void CustomScriptsEditor::displayScript(const QString &filepath) { +void CustomScriptsEditor::displayScript(const QString &filepath, bool enabled) { auto item = new QListWidgetItem(); - auto buttons = new CustomScriptsListItem(); + auto widget = new CustomScriptsListItem(); - buttons->ui->lineEdit_filepath->setText(filepath); - item->setSizeHint(buttons->sizeHint()); + widget->ui->checkBox_Enable->setChecked(enabled); + widget->ui->lineEdit_filepath->setText(filepath); + item->setSizeHint(widget->sizeHint()); - connect(buttons->ui->b_Choose, &QAbstractButton::clicked, [this, item](bool) { this->replaceScript(item); }); - connect(buttons->ui->b_Edit, &QAbstractButton::clicked, [this, item](bool) { this->openScript(item); }); - connect(buttons->ui->b_Delete, &QAbstractButton::clicked, [this, item](bool) { this->removeScript(item); }); - connect(buttons->ui->lineEdit_filepath, &QLineEdit::textEdited, [this](const QString&) { this->hasUnsavedChanges = true; }); + connect(widget->ui->b_Choose, &QAbstractButton::clicked, [this, item](bool) { this->replaceScript(item); }); + connect(widget->ui->b_Edit, &QAbstractButton::clicked, [this, item](bool) { this->openScript(item); }); + connect(widget->ui->b_Delete, &QAbstractButton::clicked, [this, item](bool) { this->removeScript(item); }); + connect(widget->ui->checkBox_Enable, &QCheckBox::stateChanged, this, &CustomScriptsEditor::markEdited); + connect(widget->ui->lineEdit_filepath, &QLineEdit::textEdited, this, &CustomScriptsEditor::markEdited); // Per the Qt manual, for performance reasons QListWidget::setItemWidget shouldn't be used with non-static items. // There's an assumption here that users won't have enough scripts for that to be a problem. ui->list->addItem(item); - ui->list->setItemWidget(item, buttons); + ui->list->setItemWidget(item, widget); +} + +void CustomScriptsEditor::markEdited() { + this->hasUnsavedChanges = true; } -QString CustomScriptsEditor::getListItemFilepath(QListWidgetItem * item) const { +QString CustomScriptsEditor::getScriptFilepath(QListWidgetItem * item, bool absolutePath) const { auto widget = dynamic_cast(ui->list->itemWidget(item)); if (!widget) return QString(); QString path = widget->ui->lineEdit_filepath->text(); - QFileInfo fileInfo(path); - if (fileInfo.isRelative()) - path.prepend(this->baseDir); + if (absolutePath) { + QFileInfo fileInfo(path); + if (fileInfo.isRelative()) + path.prepend(this->baseDir); + } return path; } -void CustomScriptsEditor::setListItemFilepath(QListWidgetItem * item, QString filepath) const { +void CustomScriptsEditor::setScriptFilepath(QListWidgetItem * item, QString filepath) const { auto widget = dynamic_cast(ui->list->itemWidget(item)); if (!widget) return; @@ -128,6 +136,11 @@ void CustomScriptsEditor::setListItemFilepath(QListWidgetItem * item, QString fi widget->ui->lineEdit_filepath->setText(filepath); } +bool CustomScriptsEditor::getScriptEnabled(QListWidgetItem * item) const { + auto widget = dynamic_cast(ui->list->itemWidget(item)); + return widget && widget->ui->checkBox_Enable->isChecked(); +} + QString CustomScriptsEditor::chooseScript(QString dir) { return QFileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)"); } @@ -139,13 +152,13 @@ void CustomScriptsEditor::addNewScript() { this->importDir = filepath; if (filepath.startsWith(this->baseDir)) filepath.remove(0, this->baseDir.length()); - this->displayScript(filepath); - this->hasUnsavedChanges = true; + this->displayScript(filepath, true); + this->markEdited(); } void CustomScriptsEditor::removeScript(QListWidgetItem * item) { ui->list->takeItem(ui->list->row(item)); - this->hasUnsavedChanges = true; + this->markEdited(); } void CustomScriptsEditor::removeSelectedScripts() { @@ -157,15 +170,15 @@ void CustomScriptsEditor::removeSelectedScripts() { } void CustomScriptsEditor::replaceScript(QListWidgetItem * item) { - const QString filepath = this->chooseScript(this->getListItemFilepath(item)); + const QString filepath = this->chooseScript(this->getScriptFilepath(item)); if (filepath.isEmpty()) return; - this->setListItemFilepath(item, filepath); - this->hasUnsavedChanges = true; + this->setScriptFilepath(item, filepath); + this->markEdited(); } void CustomScriptsEditor::openScript(QListWidgetItem * item) { - const QString path = this->getListItemFilepath(item); + const QString path = this->getScriptFilepath(item); QFileInfo fileInfo(path); if (!fileInfo.exists() || !fileInfo.isFile()){ QMessageBox::warning(this, "", QString("Failed to open script '%1'").arg(path)); @@ -191,7 +204,16 @@ void CustomScriptsEditor::reloadScripts() { void CustomScriptsEditor::save() { if (!this->hasUnsavedChanges) return; - // TODO: Set new paths in config + + QStringList paths; + QList enabledStates; + for (int i = 0; i < ui->list->count(); i++) { + auto item = ui->list->item(i); + paths.append(this->getScriptFilepath(item, false)); + enabledStates.append(this->getScriptEnabled(item)); + } + + userConfig.setCustomScripts(paths, enabledStates); this->hasUnsavedChanges = false; this->reloadScripts(); } From 2aa18da255f33e836967451253d6f4ba3580c06f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 6 Sep 2023 13:40:55 -0400 Subject: [PATCH 15/34] Implement script engine reload --- include/mainwindow.h | 1 + src/mainwindow.cpp | 12 ++++++++++++ src/ui/customscriptseditor.cpp | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 4ccaa6ff7..224b8c249 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -288,6 +288,7 @@ private slots: void togglePreferenceSpecificUi(); void on_actionEdit_Project_Settings_triggered(); void on_actionCustom_Scripts_triggered(); + void reloadScriptEngine(); public: Ui::MainWindow *ui; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ef9f90c60..c667151d8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2736,11 +2736,23 @@ void MainWindow::on_actionEdit_Project_Settings_triggered() { void MainWindow::on_actionCustom_Scripts_triggered() { if (!this->customScriptsEditor) { this->customScriptsEditor = new CustomScriptsEditor(this); + connect(this->customScriptsEditor, &CustomScriptsEditor::reloadScriptEngine, + this, &MainWindow::reloadScriptEngine); } openSubWindow(this->customScriptsEditor); } +void MainWindow::reloadScriptEngine() { + Scripting::init(this); + this->ui->graphicsView_Map->clearOverlayMap(); + Scripting::populateGlobalObject(this); + // Lying to the scripts here, simulating a project reload + Scripting::cb_ProjectOpened(projectConfig.getProjectDir()); + if (editor && editor->map) + Scripting::cb_MapOpened(editor->map->name); +} + void MainWindow::on_pushButton_AddCustomHeaderField_clicked() { bool ok; diff --git a/src/ui/customscriptseditor.cpp b/src/ui/customscriptseditor.cpp index c54ec1c77..d2ad791d4 100644 --- a/src/ui/customscriptseditor.cpp +++ b/src/ui/customscriptseditor.cpp @@ -198,7 +198,7 @@ void CustomScriptsEditor::reloadScripts() { return; this->save(); } - emit reloadScriptEngine(); // TODO: Catch this signal + emit reloadScriptEngine(); } void CustomScriptsEditor::save() { From 885695e7051f2fca313acd56b9d430ca226c94df Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 6 Sep 2023 14:45:46 -0400 Subject: [PATCH 16/34] Clean up for new editor windows --- forms/aboutporymap.ui | 2 +- forms/customscriptseditor.ui | 2 +- forms/customscriptslistitem.ui | 3 ++ forms/projectsettingseditor.ui | 59 ++++++++++++++++++-------------- include/config.h | 4 +++ include/ui/customscriptseditor.h | 4 +-- src/config.cpp | 21 ++++++++++++ src/ui/customscriptseditor.cpp | 17 +++++---- src/ui/projectsettingseditor.cpp | 9 +++-- 9 files changed, 81 insertions(+), 40 deletions(-) diff --git a/forms/aboutporymap.ui b/forms/aboutporymap.ui index 546d08172..26fd3f0a7 100644 --- a/forms/aboutporymap.ui +++ b/forms/aboutporymap.ui @@ -78,7 +78,7 @@ - <html><head/><body><p>Official Documentation: <a href="https://huderlem.github.io/porymap/"><span style=" text-decoration: underline; color:#0000ff;">https://huderlem.github.io/porymap/</span></a></p></body></html> + <html><head/><body><p>Official Documentation: <a href="https://huderlem.github.io/porymap/"><span style=" text-decoration: underline;">https://huderlem.github.io/porymap/</span></a></p></body></html> Qt::AlignCenter diff --git a/forms/customscriptseditor.ui b/forms/customscriptseditor.ui index 12acb3320..8166ed8de 100644 --- a/forms/customscriptseditor.ui +++ b/forms/customscriptseditor.ui @@ -89,7 +89,7 @@ - <html><head/><body><p><a href="https://huderlem.github.io/porymap/manual/scripting-capabilities.html"><span style=" text-decoration: underline; color:#0000ff;">What are custom scripts?</span></a></p></body></html> + <html><head/><body><p><a href="https://huderlem.github.io/porymap/manual/scripting-capabilities.html"><span style=" text-decoration: underline;">What are custom scripts?</span></a></p></body></html> true diff --git a/forms/customscriptslistitem.ui b/forms/customscriptslistitem.ui index c6040aa11..7c7e87946 100644 --- a/forms/customscriptslistitem.ui +++ b/forms/customscriptslistitem.ui @@ -52,6 +52,9 @@ + + If unchecked this script will be ignored + diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index f2e86018f..78f9e61ac 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -42,7 +42,7 @@ - + Whether map script files should prefer using .pory Use Poryscript @@ -95,13 +95,14 @@ - + + + A comma-separated list of metatile values that will be used to fill new map borders + + - - The default elevation that will be used to fill new maps - Elevation @@ -131,13 +132,14 @@ - + + + The default elevation that will be used to fill new maps + + - - The default metatile value that will be used to fill new maps - Fill Metatile @@ -145,9 +147,6 @@ - - A comma-separated list of metatile values that will be used to fill new map borders - Border Metatiles @@ -155,6 +154,9 @@ + + The default metatile value that will be used to fill new maps + 0x @@ -198,13 +200,20 @@ + + Restore the data in the prefabs file to the version defaults. Will create a new file if one doesn't exist. + Import Defaults - + + + The file that will be used to populate the Prefabs tab + + @@ -301,6 +310,9 @@ + + The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. + 0x @@ -321,9 +333,6 @@ - - The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. - Terrain Type mask @@ -351,9 +360,6 @@ - - The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. - Behavior mask @@ -361,6 +367,9 @@ + + The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. + 0x @@ -391,6 +400,9 @@ + + The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. + 0x @@ -401,9 +413,6 @@ - - The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. - Encounter Type mask @@ -411,9 +420,6 @@ - - The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. - Layer Type mask @@ -421,6 +427,9 @@ + + The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. + 0x diff --git a/include/config.h b/include/config.h index 8ce5e2d28..11d503a5d 100644 --- a/include/config.h +++ b/include/config.h @@ -74,6 +74,7 @@ class PorymapConfig: public KeyValueConfigBase void setPaletteEditorGeometry(QByteArray, QByteArray); void setRegionMapEditorGeometry(QByteArray, QByteArray); void setProjectSettingsEditorGeometry(QByteArray, QByteArray); + void setCustomScriptsEditorGeometry(QByteArray, QByteArray); void setCollisionOpacity(int opacity); void setMetatilesZoom(int zoom); void setShowPlayerView(bool enabled); @@ -95,6 +96,7 @@ class PorymapConfig: public KeyValueConfigBase QMap getPaletteEditorGeometry(); QMap getRegionMapEditorGeometry(); QMap getProjectSettingsEditorGeometry(); + QMap getCustomScriptsEditorGeometry(); int getCollisionOpacity(); int getMetatilesZoom(); bool getShowPlayerView(); @@ -133,6 +135,8 @@ class PorymapConfig: public KeyValueConfigBase QByteArray regionMapEditorState; QByteArray projectSettingsEditorGeometry; QByteArray projectSettingsEditorState; + QByteArray customScriptsEditorGeometry; + QByteArray customScriptsEditorState; int collisionOpacity; int metatilesZoom; bool showPlayerView; diff --git a/include/ui/customscriptseditor.h b/include/ui/customscriptseditor.h index a2482fc31..fd92b306c 100644 --- a/include/ui/customscriptseditor.h +++ b/include/ui/customscriptseditor.h @@ -33,19 +33,17 @@ class CustomScriptsEditor : public QMainWindow void displayScript(const QString &filepath, bool enabled); QString chooseScript(QString dir); - void removeScript(QListWidgetItem * item); void replaceScript(QListWidgetItem * item); void openScript(QListWidgetItem * item); QString getScriptFilepath(QListWidgetItem * item, bool absolutePath = true) const; void setScriptFilepath(QListWidgetItem * item, QString filepath) const; bool getScriptEnabled(QListWidgetItem * item) const; - void markEdited(); int prompt(const QString &text, QMessageBox::StandardButton defaultButton); void save(); void closeEvent(QCloseEvent*); - + void restoreWindowState(); void initShortcuts(); QObjectList shortcutableObjects() const; void applyUserShortcuts(); diff --git a/src/config.cpp b/src/config.cpp index 6e2193f2c..6bfd50a97 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -238,6 +238,10 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->projectSettingsEditorGeometry = bytesFromString(value); } else if (key == "project_settings_editor_state") { this->projectSettingsEditorState = bytesFromString(value); + } else if (key == "custom_scripts_editor_geometry") { + this->customScriptsEditorGeometry = bytesFromString(value); + } else if (key == "custom_scripts_editor_state") { + this->customScriptsEditorState = bytesFromString(value); } else if (key == "metatiles_zoom") { this->metatilesZoom = getConfigInteger(key, value, 10, 100, 30); } else if (key == "show_player_view") { @@ -286,6 +290,8 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("region_map_editor_state", stringFromByteArray(this->regionMapEditorState)); map.insert("project_settings_editor_geometry", stringFromByteArray(this->projectSettingsEditorGeometry)); map.insert("project_settings_editor_state", stringFromByteArray(this->projectSettingsEditorState)); + map.insert("custom_scripts_editor_geometry", stringFromByteArray(this->customScriptsEditorGeometry)); + map.insert("custom_scripts_editor_state", stringFromByteArray(this->customScriptsEditorState)); map.insert("collision_opacity", QString("%1").arg(this->collisionOpacity)); map.insert("metatiles_zoom", QString("%1").arg(this->metatilesZoom)); map.insert("show_player_view", this->showPlayerView ? "1" : "0"); @@ -382,6 +388,12 @@ void PorymapConfig::setProjectSettingsEditorGeometry(QByteArray projectSettingsE this->save(); } +void PorymapConfig::setCustomScriptsEditorGeometry(QByteArray customScriptsEditorGeometry_, QByteArray customScriptsEditorState_) { + this->customScriptsEditorGeometry = customScriptsEditorGeometry_; + this->customScriptsEditorState = customScriptsEditorState_; + this->save(); +} + void PorymapConfig::setCollisionOpacity(int opacity) { this->collisionOpacity = opacity; // don't auto-save here because this can be called very frequently. @@ -494,6 +506,15 @@ QMap PorymapConfig::getProjectSettingsEditorGeometry() { return geometry; } +QMap PorymapConfig::getCustomScriptsEditorGeometry() { + QMap geometry; + + geometry.insert("custom_scripts_editor_geometry", this->customScriptsEditorGeometry); + geometry.insert("custom_scripts_editor_state", this->customScriptsEditorState); + + return geometry; +} + int PorymapConfig::getCollisionOpacity() { return this->collisionOpacity; } diff --git a/src/ui/customscriptseditor.cpp b/src/ui/customscriptseditor.cpp index d2ad791d4..addb443cb 100644 --- a/src/ui/customscriptseditor.cpp +++ b/src/ui/customscriptseditor.cpp @@ -8,9 +8,6 @@ #include #include -// TODO: Better URL colors on dark themes -// TODO: Save window state - CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) : QMainWindow(parent), ui(new Ui::CustomScriptsEditor), @@ -33,6 +30,7 @@ CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) : connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &CustomScriptsEditor::dialogButtonClicked); this->initShortcuts(); + this->restoreWindowState(); } CustomScriptsEditor::~CustomScriptsEditor() @@ -90,6 +88,13 @@ void CustomScriptsEditor::applyUserShortcuts() { shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut)); } +void CustomScriptsEditor::restoreWindowState() { + logInfo("Restoring custom scripts editor geometry from previous session."); + const QMap geometry = porymapConfig.getCustomScriptsEditorGeometry(); + this->restoreGeometry(geometry.value("custom_scripts_editor_geometry")); + this->restoreState(geometry.value("custom_scripts_editor_state")); +} + void CustomScriptsEditor::displayScript(const QString &filepath, bool enabled) { auto item = new QListWidgetItem(); auto widget = new CustomScriptsListItem(); @@ -243,11 +248,9 @@ void CustomScriptsEditor::closeEvent(QCloseEvent* event) { if (result == QMessageBox::Yes) this->save(); } -/* - // TODO - porymapConfig.setProjectSettingsEditorGeometry( + + porymapConfig.setCustomScriptsEditorGeometry( this->saveGeometry(), this->saveState() ); -*/ } diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index bf8d17aed..9318838cf 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -29,8 +29,6 @@ ProjectSettingsEditor::~ProjectSettingsEditor() delete ui; } -// TODO: Move tool tips to editable areas - void ProjectSettingsEditor::connectSignals() { connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &ProjectSettingsEditor::dialogButtonClicked); connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked); @@ -178,7 +176,7 @@ void ProjectSettingsEditor::save() { this->projectNeedsReload = true; } -// TODO: If the selected file is in the project directory use a relative path +// Pick a file to use as the new prefabs file path void ProjectSettingsEditor::choosePrefabsFileClicked(bool) { QString startPath = this->project->importExportPath; QFileInfo fileInfo(ui->lineEdit_PrefabsPath->text()); @@ -190,6 +188,11 @@ void ProjectSettingsEditor::choosePrefabsFileClicked(bool) { if (filepath.isEmpty()) return; this->project->setImportExportPath(filepath); + + // Display relative path if this file is in the project folder + const QString projectDir = projectConfig.getProjectDir() + QDir::separator(); + if (filepath.startsWith(projectDir)) + filepath.remove(0, projectDir.length()); ui->lineEdit_PrefabsPath->setText(filepath); this->hasUnsavedChanges = true; } From 7411ddaeef1b39763d2610f3a8f33d8be06de503 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 6 Sep 2023 21:52:42 -0400 Subject: [PATCH 17/34] Ignore empty script paths --- src/ui/customscriptseditor.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/customscriptseditor.cpp b/src/ui/customscriptseditor.cpp index addb443cb..7a2880296 100644 --- a/src/ui/customscriptseditor.cpp +++ b/src/ui/customscriptseditor.cpp @@ -214,8 +214,11 @@ void CustomScriptsEditor::save() { QList enabledStates; for (int i = 0; i < ui->list->count(); i++) { auto item = ui->list->item(i); - paths.append(this->getScriptFilepath(item, false)); - enabledStates.append(this->getScriptEnabled(item)); + const QString path = this->getScriptFilepath(item, false); + if (!path.isEmpty()) { + paths.append(path); + enabledStates.append(this->getScriptEnabled(item)); + } } userConfig.setCustomScripts(paths, enabledStates); From 61cbbbf08ae1a9d4c4df133fc11bbf85362eb44c Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 6 Sep 2023 23:33:13 -0400 Subject: [PATCH 18/34] Add path override editor --- forms/mainwindow.ui | 18 +++---- forms/projectsettingseditor.ui | 79 ++++++++++++++++++++++++++---- include/config.h | 5 +- include/mainwindow.h | 6 +-- include/ui/projectsettingseditor.h | 2 + src/config.cpp | 22 +++++++-- src/mainwindow.cpp | 6 +-- src/ui/projectsettingseditor.cpp | 43 ++++++++++++++-- 8 files changed, 146 insertions(+), 35 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index f23028b69..91dfc192e 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -3015,9 +3015,9 @@ - - - + + + @@ -3272,9 +3272,9 @@ Export Map Stitch Image... - + - Edit Preferences... + Preferences... Ctrl+, @@ -3285,9 +3285,9 @@ Open Project in Text Editor - + - Edit Shortcuts... + Shortcuts... @@ -3310,9 +3310,9 @@ Import Map from Advance Map 1.92... - + - Edit Project Settings... + Project Settings... diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index 78f9e61ac..bcc19418d 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -6,8 +6,8 @@ 0 0 - 570 - 1041 + 563 + 1129 @@ -28,8 +28,8 @@ 0 0 - 544 - 1107 + 537 + 1427 @@ -132,7 +132,7 @@ - + The default elevation that will be used to fill new maps @@ -153,7 +153,7 @@ - + The default metatile value that will be used to fill new maps @@ -309,7 +309,7 @@ - + The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. @@ -366,7 +366,7 @@ - + The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. @@ -399,7 +399,7 @@ - + The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. @@ -426,7 +426,7 @@ - + The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. @@ -441,6 +441,60 @@
+ + + + + 0 + 320 + + + + Path Overrides + + + + 1 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + 0 + 0 + 507 + 295 + + + + + + + + + @@ -577,6 +631,11 @@ QComboBox
noscrollcombobox.h
+ + NoScrollSpinBox + QSpinBox +
noscrollspinbox.h
+
diff --git a/include/config.h b/include/config.h index 11d503a5d..4ec23b523 100644 --- a/include/config.h +++ b/include/config.h @@ -227,6 +227,7 @@ class ProjectConfig: public KeyValueConfigBase this->filePaths.clear(); this->readKeys.clear(); } + static const QMap> defaultPaths; static const QStringList versionStrings; void reset(BaseGameVersion baseGameVersion); void setBaseGameVersion(BaseGameVersion baseGameVersion); @@ -271,8 +272,10 @@ class ProjectConfig: public KeyValueConfigBase QString getDefaultSecondaryTileset(); void setDefaultPrimaryTileset(QString tilesetName); void setDefaultSecondaryTileset(QString tilesetName); + void setFilePath(QString pathId, QString path); void setFilePath(ProjectFilePath pathId, QString path); - QString getFilePath(ProjectFilePath pathId); + QString getFilePath(QString defaultPath, bool allowDefault = true); + QString getFilePath(ProjectFilePath pathId, bool allowDefault = true); void setPrefabFilepath(QString filepath); QString getPrefabFilepath(); void setPrefabImportPrompted(bool prompted); diff --git a/include/mainwindow.h b/include/mainwindow.h index 224b8c249..41c6c7f01 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -201,7 +201,7 @@ private slots: void on_spinBox_FloorNumber_valueChanged(int offset); void on_actionMonitor_Project_Files_triggered(bool checked); void on_actionOpen_Recent_Project_On_Launch_triggered(bool checked); - void on_actionEdit_Shortcuts_triggered(); + void on_actionShortcuts_triggered(); void on_actionZoom_In_triggered(); void on_actionZoom_Out_triggered(); @@ -284,9 +284,9 @@ private slots: void on_pushButton_CreatePrefab_clicked(); void on_actionRegion_Map_Editor_triggered(); - void on_actionEdit_Preferences_triggered(); + void on_actionPreferences_triggered(); void togglePreferenceSpecificUi(); - void on_actionEdit_Project_Settings_triggered(); + void on_actionProject_Settings_triggered(); void on_actionCustom_Scripts_triggered(); void reloadScriptEngine(); diff --git a/include/ui/projectsettingseditor.h b/include/ui/projectsettingseditor.h index 03b3d14d7..5f4fcd310 100644 --- a/include/ui/projectsettingseditor.h +++ b/include/ui/projectsettingseditor.h @@ -41,6 +41,8 @@ class ProjectSettingsEditor : public QMainWindow bool promptSaveChanges(); bool promptRestoreDefaults(); + void createProjectPathsTable(); + private slots: void dialogButtonClicked(QAbstractButton *button); void choosePrefabsFileClicked(bool); diff --git a/src/config.cpp b/src/config.cpp index 6bfd50a97..9592ca631 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -16,7 +16,7 @@ #include #include -const QMap> defaultPaths = { +const QMap> ProjectConfig::defaultPaths = { {ProjectFilePath::data_map_folders, { "data_map_folders", "data/maps/"}}, {ProjectFilePath::data_scripts_folders, { "data_scripts_folders", "data/scripts/"}}, {ProjectFilePath::data_layouts_folders, { "data_layouts_folders", "data/layouts/"}}, @@ -64,7 +64,7 @@ const QMap> defaultPaths = { }; ProjectFilePath reverseDefaultPaths(QString str) { - for (auto it = defaultPaths.constKeyValueBegin(); it != defaultPaths.constKeyValueEnd(); ++it) { + for (auto it = ProjectConfig::defaultPaths.constKeyValueBegin(); it != ProjectConfig::defaultPaths.constKeyValueEnd(); ++it) { if ((*it).second.first == str) return (*it).first; } return static_cast(-1); @@ -793,19 +793,31 @@ QString ProjectConfig::getProjectDir() { void ProjectConfig::setFilePath(ProjectFilePath pathId, QString path) { if (!defaultPaths.contains(pathId)) return; - this->filePaths[pathId] = path; + if (path.isEmpty()) { + this->filePaths.remove(pathId); + } else { + this->filePaths[pathId] = path; + } +} + +void ProjectConfig::setFilePath(QString defaultPath, QString newPath) { + this->setFilePath(reverseDefaultPaths(defaultPath), newPath); } -QString ProjectConfig::getFilePath(ProjectFilePath pathId) { +QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool allowDefault) { if (this->filePaths.contains(pathId)) { return this->filePaths[pathId]; - } else if (defaultPaths.contains(pathId)) { + } else if (allowDefault && defaultPaths.contains(pathId)) { return defaultPaths[pathId].second; } else { return QString(); } } +QString ProjectConfig::getFilePath(QString defaultPath, bool allowDefault) { + return this->getFilePath(reverseDefaultPaths(defaultPath), allowDefault); +} + void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) { this->baseGameVersion = baseGameVersion; this->save(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c667151d8..f568f505d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1780,7 +1780,7 @@ void MainWindow::on_actionOpen_Recent_Project_On_Launch_triggered(bool checked) porymapConfig.setReopenOnLaunch(checked); } -void MainWindow::on_actionEdit_Shortcuts_triggered() +void MainWindow::on_actionShortcuts_triggered() { if (!shortcutsEditor) initShortcutsEditor(); @@ -2702,7 +2702,7 @@ void MainWindow::on_actionOpen_Config_Folder_triggered() { QDesktopServices::openUrl(QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation))); } -void MainWindow::on_actionEdit_Preferences_triggered() { +void MainWindow::on_actionPreferences_triggered() { if (!preferenceEditor) { preferenceEditor = new PreferenceEditor(this); connect(preferenceEditor, &PreferenceEditor::themeChanged, @@ -2723,7 +2723,7 @@ void MainWindow::togglePreferenceSpecificUi() { ui->actionOpen_Project_in_Text_Editor->setEnabled(true); } -void MainWindow::on_actionEdit_Project_Settings_triggered() { +void MainWindow::on_actionProject_Settings_triggered() { if (!this->projectSettingsEditor) { this->projectSettingsEditor = new ProjectSettingsEditor(this, this->editor->project); connect(this->projectSettingsEditor, &ProjectSettingsEditor::reloadProject, diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index 9318838cf..e8d9af407 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -11,6 +11,8 @@ Editor for the settings in a user's porymap.project.cfg file (and 'use_encounter_json' in porymap.user.cfg). */ +// TODO: Better red outline around warning section + ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) : QMainWindow(parent), ui(new Ui::ProjectSettingsEditor), @@ -19,6 +21,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); this->initUi(); + this->createProjectPathsTable(); this->connectSignals(); this->refresh(); this->restoreWindowState(); @@ -40,7 +43,7 @@ void ProjectSettingsEditor::connectSignals() { connect(combo, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited); for (auto checkBox : ui->centralwidget->findChildren()) connect(checkBox, &QCheckBox::stateChanged, this, &ProjectSettingsEditor::markEdited); - for (auto spinBox : ui->centralwidget->findChildren()) + for (auto spinBox : ui->centralwidget->findChildren()) connect(spinBox, QOverload::of(&QSpinBox::valueChanged), [this](int) { this->markEdited(); }); for (auto lineEdit : ui->centralwidget->findChildren()) connect(lineEdit, &QLineEdit::textEdited, this, &ProjectSettingsEditor::markEdited); @@ -75,6 +78,35 @@ void ProjectSettingsEditor::initUi() { ui->spinBox_TerrainTypeMask->setMaximum(INT_MAX); } +// TODO: Reduce vertical space between entries +// TODO: Fix vertical misalignment between label and edit area +// TODO: Add description / manual link at top? +void ProjectSettingsEditor::createProjectPathsTable() { + auto pathPairs = ProjectConfig::defaultPaths.values(); + for (auto pathPair : pathPairs) { + // Name of the path + auto name = new QLabel(); + name->setText(pathPair.first); + + // Editable area of the path + auto path = new QLineEdit(); + path->setObjectName(pathPair.first); // Used when saving the paths + path->setPlaceholderText(pathPair.second); + path->setClearButtonEnabled(true); + auto button = new QToolButton(); + button->setIcon(QIcon(":/icons/folder.ico")); + // TODO: file prompt + //connect(button, &QAbstractButton::clicked, this, &ProjectSettingsEditor::); + + // Add to list + auto editFrame = new QFrame(); + auto layout = new QHBoxLayout(editFrame); + layout->addWidget(path); + layout->addWidget(button); + ui->layout_ProjectPaths->addRow(name, editFrame); + } +} + void ProjectSettingsEditor::restoreWindowState() { logInfo("Restoring project settings editor geometry from previous session."); const QMap geometry = porymapConfig.getProjectSettingsEditorGeometry(); @@ -120,6 +152,8 @@ void ProjectSettingsEditor::refresh() { // Set line edit texts ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString()); ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath()); + for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren()) + lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), false)); this->refreshing = false; // Allow signals } @@ -157,11 +191,12 @@ void ProjectSettingsEditor::save() { projectConfig.setMetatileEncounterTypeMask(ui->spinBox_EncounterTypeMask->value()); projectConfig.setMetatileLayerTypeMask(ui->spinBox_LayerTypeMask->value()); projectConfig.setPrefabFilepath(ui->lineEdit_PrefabsPath->text()); + for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren()) + projectConfig.setFilePath(lineEdit->objectName(), lineEdit->text()); - // Parse border metatile list - QList metatileIdStrings = ui->lineEdit_BorderMetatiles->text().split(","); + // Parse and save border metatile list QList metatileIds; - for (auto s : metatileIdStrings) { + for (auto s : ui->lineEdit_BorderMetatiles->text().split(",")) { uint16_t metatileId = s.toUInt(nullptr, 0); metatileIds.append(qMin(metatileId, static_cast(Project::getNumMetatilesTotal() - 1))); } From 7766ae39e9f0b7cde8acf221d8707d4cf4fe95af Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Tue, 25 Jul 2023 12:39:55 -0700 Subject: [PATCH 19/34] Update INSTALL.md Removed breaking linux package --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index 4cad73656..eb450597d 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -33,7 +33,7 @@ You need to install Qt. The minimum supported version is currently Qt 5.14.2. Yo with `qtdiag`. ``` -sudo apt-get install qt5-default qtdeclarative5-dev +sudo apt-get install qtdeclarative5-dev qmake make ./porymap From 9be5faecff055f58a63ed99a91da001f2ceefcb6 Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Fri, 8 Sep 2023 10:02:04 -0700 Subject: [PATCH 20/34] Update INSTALL.md Updated Ubuntu install instructions per discussion: https://discord.com/channels/442462691542695948/495019188042203147/1149746226263248896 --- INSTALL.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index eb450597d..2fcca5a8f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -33,7 +33,8 @@ You need to install Qt. The minimum supported version is currently Qt 5.14.2. Yo with `qtdiag`. ``` -sudo apt-get install qtdeclarative5-dev +sudo apt-get install qt6-declarative-dev +# if your distro does not have qt6-declarative-dev, try sudo apt-get install qtdeclarative5-dev qmake make ./porymap From 7b03678b8e1fcf9d09c7a2d4ab398171f2695255 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 8 Sep 2023 13:07:11 -0400 Subject: [PATCH 21/34] Fix INSTALL code rendering --- INSTALL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 2fcca5a8f..34f03196f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -7,7 +7,7 @@ porymap requires Qt 5.14.2 & C++11. The easiest way to get Qt is through [homebrew](https://brew.sh/). Once homebrew is installed, run these commands in Terminal: -``` +```bash xcode-select --install brew update @@ -32,7 +32,7 @@ Install [Qt development tools](https://www.qt.io/download-qt-installer), and use You need to install Qt. The minimum supported version is currently Qt 5.14.2. You can check your Qt version with `qtdiag`. -``` +```bash sudo apt-get install qt6-declarative-dev # if your distro does not have qt6-declarative-dev, try sudo apt-get install qtdeclarative5-dev qmake From 7a399daaffed3f8bc7bbf5a08376ffd164c43a52 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 8 Sep 2023 13:05:38 -0400 Subject: [PATCH 22/34] Clean up project settings editor UI --- forms/projectsettingseditor.ui | 751 ++++++++++++++++--------------- src/ui/projectsettingseditor.cpp | 12 +- 2 files changed, 397 insertions(+), 366 deletions(-) diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index bcc19418d..be99e633a 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -6,8 +6,8 @@ 0 0 - 563 - 1129 + 611 + 1137 @@ -28,15 +28,15 @@ 0 0 - 537 - 1427 + 585 + 1486 - User config + Preferences @@ -233,381 +233,416 @@ - - - - 12 - 75 - true - + + + .QFrame { border: 1px solid red; } - - <html><head/><body><p><span style=" font-size:13pt; color:#d7000c;">WARNING: </span><span style=" font-weight:400;">The settings from this point below require project changes to function properly. Do not modify these settings without the necessary changes. </span></p></body></html> + + QFrame::StyledPanel - - true + + QFrame::Raised - - - - - - - - - Base game version - - - + - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Tilesets / Metatiles - - - - - - Qt::Vertical - - - - 20 - 10 - - - - - - - - Enable Triple Layer Metatiles - - - - - - - The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. - - - 0x - - - 16 - - - - - - - The number of bytes used per metatile for metatile attributes - - - Attributes size (in bytes) - - - - - - - Terrain Type mask - - - - - - - false - - - - - - - Qt::Vertical - - - - 20 - 15 - - - - - - - - Behavior mask - - - - - - - The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. - - - 0x - - - 16 - - - - - - - Whether the C data outputted for new tilesets will include the "callback" field + + + + 12 + 75 + true + - Output 'callback' field - - - - - - - Whether the C data outputted for new tilesets will include the "isCompressed" field - - - Output 'isCompressed' field - - - - - - - The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. - - - 0x - - - 16 + <html><head/><body><p><span style=" font-size:13pt; color:#d7000c;">WARNING: </span><span style=" font-weight:400;">The settings from this point below require project changes to function properly. Do not modify these settings without the necessary changes. </span></p></body></html> - - - - - - Encounter Type mask + + true - - - - Layer Type mask - + + + + + + + Base game version + + + + + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - - The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. - - - 0x - - - 16 - + + + + Tilesets / Metatiles + + + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + Enable Triple Layer Metatiles + + + + + + + The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. + + + 0x + + + 16 + + + + + + + The number of bytes used per metatile for metatile attributes + + + Attributes size (in bytes) + + + + + + + Terrain Type mask + + + + + + + false + + + + + + + Qt::Vertical + + + + 20 + 15 + + + + + + + + Behavior mask + + + + + + + The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. + + + 0x + + + 16 + + + + + + + Whether the C data outputted for new tilesets will include the "callback" field + + + Output 'callback' field + + + + + + + Whether the C data outputted for new tilesets will include the "isCompressed" field + + + Output 'isCompressed' field + + + + + + + The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. + + + 0x + + + 16 + + + + + + + Encounter Type mask + + + + + + + Layer Type mask + + + + + + + The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. + + + 0x + + + 16 + + + + - - - - - - - - 0 - 320 - - - - Path Overrides - - - - 1 - - - 0 - - - 0 - - - 0 - - - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - true - - - - - 0 - 0 - 507 - 295 - + + + + 2 - - - - - - - - - - - Events - - - - - - Enable 'Requires Itemfinder' for Hidden Items - - - - - - - Enable 'Quantity' for Hidden Items - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Enable Secret Bases - - - - - - - Enable Weather Triggers - - - - - - - Enable Clone Objects - - - - - - - Enable 'Respawn Map/NPC' for Heal Locations - - - - - - - - - - Maps - - - - - - Whether "Allow Running", "Allow Biking" and "Allow Dig & Escape Rope" are default options for Map Headers - - - Enable 'Allow Running/Biking/Escaping' - + + 0 + + + 0 + + + 0 + + + 0 + + + + + <html><head/><body><p><a href="https://huderlem.github.io/porymap/manual/project-files.html"><span style=" text-decoration: underline;">Project Files</span></a></p></body></html> + + + Qt::RichText + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + true + + + + + + + + 0 + 320 + + + + 2 + + + true + + + + + 0 + 0 + 533 + 318 + + + + + 0 + + + 0 + + + 4 + + + + + + - - - - Whether "Floor Number" is a default option for Map Headers - - - Enable 'Floor Number' - + + + + Events + + + + + + Enable Weather Triggers + + + + + + + Enable Secret Bases + + + + + + + Enable Clone Objects + + + + + + + Enable 'Requires Itemfinder' for Hidden Items + + + + + + + Enable 'Quantity' for Hidden Items + + + + + + + Enable 'Respawn Map/NPC' for Heal Locations + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - - Whether the dimensions of the border can be changed. If not set, all borders are 2x2 - - - Enable Custom Border Size - + + + + Maps + + + + + + Whether "Allow Running", "Allow Biking" and "Allow Dig & Escape Rope" are default options for Map Headers + + + Enable 'Allow Running/Biking/Escaping' + + + + + + + Whether "Floor Number" is a default option for Map Headers + + + Enable 'Floor Number' + + + + + + + Whether the dimensions of the border can be changed. If not set, all borders are 2x2 + + + Enable Custom Border Size + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - - Qt::Horizontal - - - - 40 - 20 - - - - diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index e8d9af407..502eaca9b 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -11,8 +11,6 @@ Editor for the settings in a user's porymap.project.cfg file (and 'use_encounter_json' in porymap.user.cfg). */ -// TODO: Better red outline around warning section - ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) : QMainWindow(parent), ui(new Ui::ProjectSettingsEditor), @@ -78,14 +76,12 @@ void ProjectSettingsEditor::initUi() { ui->spinBox_TerrainTypeMask->setMaximum(INT_MAX); } -// TODO: Reduce vertical space between entries -// TODO: Fix vertical misalignment between label and edit area -// TODO: Add description / manual link at top? void ProjectSettingsEditor::createProjectPathsTable() { auto pathPairs = ProjectConfig::defaultPaths.values(); for (auto pathPair : pathPairs) { // Name of the path auto name = new QLabel(); + name->setAlignment(Qt::AlignBottom); name->setText(pathPair.first); // Editable area of the path @@ -99,11 +95,11 @@ void ProjectSettingsEditor::createProjectPathsTable() { //connect(button, &QAbstractButton::clicked, this, &ProjectSettingsEditor::); // Add to list - auto editFrame = new QFrame(); - auto layout = new QHBoxLayout(editFrame); + auto editArea = new QWidget(); + auto layout = new QHBoxLayout(editArea); layout->addWidget(path); layout->addWidget(button); - ui->layout_ProjectPaths->addRow(name, editFrame); + ui->layout_ProjectPaths->addRow(name, editArea); } } From a5a864926a0fcf4e6c2a46c94ae1931a184c1cb1 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sat, 9 Sep 2023 19:36:12 -0400 Subject: [PATCH 23/34] Enforce project folder for custom filepaths --- include/config.h | 4 +-- include/ui/projectsettingseditor.h | 2 ++ src/config.cpp | 29 +++++++++++----- src/ui/projectsettingseditor.cpp | 55 +++++++++++++++++++++++------- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/include/config.h b/include/config.h index 4ec23b523..96086749d 100644 --- a/include/config.h +++ b/include/config.h @@ -274,8 +274,8 @@ class ProjectConfig: public KeyValueConfigBase void setDefaultSecondaryTileset(QString tilesetName); void setFilePath(QString pathId, QString path); void setFilePath(ProjectFilePath pathId, QString path); - QString getFilePath(QString defaultPath, bool allowDefault = true); - QString getFilePath(ProjectFilePath pathId, bool allowDefault = true); + QString getFilePath(QString defaultPath, bool customOnly = false); + QString getFilePath(ProjectFilePath pathId, bool customOnly = false); void setPrefabFilepath(QString filepath); QString getPrefabFilepath(); void setPrefabImportPrompted(bool prompted); diff --git a/include/ui/projectsettingseditor.h b/include/ui/projectsettingseditor.h index 5f4fcd310..83fe741e6 100644 --- a/include/ui/projectsettingseditor.h +++ b/include/ui/projectsettingseditor.h @@ -30,6 +30,7 @@ class ProjectSettingsEditor : public QMainWindow bool hasUnsavedChanges = false; bool projectNeedsReload = false; bool refreshing = false; + const QString baseDir; void initUi(); void connectSignals(); @@ -42,6 +43,7 @@ class ProjectSettingsEditor : public QMainWindow bool promptRestoreDefaults(); void createProjectPathsTable(); + QString chooseProjectFile(const QString &defaultFilepath); private slots: void dialogButtonClicked(QAbstractButton *button); diff --git a/src/config.cpp b/src/config.cpp index 9592ca631..8c51de9f4 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -804,18 +804,29 @@ void ProjectConfig::setFilePath(QString defaultPath, QString newPath) { this->setFilePath(reverseDefaultPaths(defaultPath), newPath); } -QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool allowDefault) { - if (this->filePaths.contains(pathId)) { - return this->filePaths[pathId]; - } else if (allowDefault && defaultPaths.contains(pathId)) { - return defaultPaths[pathId].second; - } else { - return QString(); +QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool customOnly) { + const QString customPath = this->filePaths.value(pathId); + + // When reading custom filepaths for the settings editor we don't care + // about the default path or whether the custom path exists. + if (customOnly) + return customPath; + + if (!customPath.isEmpty()) { + // A custom filepath has been specified. If the file/folder exists, use that. + const QString absCustomPath = this->projectDir + QDir::separator() + customPath; + if (QFileInfo::exists(absCustomPath)) { + return customPath; + } else { + logError(QString("Custom project filepath '%1' not found. Using default.").arg(absCustomPath)); + } } + return defaultPaths.contains(pathId) ? defaultPaths[pathId].second : QString(); + } -QString ProjectConfig::getFilePath(QString defaultPath, bool allowDefault) { - return this->getFilePath(reverseDefaultPaths(defaultPath), allowDefault); +QString ProjectConfig::getFilePath(QString defaultPath, bool customOnly) { + return this->getFilePath(reverseDefaultPaths(defaultPath), customOnly); } void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) { diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index 502eaca9b..cfd330eb2 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -14,7 +14,8 @@ ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project) : QMainWindow(parent), ui(new Ui::ProjectSettingsEditor), - project(project) + project(project), + baseDir(userConfig.getProjectDir() + QDir::separator()) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); @@ -84,25 +85,54 @@ void ProjectSettingsEditor::createProjectPathsTable() { name->setAlignment(Qt::AlignBottom); name->setText(pathPair.first); - // Editable area of the path - auto path = new QLineEdit(); - path->setObjectName(pathPair.first); // Used when saving the paths - path->setPlaceholderText(pathPair.second); - path->setClearButtonEnabled(true); + // Filepath line edit + auto lineEdit = new QLineEdit(); + lineEdit->setObjectName(pathPair.first); // Used when saving the paths + lineEdit->setPlaceholderText(pathPair.second); + lineEdit->setClearButtonEnabled(true); + + // "Choose file" button auto button = new QToolButton(); button->setIcon(QIcon(":/icons/folder.ico")); - // TODO: file prompt - //connect(button, &QAbstractButton::clicked, this, &ProjectSettingsEditor::); + connect(button, &QAbstractButton::clicked, [this, lineEdit](bool) { + const QString path = this->chooseProjectFile(lineEdit->placeholderText()); + if (!path.isEmpty()) { + lineEdit->setText(path); + this->markEdited(); + } + }); // Add to list auto editArea = new QWidget(); auto layout = new QHBoxLayout(editArea); - layout->addWidget(path); + layout->addWidget(lineEdit); layout->addWidget(button); ui->layout_ProjectPaths->addRow(name, editArea); } } +QString ProjectSettingsEditor::chooseProjectFile(const QString &defaultFilepath) { + const QString startDir = this->baseDir + defaultFilepath; + + QString path; + if (defaultFilepath.endsWith("/")){ + // Default filepath is a folder, choose a new folder + path = QFileDialog::getExistingDirectory(this, "Choose Project File Folder", startDir) + QDir::separator(); + } else{ + // Default filepath is not a folder, choose a new file + path = QFileDialog::getOpenFileName(this, "Choose Project File", startDir); + } + + if (!path.startsWith(this->baseDir)){ + // Most of Porymap's file-parsing code for project files will assume that filepaths + // are relative to the root project folder, so we enforce that here. + QMessageBox::warning(this, "Failed to set custom filepath", + QString("Custom filepaths must be inside the root project folder '%1'").arg(this->baseDir)); + return QString(); + } + return path.remove(0, this->baseDir.length()); +} + void ProjectSettingsEditor::restoreWindowState() { logInfo("Restoring project settings editor geometry from previous session."); const QMap geometry = porymapConfig.getProjectSettingsEditorGeometry(); @@ -149,7 +179,7 @@ void ProjectSettingsEditor::refresh() { ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString()); ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath()); for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren()) - lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), false)); + lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), true)); this->refreshing = false; // Allow signals } @@ -221,9 +251,8 @@ void ProjectSettingsEditor::choosePrefabsFileClicked(bool) { this->project->setImportExportPath(filepath); // Display relative path if this file is in the project folder - const QString projectDir = projectConfig.getProjectDir() + QDir::separator(); - if (filepath.startsWith(projectDir)) - filepath.remove(0, projectDir.length()); + if (filepath.startsWith(this->baseDir)) + filepath.remove(0, this->baseDir.length()); ui->lineEdit_PrefabsPath->setText(filepath); this->hasUnsavedChanges = true; } From 1c081f201158f050ab932b1f640c5c3f0ecfdd37 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 10 Sep 2023 17:04:44 -0400 Subject: [PATCH 24/34] Connect custom script editor to shortcuts editor --- include/mainwindow.h | 1 + include/ui/customscriptseditor.h | 4 +++- src/mainwindow.cpp | 18 +++++++++++++----- src/ui/customscriptseditor.cpp | 7 +------ 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 41c6c7f01..36f89d487 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -387,6 +387,7 @@ private slots: void initTilesetEditor(); bool initRegionMapEditor(bool silent = false); void initShortcutsEditor(); + void initCustomScriptsEditor(); void connectSubEditorsToShortcutsEditor(); bool isProjectOpen(); diff --git a/include/ui/customscriptseditor.h b/include/ui/customscriptseditor.h index fd92b306c..d54a7cc33 100644 --- a/include/ui/customscriptseditor.h +++ b/include/ui/customscriptseditor.h @@ -24,6 +24,9 @@ class CustomScriptsEditor : public QMainWindow signals: void reloadScriptEngine(); +public slots: + void applyUserShortcuts(); + private: Ui::CustomScriptsEditor *ui; @@ -46,7 +49,6 @@ class CustomScriptsEditor : public QMainWindow void restoreWindowState(); void initShortcuts(); QObjectList shortcutableObjects() const; - void applyUserShortcuts(); private slots: void dialogButtonClicked(QAbstractButton *button); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f568f505d..e26dd3826 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1811,6 +1811,11 @@ void MainWindow::connectSubEditorsToShortcutsEditor() { if (regionMapEditor) connect(shortcutsEditor, &ShortcutsEditor::shortcutsSaved, regionMapEditor, &RegionMapEditor::applyUserShortcuts); + + if (!customScriptsEditor) + initCustomScriptsEditor(); + connect(shortcutsEditor, &ShortcutsEditor::shortcutsSaved, + customScriptsEditor, &CustomScriptsEditor::applyUserShortcuts); } void MainWindow::on_actionPencil_triggered() @@ -2734,15 +2739,18 @@ void MainWindow::on_actionProject_Settings_triggered() { } void MainWindow::on_actionCustom_Scripts_triggered() { - if (!this->customScriptsEditor) { - this->customScriptsEditor = new CustomScriptsEditor(this); - connect(this->customScriptsEditor, &CustomScriptsEditor::reloadScriptEngine, - this, &MainWindow::reloadScriptEngine); - } + if (!this->customScriptsEditor) + initCustomScriptsEditor(); openSubWindow(this->customScriptsEditor); } +void MainWindow::initCustomScriptsEditor() { + this->customScriptsEditor = new CustomScriptsEditor(this); + connect(this->customScriptsEditor, &CustomScriptsEditor::reloadScriptEngine, + this, &MainWindow::reloadScriptEngine); +} + void MainWindow::reloadScriptEngine() { Scripting::init(this); this->ui->graphicsView_Map->clearOverlayMap(); diff --git a/src/ui/customscriptseditor.cpp b/src/ui/customscriptseditor.cpp index 7a2880296..6daeb0ebb 100644 --- a/src/ui/customscriptseditor.cpp +++ b/src/ui/customscriptseditor.cpp @@ -44,8 +44,7 @@ void CustomScriptsEditor::initShortcuts() { shortcut_remove->setObjectName("shortcut_remove"); shortcut_remove->setWhatsThis("Remove Selected Scripts"); - // TODO: Prevent ambiguity with MainWindow - auto *shortcut_open = new Shortcut(QKeySequence("Ctrl+O"), this, SLOT(openSelectedScripts())); + auto *shortcut_open = new Shortcut(QKeySequence(), this, SLOT(openSelectedScripts())); shortcut_open->setObjectName("shortcut_open"); shortcut_open->setWhatsThis("Open Selected Scripts"); @@ -57,9 +56,6 @@ void CustomScriptsEditor::initShortcuts() { shortcut_reload->setObjectName("shortcut_reload"); shortcut_reload->setWhatsThis("Reload Scripts"); - //connect(new QShortcut(QKeySequence("Backspace"), this), &QShortcut::activated, this, &CustomScriptsEditor::removeSelectedScripts); - //connect(new QShortcut(QKeySequence("Ctrl+O"), this), &QShortcut::activated, this, &CustomScriptsEditor::openSelectedScripts); - shortcutsConfig.load(); shortcutsConfig.setDefaultShortcuts(shortcutableObjects()); applyUserShortcuts(); @@ -78,7 +74,6 @@ QObjectList CustomScriptsEditor::shortcutableObjects() const { return shortcutable_objects; } -// TODO: Connect to shorcuts editor void CustomScriptsEditor::applyUserShortcuts() { for (auto *action : findChildren()) if (!action->objectName().isEmpty()) From b00c644099fbde513df8d7a6466120fc5a4a4f6a Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 10 Sep 2023 18:08:32 -0400 Subject: [PATCH 25/34] Update CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d61cd0acd..70970cc17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,16 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ## [Unreleased] ### Added +- Adds an editor window under `Options -> Project Settings...` to customize the project-specific settings in `porymap.project.cfg` and `porymap.user.cfg`. +- Adds an editor window under `Options -> Custom Scripts...` for Porymap's API scripts. - Support for 8BPP tileset tile images. ### Changed - The Palette Editor now remembers the Bit Depth setting. - The min/max levels on the Wild Pokémon tab will now adjust automatically if they invalidate each other. - If the recent project directory doesn't exist Porymap will open an empty project instead of failing with a misleading error message. +- Settings under `Options` were relocated either to the `Preferences` window or `Options -> Project Settings`. +- Secret Base and Weather Trigger events are automatically disabled if their respective constants files fail to parse, instead of not opening the project. ### Fixed - Fix text boxes in the Palette Editor calculating color incorrectly. @@ -22,6 +26,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix the map border not updating when a tileset is changed. - Stop the Tileset Editor from scrolling to the initially selected metatile when saving. - Fix the selection outline sticking in single-tile mode on the Prefab tab. +- Fix bad URL color contrast on dark themes. ## [5.1.1] - 2023-02-20 ### Added From 603df4defa3232744cae8742378ddc2067266185 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 11 Sep 2023 12:44:15 -0400 Subject: [PATCH 26/34] Add UIntSpinBox class --- forms/projectsettingseditor.ui | 13 ++- include/ui/uintspinbox.h | 67 ++++++++++++ porymap.pro | 6 +- src/ui/projectsettingseditor.cpp | 14 +-- src/ui/uintspinbox.cpp | 178 +++++++++++++++++++++++++++++++ 5 files changed, 266 insertions(+), 12 deletions(-) create mode 100644 include/ui/uintspinbox.h create mode 100644 src/ui/uintspinbox.cpp diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index be99e633a..34504fb5b 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -321,7 +321,7 @@ - + The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled. @@ -378,7 +378,7 @@ - + The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled. @@ -411,7 +411,7 @@ - + The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled. @@ -438,7 +438,7 @@ - + The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled. @@ -671,6 +671,11 @@ QSpinBox
noscrollspinbox.h
+ + UIntSpinBox + QAbstractSpinBox +
uintspinbox.h
+
diff --git a/include/ui/uintspinbox.h b/include/ui/uintspinbox.h new file mode 100644 index 000000000..b561e2194 --- /dev/null +++ b/include/ui/uintspinbox.h @@ -0,0 +1,67 @@ +#ifndef UINTSPINBOX_H +#define UINTSPINBOX_H + +#include +#include + +/* + QSpinBox stores minimum/maximum/value as ints. This class is a version of QAbstractSpinBox for values above 0x7FFFFFFF. + It minimally implements some QSpinBox-specific features like prefixes to simplify support for hex value input. + It also implements the scroll focus requirements of NoScrollSpinBox. +*/ + +class UIntSpinBox : public QAbstractSpinBox +{ + Q_OBJECT + +public: + explicit UIntSpinBox(QWidget *parent = nullptr); + ~UIntSpinBox() {}; + + uint32_t value() const { return m_value; } + uint32_t minimum() const { return m_minimum; } + uint32_t maximum() const { return m_maximum; } + QString prefix() const { return m_prefix; } + int displayIntegerBase() const { return m_displayIntegerBase; } + bool hasPadding() const { return m_hasPadding; } + + void setMinimum(uint32_t min); + void setMaximum(uint32_t max); + void setRange(uint32_t min, uint32_t max); + void setPrefix(const QString &prefix); + void setDisplayIntegerBase(int base); + void setHasPadding(bool enabled); + +private: + uint32_t m_minimum; + uint32_t m_maximum; + uint32_t m_value; + QString m_prefix; + int m_displayIntegerBase; + bool m_hasPadding; + int m_numChars; + + void updateEdit(); + QString stripped(QString input) const; + + virtual void stepBy(int steps) override; + virtual void wheelEvent(QWheelEvent *event) override; + virtual void focusOutEvent(QFocusEvent *event) override; + +protected: + virtual uint32_t valueFromText(const QString &text) const; + virtual QString textFromValue(uint32_t val) const; + virtual QValidator::State validate(QString &input, int &pos) const override; + virtual QAbstractSpinBox::StepEnabled stepEnabled() const override; + + +public slots: + void setValue(uint32_t val); + void onEditFinished(); + +signals: + void valueChanged(uint32_t val); + void textChanged(const QString &text); +}; + +#endif // UINTSPINBOX_H \ No newline at end of file diff --git a/porymap.pro b/porymap.pro index 4a2a20081..63b97c1a2 100644 --- a/porymap.pro +++ b/porymap.pro @@ -100,7 +100,8 @@ SOURCES += src/core/block.cpp \ src/mainwindow.cpp \ src/project.cpp \ src/settings.cpp \ - src/log.cpp + src/log.cpp \ + src/ui/uintspinbox.cpp HEADERS += include/core/block.h \ include/core/blockdata.h \ @@ -192,7 +193,8 @@ HEADERS += include/core/block.h \ include/scripting.h \ include/scriptutility.h \ include/settings.h \ - include/log.h + include/log.h \ + include/ui/uintspinbox.h FORMS += forms/mainwindow.ui \ forms/prefabcreationdialog.ui \ diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index cfd330eb2..ae64053e4 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -42,10 +42,12 @@ void ProjectSettingsEditor::connectSignals() { connect(combo, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::markEdited); for (auto checkBox : ui->centralwidget->findChildren()) connect(checkBox, &QCheckBox::stateChanged, this, &ProjectSettingsEditor::markEdited); - for (auto spinBox : ui->centralwidget->findChildren()) - connect(spinBox, QOverload::of(&QSpinBox::valueChanged), [this](int) { this->markEdited(); }); for (auto lineEdit : ui->centralwidget->findChildren()) connect(lineEdit, &QLineEdit::textEdited, this, &ProjectSettingsEditor::markEdited); + for (auto spinBox : ui->centralwidget->findChildren()) + connect(spinBox, &QSpinBox::textChanged, this, &ProjectSettingsEditor::markEdited); + for (auto spinBox : ui->centralwidget->findChildren()) + connect(spinBox, &UIntSpinBox::textChanged, this, &ProjectSettingsEditor::markEdited); } void ProjectSettingsEditor::markEdited() { @@ -71,10 +73,10 @@ void ProjectSettingsEditor::initUi() { ui->spinBox_FillMetatile->setMaximum(Project::getNumMetatilesTotal() - 1); // TODO: These need to be subclassed (or changed to line edits) to handle larger values - ui->spinBox_BehaviorMask->setMaximum(INT_MAX); - ui->spinBox_EncounterTypeMask->setMaximum(INT_MAX); - ui->spinBox_LayerTypeMask->setMaximum(INT_MAX); - ui->spinBox_TerrainTypeMask->setMaximum(INT_MAX); + ui->spinBox_BehaviorMask->setMaximum(UINT_MAX); + ui->spinBox_EncounterTypeMask->setMaximum(UINT_MAX); + ui->spinBox_LayerTypeMask->setMaximum(UINT_MAX); + ui->spinBox_TerrainTypeMask->setMaximum(UINT_MAX); } void ProjectSettingsEditor::createProjectPathsTable() { diff --git a/src/ui/uintspinbox.cpp b/src/ui/uintspinbox.cpp new file mode 100644 index 000000000..31f66ba9a --- /dev/null +++ b/src/ui/uintspinbox.cpp @@ -0,0 +1,178 @@ +#include "uintspinbox.h" + +UIntSpinBox::UIntSpinBox(QWidget *parent) + : QAbstractSpinBox(parent) +{ + // Don't let scrolling hijack focus. + setFocusPolicy(Qt::StrongFocus); + + m_minimum = 0; + m_maximum = 99; + m_value = m_minimum; + m_displayIntegerBase = 10; + m_numChars = 2; + m_hasPadding = false; + + this->updateEdit(); + connect(lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onEditFinished())); +}; + +void UIntSpinBox::setValue(uint32_t val) { + if (m_value != val) { + m_value = val; + emit valueChanged(m_value); + } + this->updateEdit(); +} + +uint32_t UIntSpinBox::valueFromText(const QString &text) const { + return this->stripped(text).toUInt(nullptr, m_displayIntegerBase); +} + +QString UIntSpinBox::textFromValue(uint32_t val) const { + if (m_hasPadding) + return m_prefix + QString("%1").arg(val, m_numChars, m_displayIntegerBase, QChar('0')).toUpper(); + + return m_prefix + QString::number(val, m_displayIntegerBase).toUpper(); +} + +void UIntSpinBox::setMinimum(uint32_t min) { + this->setRange(min, qMax(min, m_maximum)); +} + +void UIntSpinBox::setMaximum(uint32_t max) { + this->setRange(qMin(m_minimum, max), max); +} + +void UIntSpinBox::setRange(uint32_t min, uint32_t max) { + max = qMax(min, max); + + if (m_maximum == max && m_minimum == min) + return; + + if (m_maximum != max) { + // Update number of characters for padding + m_numChars = 0; + for (uint32_t i = max; i != 0; i /= m_displayIntegerBase) + m_numChars++; + } + + m_minimum = min; + m_maximum = max; + + if (m_value < min) + m_value %= min; + else if (m_value > max) + m_value %= max; + this->updateEdit(); +} + +void UIntSpinBox::setPrefix(const QString &prefix) { + if (m_prefix != prefix) { + m_prefix = prefix; + this->updateEdit(); + } +} + +void UIntSpinBox::setDisplayIntegerBase(int base) { + if (base < 2 || base > 36) + base = 10; + if (m_displayIntegerBase != base) { + m_displayIntegerBase = base; + this->updateEdit(); + } +} + +void UIntSpinBox::setHasPadding(bool enabled) { + if (m_hasPadding != enabled) { + m_hasPadding = enabled; + this->updateEdit(); + } +} + +void UIntSpinBox::updateEdit() { + const QString text = this->textFromValue(m_value); + if (text != this->lineEdit()->text()) { + this->lineEdit()->setText(text); + emit textChanged(this->lineEdit()->text()); + } +} + +void UIntSpinBox::onEditFinished() { + int pos = this->lineEdit()->cursorPosition(); + QString input = this->lineEdit()->text(); + + auto state = this->validate(input, pos); + if (state == QValidator::Acceptable) { + // Valid input + m_value = this->valueFromText(input); + } else if (state == QValidator::Intermediate) { + // User has deleted all the number text. + // If they did this by selecting all text and then hitting delete + // make sure to put the cursor back in front of the prefix. + m_value = m_minimum; + this->lineEdit()->setCursorPosition(m_prefix.length()); + } +} + +void UIntSpinBox::stepBy(int steps) +{ + auto new_value = m_value; + if (steps < 0 && new_value + steps > new_value) { + new_value = 0; + } else if (steps > 0 && new_value + steps < new_value) { + new_value = UINT_MAX; + } else { + new_value += steps; + } + this->setValue(new_value); +} + +QString UIntSpinBox::stripped(QString input) const { + if (m_prefix.length() && input.startsWith(m_prefix)) + input.remove(0, m_prefix.length()); + return input.trimmed(); +} + +QValidator::State UIntSpinBox::validate(QString &input, int &pos) const { + QString copy(input); + input = m_prefix; + + // Adjust for prefix + copy = this->stripped(copy); + if (copy.isEmpty()) + return QValidator::Intermediate; + + // Editing the prefix (if not deleting all text) is not allowed + if (pos < m_prefix.length()) + return QValidator::Invalid; + + bool ok; + uint32_t num = copy.toUInt(&ok, m_displayIntegerBase); + if (!ok || num < m_minimum || num > m_maximum) + return QValidator::Invalid; + + input += copy.toUpper(); + return QValidator::Acceptable; +} + +QAbstractSpinBox::StepEnabled UIntSpinBox::stepEnabled() const { + QAbstractSpinBox::StepEnabled flags = QAbstractSpinBox::StepNone; + if (m_value < m_maximum) + flags |= QAbstractSpinBox::StepUpEnabled; + if (m_value > m_minimum) + flags |= QAbstractSpinBox::StepDownEnabled; + + return flags; +} + +void UIntSpinBox::wheelEvent(QWheelEvent *event) { + // Only allow scrolling to modify contents when it explicitly has focus. + if (hasFocus()) + QAbstractSpinBox::wheelEvent(event); +} + +void UIntSpinBox::focusOutEvent(QFocusEvent *event) { + this->updateEdit(); + QAbstractSpinBox::focusOutEvent(event); +} From 30a01b7061eca84084da5b53f4f90334ebce9ea9 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 11 Sep 2023 16:32:15 -0400 Subject: [PATCH 27/34] Use UIntSpinBox for metatile attribute settings --- forms/projectsettingseditor.ui | 12 ++++++++++++ include/ui/projectsettingseditor.h | 1 + src/ui/projectsettingseditor.cpp | 19 ++++++++++++++----- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index 34504fb5b..0769ac7b4 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -331,6 +331,9 @@ 16 + + true +
@@ -388,6 +391,9 @@ 16 + + true + @@ -421,6 +427,9 @@ 16 + + true + @@ -448,6 +457,9 @@ 16 + + true + diff --git a/include/ui/projectsettingseditor.h b/include/ui/projectsettingseditor.h index 83fe741e6..5ba85813b 100644 --- a/include/ui/projectsettingseditor.h +++ b/include/ui/projectsettingseditor.h @@ -49,6 +49,7 @@ private slots: void dialogButtonClicked(QAbstractButton *button); void choosePrefabsFileClicked(bool); void importDefaultPrefabsClicked(bool); + void updateAttributeLimits(const QString &attrSize); void markEdited(); }; diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index ae64053e4..3afc77d1f 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -36,6 +36,7 @@ void ProjectSettingsEditor::connectSignals() { connect(ui->button_ChoosePrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::choosePrefabsFileClicked); connect(ui->button_ImportDefaultPrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::importDefaultPrefabsClicked); connect(ui->comboBox_BaseGameVersion, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::promptRestoreDefaults); + connect(ui->comboBox_AttributesSize, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::updateAttributeLimits); // Record that there are unsaved changes if any of the settings are modified for (auto combo : ui->centralwidget->findChildren()) @@ -71,12 +72,19 @@ void ProjectSettingsEditor::initUi() { ui->spinBox_Elevation->setMaximum(15); ui->spinBox_FillMetatile->setMaximum(Project::getNumMetatilesTotal() - 1); +} - // TODO: These need to be subclassed (or changed to line edits) to handle larger values - ui->spinBox_BehaviorMask->setMaximum(UINT_MAX); - ui->spinBox_EncounterTypeMask->setMaximum(UINT_MAX); - ui->spinBox_LayerTypeMask->setMaximum(UINT_MAX); - ui->spinBox_TerrainTypeMask->setMaximum(UINT_MAX); +void ProjectSettingsEditor::updateAttributeLimits(const QString &attrSize) { + QMap limits { + {"1", 0xFF}, + {"2", 0xFFFF}, + {"4", 0xFFFFFFFF}, + }; + uint32_t max = limits.value(attrSize, UINT_MAX); + ui->spinBox_BehaviorMask->setMaximum(max); + ui->spinBox_EncounterTypeMask->setMaximum(max); + ui->spinBox_LayerTypeMask->setMaximum(max); + ui->spinBox_TerrainTypeMask->setMaximum(max); } void ProjectSettingsEditor::createProjectPathsTable() { @@ -151,6 +159,7 @@ void ProjectSettingsEditor::refresh() { ui->comboBox_DefaultSecondaryTileset->setTextItem(projectConfig.getDefaultSecondaryTileset()); ui->comboBox_BaseGameVersion->setTextItem(projectConfig.getBaseGameVersionString()); ui->comboBox_AttributesSize->setTextItem(QString::number(projectConfig.getMetatileAttributesSize())); + this->updateAttributeLimits(ui->comboBox_AttributesSize->currentText()); // Set check box states ui->checkBox_UsePoryscript->setChecked(projectConfig.getUsePoryScript()); From a508677b1d1ee626b2960ab49b229705d54284e8 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 11 Sep 2023 16:54:15 -0400 Subject: [PATCH 28/34] Move remaining Porymap config settings to Preferences --- forms/mainwindow.ui | 19 ------------ forms/preferenceeditor.ui | 56 +++++++++++++++++++++++++++++++++-- include/mainwindow.h | 2 -- include/ui/preferenceeditor.h | 4 ++- src/mainwindow.cpp | 19 ++++-------- src/ui/preferenceeditor.cpp | 15 ++++++---- 6 files changed, 72 insertions(+), 43 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 91dfc192e..7b8aa8b49 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -3012,9 +3012,6 @@ Options - - - @@ -3064,22 +3061,6 @@ Ctrl+S - - - true - - - Monitor Project Files - - - - - true - - - Open Recent Project On Launch - - New Map... diff --git a/forms/preferenceeditor.ui b/forms/preferenceeditor.ui index c44fa98c9..6a0554809 100644 --- a/forms/preferenceeditor.ui +++ b/forms/preferenceeditor.ui @@ -18,6 +18,58 @@ 9 + + + + Miscellaneous + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Open recent project on launch + + + + + + + Monitor project files + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 20 + 20 + + + + + + + @@ -65,8 +117,8 @@ 0 0 - 582 - 372 + 570 + 322 diff --git a/include/mainwindow.h b/include/mainwindow.h index 36f89d487..9b51bc127 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -199,8 +199,6 @@ private slots: void on_checkBox_AllowBiking_stateChanged(int selected); void on_checkBox_AllowEscaping_stateChanged(int selected); void on_spinBox_FloorNumber_valueChanged(int offset); - void on_actionMonitor_Project_Files_triggered(bool checked); - void on_actionOpen_Recent_Project_On_Launch_triggered(bool checked); void on_actionShortcuts_triggered(); void on_actionZoom_In_triggered(); diff --git a/include/ui/preferenceeditor.h b/include/ui/preferenceeditor.h index c16716d94..c59641c2a 100644 --- a/include/ui/preferenceeditor.h +++ b/include/ui/preferenceeditor.h @@ -18,6 +18,7 @@ class PreferenceEditor : public QMainWindow public: explicit PreferenceEditor(QWidget *parent = nullptr); ~PreferenceEditor(); + void updateFields(); signals: void preferencesSaved(); @@ -27,9 +28,10 @@ class PreferenceEditor : public QMainWindow Ui::PreferenceEditor *ui; NoScrollComboBox *themeSelector; - void populateFields(); + void initFields(); void saveFields(); + private slots: void dialogButtonClicked(QAbstractButton *button); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e26dd3826..92fbb23f3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -452,8 +452,6 @@ void MainWindow::loadUserSettings() { ui->horizontalSlider_MetatileZoom->blockSignals(true); ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.getMetatilesZoom()); ui->horizontalSlider_MetatileZoom->blockSignals(false); - ui->actionMonitor_Project_Files->setChecked(porymapConfig.getMonitorFiles()); - ui->actionOpen_Recent_Project_On_Launch->setChecked(porymapConfig.getReopenOnLaunch()); setTheme(porymapConfig.getTheme()); } @@ -524,8 +522,11 @@ bool MainWindow::openProject(QString dir) { QObject::connect(editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered); QObject::connect(editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared); QObject::connect(editor->project, &Project::disableWildEncountersUI, [this]() { this->setWildEncountersUIEnabled(false); }); - QObject::connect(editor->project, &Project::uncheckMonitorFilesAction, [this]() { ui->actionMonitor_Project_Files->setChecked(false); }); - on_actionMonitor_Project_Files_triggered(porymapConfig.getMonitorFiles()); + QObject::connect(editor->project, &Project::uncheckMonitorFilesAction, [this]() { + porymapConfig.setMonitorFiles(false); + if (this->preferenceEditor) + this->preferenceEditor->updateFields(); + }); editor->project->set_root(dir); success = loadDataStructures() && populateMapList() @@ -1770,16 +1771,6 @@ void MainWindow::on_actionCursor_Tile_Outline_triggered() } } -void MainWindow::on_actionMonitor_Project_Files_triggered(bool checked) -{ - porymapConfig.setMonitorFiles(checked); -} - -void MainWindow::on_actionOpen_Recent_Project_On_Launch_triggered(bool checked) -{ - porymapConfig.setReopenOnLaunch(checked); -} - void MainWindow::on_actionShortcuts_triggered() { if (!shortcutsEditor) diff --git a/src/ui/preferenceeditor.cpp b/src/ui/preferenceeditor.cpp index 0ef62dcea..e2e4d916b 100644 --- a/src/ui/preferenceeditor.cpp +++ b/src/ui/preferenceeditor.cpp @@ -21,7 +21,8 @@ PreferenceEditor::PreferenceEditor(QWidget *parent) : setAttribute(Qt::WA_DeleteOnClose); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &PreferenceEditor::dialogButtonClicked); - populateFields(); + initFields(); + updateFields(); } PreferenceEditor::~PreferenceEditor() @@ -29,7 +30,7 @@ PreferenceEditor::~PreferenceEditor() delete ui; } -void PreferenceEditor::populateFields() { +void PreferenceEditor::initFields() { QStringList themes = { "default" }; static const QRegularExpression re(":/themes/([A-z0-9_-]+).qss"); QDirIterator it(":/themes", QDirIterator::Subdirectories); @@ -38,11 +39,14 @@ void PreferenceEditor::populateFields() { themes.append(themeName); } themeSelector->addItems(themes); - themeSelector->setCurrentText(porymapConfig.getTheme()); +} +void PreferenceEditor::updateFields() { + themeSelector->setCurrentText(porymapConfig.getTheme()); ui->lineEdit_TextEditorOpenFolder->setText(porymapConfig.getTextEditorOpenFolder()); - ui->lineEdit_TextEditorGotoLine->setText(porymapConfig.getTextEditorGotoLine()); + ui->checkBox_MonitorProjectFiles->setChecked(porymapConfig.getMonitorFiles()); + ui->checkBox_OpenRecentProject->setChecked(porymapConfig.getReopenOnLaunch()); } void PreferenceEditor::saveFields() { @@ -53,8 +57,9 @@ void PreferenceEditor::saveFields() { } porymapConfig.setTextEditorOpenFolder(ui->lineEdit_TextEditorOpenFolder->text()); - porymapConfig.setTextEditorGotoLine(ui->lineEdit_TextEditorGotoLine->text()); + porymapConfig.setMonitorFiles(ui->checkBox_MonitorProjectFiles->isChecked()); + porymapConfig.setReopenOnLaunch(ui->checkBox_OpenRecentProject->isChecked()); emit preferencesSaved(); } From 26620cd1d4b7a5ddbeb74d0b9395523c74d7bd46 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 11 Sep 2023 19:22:18 -0400 Subject: [PATCH 29/34] Update settings & options manual page --- docsrc/manual/settings-and-options.rst | 319 ++++++++++++++++++++----- 1 file changed, 259 insertions(+), 60 deletions(-) diff --git a/docsrc/manual/settings-and-options.rst b/docsrc/manual/settings-and-options.rst index 3679f3d70..12de5626a 100644 --- a/docsrc/manual/settings-and-options.rst +++ b/docsrc/manual/settings-and-options.rst @@ -5,66 +5,265 @@ Porymap Settings **************** Porymap uses config files to read and store user and project settings. + +=============== +Global settings +=============== + A global settings file is stored in a platform-dependent location for app configuration files (``%Appdata%\pret\porymap\porymap.cfg`` on Windows, ``~/Library/Application\ Support/pret/porymap/porymap.cfg`` on macOS). -A config file is also created when opening a project in porymap for the first time. It is stored in -your project root as ``porymap.project.cfg``. There are several project-specific settings that are -determined by this file. You may want to force commit this file so that other users will automatically have access to your project settings. - -A second config file is created for user-specific settings. It is stored in -your project root as ``porymap.user.cfg``. You should add this file to your gitignore. - -.. csv-table:: - :header: Setting,Default,Location,Can Edit?,Description - :widths: 10, 3, 5, 5, 20 - - ``recent_project``, , global, yes, The project that will be opened on launch - ``reopen_on_launch``, 1, global, yes, Whether the most recent project should be opened on launch - ``recent_map``, , user, yes, The map that will be opened on launch - ``pretty_cursors``, 1, global, yes, Whether to use custom crosshair cursors - ``map_sort_order``, group, global, yes, The order map list is sorted in - ``window_geometry``, , global, no, For restoring window sizes - ``window_state``, , global, no, For restoring window sizes - ``map_splitter_state``, , global, no, For restoring window sizes - ``main_splitter_state``, , global, no, For restoring window sizes - ``collision_opacity``, 50, global, yes, Opacity of collision overlay - ``metatiles_zoom``, 30, global, yes, Scale of map metatiles - ``show_player_view``, 0, global, yes, Display a rectangle for the GBA screen radius - ``show_cursor_tile``, 0, global, yes, Display a rectangle around the hovered metatile(s) - ``monitor_files``, 1, global, yes, Whether porymap will monitor changes to project files - ``tileset_checkerboard_fill``, 1, global, yes, Whether new tilesets will be filled with a checkerboard pattern of metatiles. - ``theme``, default, global, yes, The color theme for porymap windows and widgets - ``text_editor_goto_line``, , global, yes, The command that will be executed when clicking the button next the ``Script`` combo-box. - ``text_editor_open_directory``, , global, yes, The command that will be executed when clicking ``Open Project in Text Editor``. - ``base_game_version``, , project, no, The base pret repo for this project - ``use_encounter_json``, 1, user, yes, Enables wild encounter table editing - ``use_poryscript``, 0, project, yes, Whether to open .pory files for scripts - ``use_custom_border_size``, 0, project, yes, Whether to allow variable border sizes - ``enable_event_weather_trigger``, 1 if not ``pokefirered``, project, yes, Allows adding Weather Trigger events - ``enable_event_secret_base``, 1 if not ``pokefirered``, project, yes, Allows adding Secret Base events - ``enable_event_clone_object``, 1 if ``pokefirered``, project, yes, Allows adding Clone Object events - ``enable_hidden_item_quantity``, 1 if ``pokefirered``, project, yes, Adds ``Quantity`` to Hidden Item events - ``enable_hidden_item_requires_itemfinder``, 1 if ``pokefirered``, project, yes, Adds ``Requires Itemfinder`` to Hidden Item events - ``enable_heal_location_respawn_data``, 1 if ``pokefirered``, project, yes, Adds ``Respawn Map`` and ``Respawn NPC`` to Heal Location events - ``enable_floor_number``, 1 if ``pokefirered``, project, yes, Adds ``Floor Number`` to map headers - ``enable_map_allow_flags``, 1 if not ``pokeruby``, project, yes, "Adds ``Allow Running``, ``Allow Biking``, and ``Allow Dig & Escape Rope`` to map headers" - ``create_map_text_file``, 1 if not ``pokeemerald``, project, yes, A ``text.inc`` or ``text.pory`` file will be created for any new map - ``enable_triple_layer_metatiles``, 0, project, yes, Enables triple-layer metatiles (See https://github.com/pret/pokeemerald/wiki/Triple-layer-metatiles) - ``new_map_metatile``, 1, project, yes, The metatile id that will be used to fill new maps - ``new_map_elevation``, 3, project, yes, The elevation that will be used to fill new maps - ``new_map_border_metatiles``, "``468,469,476,477`` or ``20,21,28,29``", project, yes, The list of metatile ids that will be used to fill the 2x2 border of new maps - ``default_primary_tileset``, ``gTileset_General``, project, yes, The label of the default primary tileset - ``default_secondary_tileset``, ``gTileset_Petalburg`` or ``gTileset_PalletTown``, project, yes, The label of the default secondary tileset - ``custom_scripts``, , user, yes, A list of script files to load into the scripting engine - ``prefabs_filepath``, ``/prefabs.json``, project, yes, The filepath containing prefab JSON data - ``prefabs_import_prompted``, 0, project, no, Keeps track of whether or not the project was prompted for importing default prefabs - ``tilesets_have_callback``, 1, project, yes, Whether new tileset headers should have the ``callback`` field - ``tilesets_have_is_compressed``, 1, project, yes, Whether new tileset headers should have the ``isCompressed`` field - ``metatile_attributes_size``, 2 or 4, project, yes, The number of attribute bytes each metatile has - ``metatile_behavior_mask``, ``0xFF`` or ``0x1FF``, project, yes, The mask for the metatile Behavior attribute - ``metatile_encounter_type_mask``, ``0x0`` or ``0x7000000``, project, yes, The mask for the metatile Encounter Type attribute - ``metatile_layer_type_mask``, ``0xF000`` or ``0x60000000``, project, yes, The mask for the metatile Layer Type attribute - ``metatile_terrain_type_mask``, ``0x0`` or ``0x3E00``, project, yes, The mask for the metatile Terrain Type attribute - -Some of these settings can be toggled manually in porymap via the *Options* menu. +A selection of the settings in this file can be edited under ``Preferences...``, and the rest are updated automatically while using Porymap. + +================ +Project settings +================ + +A config file for project-specific settings is also created when opening a project in porymap for the first time. It is stored in your project root as ``porymap.project.cfg``. You may want to force commit this file so that other users will automatically have access to your project settings. + +A second config file is created for user-specific settings. It is stored in your project root as ``porymap.user.cfg``. You should add this file to your gitignore. + +The settings in ``porymap.project.cfg`` and ``porymap.user.cfg`` can be edited under ``Options -> Project Settings...``. Any changes made in this window will not take effect unless confirmed by selecting ``OK`` and then reloading the project. + +Each of the settings in the ``Project Settings...`` window are described below. + +.. warning:: + Changing any of the settings in the Project Settings Editor's red ``Warning`` box will require additional changes to your project to function correctly. Investigate the repository versions that have a setting natively supported to see what changes to your project are necessary. + + +Preferences +----------- + +Use Poryscript + If this is checked, a ``scripts.pory`` (and ``text.pory``, if applicable) file will be created alongside new maps, instead of a ``scripts.inc`` file. Additionally, ``.pory`` files will be considered when searching for scripts labels and when opening scripts files (in addition to the regular ``.inc`` files). + + Defaults to ``unchecked``. + + Field name: ``use_poryscript`` + +Show Wild Encounters + If this is checked, the ``Wild Pokemon`` tab will be enabled and wild encounter data will be read from the project's encounters JSON file. + + If no encounters JSON file is found this will be automatically unchecked. + + Field name: ``use_encounter_json`` + + +Default Tilesets +---------------- + +Default Primary/Secondary Tilesest + These will be the initially-selected tilesets when creating a new map, and will be used if a layout's tileset fails to load. If a default tileset is not found then the first tileset in the respective list will be used instead. + + The default primary tileset is ``gTileset_General``. + + The default secondary tileset is ``gTileset_PalletTown`` for ``pokefirered``, and ``gTileset_Petalburg`` for other versions. + + Field names: ``default_primary_tileset`` and ``default_secondary_tileset`` + + +New Map Defaults +---------------- + +Border Metatiles + This is a comma-separated list of metatile ID values that will be used to fill the border on new maps. If the number of metatiles in the border is not the same as the number of values in the list then the border will be filled with metatile ID ``0x000`` instead. + + Defaults to ``0x014,0x015,0x01C,0x01D`` for ``pokefirered``, and ``0x1D4,0x1D5,0x1DC,0x1DD`` for other versions. + + Field name: ``new_map_border_metatiles`` + +Fill Metatile + This is the metatile ID value that will be used to fill new maps. + + Defaults to ``0x1``. + + Field name: ``new_map_metatile`` + +Elevation + This is the elevation that will be used to fill new maps. New maps will be filled with passable collision. + + Defaults to ``3``. + + Field name: ``new_map_elevation`` + +Create separate text file + If this is checked, a ``text.inc`` (or ``text.pory``) file will be created alongside new maps. + + Defaults to ``unchecked`` for ``pokeemerald`` and ``checked`` for other versions. + + Field name: ``create_map_text_file`` + + +Prefabs +------- + +Prefabs Path + This is the file path to a ``.json`` file that contains definitions of prefabs. This will be used to populate the ``Prefabs`` panel on the ``Map`` tab. If no path is specified prefabs will be saved to a new ``prefabs.json`` file in the root project folder. A new file can be selected with the folder button. + + The ``Import Defaults`` button will populate the specified file with version-specific prefabs constructed using the vanilla tilesets. This will overwrite any existing prefabs. + + Field name: ``prefabs_filepath``. + + Additionally, there is a ``prefabs_import_prompted`` field that should not be edited. + + +Base game version +----------------- + + This is the name of base pret repository for this project. The options are ``pokeruby``, ``pokefirered``, and ``pokeemerald``, and can be selected (or automatically from the project folder name) when the project is first opened. Changing the base game version setting will prompt you to restore the default project settings for any of the three versions. You can also do this for the currently-selected base game version by selecting ``Restore Defaults`` at the bottom. For up-to-date projects changing this setting has no other effect. + + Field name: ``base_game_version`` + + +Tilesets / Metatiles +-------------------- + +Enable Triple Layer Metatiles + Metatile data normally consists of 2 layers with 4 tiles each. If this is checked, they should instead consist of 3 layers with 4 tiles each. Additionally, the ``Layer Type`` option in the ``Tileset Editor`` will be removed. Note that layer type data will still be read and written according to your ``Layer Type mask`` setting. + + For details on supporting this setting in your project, see https://github.com/pret/pokeemerald/wiki/Triple-layer-metatiles. + + Defaults to ``unchecked`` + + Field name: ``enable_triple_layer_metatiles`` + +Attributes size + The number of bytes used per metatile for metatile attributes. The data in each of your project's ``metatile_attributes.bin`` files will be expected to be ``s * n``, where ``s`` is this size and ``n`` is the number of metatiles in the tileset. Additionally, new ``metatile_attributes.bin`` will be included in the project with a corresponding ``INCBIN_U8``, ``INCBIN_U16``, or ``INCBIN_U32`` directive. + + Changing this setting will automatically enforce the new limit on the metatile attribute mask settings below. + + Defaults to ``4`` for ``pokefirered`` and ``2`` for other versions. + + Field name: ``metatile_attributes_size`` + +Attribute masks + Each of the following four settings are bit masks that will be used to read and write a specific metatile attribute from the metatile attributes data. If you are instead importing metatile attribute data from AdvanceMap, a default mask value will be used to read the data, and the mask value specified here will be used to write the new file. + + If any of the mask values are set to ``0x0``, the corresponding option in the Tileset Editor will be removed. The maximum for all the attribute masks is determined by the Attributes size setting. + +.. warning:: + If any of the metatile attribute masks have overlapping bits they may behave in unexpected ways. A warning will be logged in the Porymap log file if this happens + + +Metatile Behavior mask + See Attribute masks. This is the mask value for the ``Metatile Behavior`` metatile attribute. + + Defaults to ``0x1FF`` for ``pokefirered``, and ``0xFF`` for other versions. + + Field name: ``metatile_behavior_mask`` + +Layer Type mask + See Attribute masks. This is the mask value for the ``Layer Type`` metatile attribute. If the value is set to ``0x0`` the ``Layer Type`` option will be disabled in the Tileset Editor, and all metatiles will be treated in the editor as if they had the ``Normal`` layer type. + + Defaults to ``0x60000000`` for ``pokefirered`` and ``0xF000`` for other versions. + + Field name: ``metatile_layer_type_mask`` + +Encounter Type mask + See Attribute masks. This is the mask value for the ``Encounter Type`` metatile attribute. + + Defaults to ``0x7000000`` for ``pokefirered`` and ``0x0`` for other versions. + + Field name: ``metatile_encounter_type_mask`` + +Terrain Type mask + See Attribute masks. This is the mask value for the ``Terrain Type`` metatile attribute. + + Defaults to ``0x3E00`` for ``pokefirered`` and ``0x0`` for other versions. + + Field name: ``metatile_terrain_type_mask`` + +Output ``callback`` and ``isCompressed`` fields + If these are checked, then ``callback`` and ``isCompressed`` fields will be output in the C data for new tilesets. Their default values will be ``NULL`` and ``TRUE``, respectively. + + Defaults to ``checked`` for both. + + Field names: ``tilesets_have_callback`` and ``tilesets_have_is_compressed`` + + +Project Files +------------- + This is a list of the files and folders Porymap expects from your project. Each can be overridden by typing a new path or selecting a file/folder with the folder button. If the file/folder doesn't exist when the project is loaded then the default path will be used instead. + + For more information on each of these files/folders, see https://huderlem.github.io/porymap/manual/project-files.html + + Field name: ``path/`` + +Events +------ + +Enable Clone Objects + If this is checked Clone Object Events will be available on the ``Events`` tab. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#clone-object-events + + Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. + + Field name: ``enable_event_clone_object`` + +Enable Secret Bases + If this is checked Secret Base Events will be available on the ``Events`` tab. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#secret-base-event + + Defaults to ``unchecked`` for ``pokefirered`` and ``checked`` for other versions. + + Field name: ``enable_event_secret_base`` + +Enable Weather Triggers + If this is checked Weather Trigger Events will be available on the ``Events`` tab. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#weather-trigger-events + + Defaults to ``unchecked`` for ``pokefirered`` and ``checked`` for other versions. + + Field name: ``enable_event_weather_trigger`` + +Enable ``Quantity`` for Hidden Items + If this is checked the ``Quantity`` property will be available for Hidden Item Events. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#hidden-item-event + + Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. + + Field name: ``enable_hidden_item_quantity`` + +Enable ``Requires Itemfinder`` for Hidden Items + If this is checked the ``Requires Itemfinder`` property will be available for Hidden Item Events. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#hidden-item-event + + Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. + + Field name: ``enable_hidden_item_requires_itemfinder`` + +Enable ``Repsawn Map/NPC`` for Heal Locations + If this is checked the ``Respawn Map`` and ``Respawn NPC`` properties will be available for Heal Location events. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#heal-location-healspots + + Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. + + Field name: ``enable_heal_location_respawn_data`` + + +Maps +---- + +Enable ``Floor Number`` + If this is checked, a ``Floor Number`` option will become available on the ``Header`` tab and on the new map prompt. For more information see https://huderlem.github.io/porymap/manual/editing-map-header.html + + Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. + + Field name: ``enable_floor_number`` + +Enable ``Allow Running/Biking/Escaping`` + If this is checked, ``Allow Running``, ``Allow Biking``, and ``Allow Dig & Escape Rope`` options will become available on the ``Header`` tab and on the new map prompt. For more information see https://huderlem.github.io/porymap/manual/editing-map-header.html + + Defaults to ``unchecked`` for ``pokeruby`` and ``checked`` for other versions. + + Field name: ``enable_map_allow_flags`` + +Enable Custom Border Size + If this is checked, ``Border Width`` and ``Border Height`` options will become available under the ``Change Dimensions`` button and on the new map prompt. If it is unchecked all maps will use the default 2x2 dimensions. + + Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. + + Field name: ``use_custom_border_size`` + + +Additional Fields +----------------- + There are two additional fields in ``porymap.user.cfg`` that aren't described above. + + ``recent_map`` is the name of the most recently opened map and is updated automatically. This is the map that will be opened when the project is opened. If no map is found with this name (or if the field is empty) then the first map in the map list will be used instead. + + ``custom_scripts`` is a comma-separated list of filepaths to scripts for Porymap's API. These can be edited under ``Options -> Custom Scripts...``. For more information see https://huderlem.github.io/porymap/manual/scripting-capabilities.html From 0c47866e3d9f32be12506b15156d82c37d6f37dd Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 12 Sep 2023 13:25:16 -0400 Subject: [PATCH 30/34] Fix some window and scrollbox sizes --- forms/preferenceeditor.ui | 51 +++------- forms/projectsettingseditor.ui | 6 +- forms/tileseteditor.ui | 166 ++++++++++++++++++++------------- src/ui/preferenceeditor.cpp | 2 + src/ui/tileseteditor.cpp | 4 + 5 files changed, 119 insertions(+), 110 deletions(-) diff --git a/forms/preferenceeditor.ui b/forms/preferenceeditor.ui index 6a0554809..974d63226 100644 --- a/forms/preferenceeditor.ui +++ b/forms/preferenceeditor.ui @@ -6,8 +6,8 @@ 0 0 - 600 - 480 + 522 + 493 @@ -23,49 +23,20 @@ Miscellaneous - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Open recent project on launch - - - - + + Monitor project files - - - - Qt::Horizontal - - - QSizePolicy::Maximum - - - - 20 - 20 - + + + + Open recent project on launch - + @@ -117,8 +88,8 @@ 0 0 - 570 - 322 + 492 + 327 diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index 0769ac7b4..a24e8f832 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -6,8 +6,8 @@ 0 0 - 611 - 1137 + 600 + 600 @@ -29,7 +29,7 @@ 0 0 585 - 1486 + 585 diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 36e475124..6a2a4c69e 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -169,7 +169,7 @@ - QLayout::SetFixedSize + QLayout::SetMinimumSize 0 @@ -186,8 +186,8 @@ - - 1 + + 0 0 @@ -201,7 +201,44 @@ false - + + + + Bottom/Top + + + + + + + + + + Encounter Type + + + + + + + Terrain Type + + + + + + + + + + Metatile Label (Optional) + + + + + + + <html><head/><body><p>Copies the full metatile label to the clipboard.</p></body></html> @@ -215,46 +252,29 @@ - + true - - + + - Metatile Label (Optional) + Layer Type - - + + - Bottom/Top + Metatile Behavior - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Encounter Type - - + + @@ -278,44 +298,17 @@ - - - - - - - Layer Type - - - - - - - - - - Metatile Behavior - - - - - - - - - - - - - Terrain Type - - - + + + 0 + 0 + + Tile Properties @@ -331,7 +324,14 @@ - + + + + 0 + 0 + + + @@ -364,7 +364,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -402,6 +402,32 @@ + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + @@ -410,6 +436,12 @@ + + + 0 + 0 + + true @@ -419,7 +451,7 @@ 0 0 411 - 247 + 272 diff --git a/src/ui/preferenceeditor.cpp b/src/ui/preferenceeditor.cpp index e2e4d916b..f94c07da6 100644 --- a/src/ui/preferenceeditor.cpp +++ b/src/ui/preferenceeditor.cpp @@ -17,6 +17,8 @@ PreferenceEditor::PreferenceEditor(QWidget *parent) : ui->setupUi(this); auto *formLayout = new QFormLayout(ui->groupBox_Themes); themeSelector = new NoScrollComboBox(ui->groupBox_Themes); + themeSelector->setEditable(false); + themeSelector->setMinimumContentsLength(0); formLayout->addRow("Themes", themeSelector); setAttribute(Qt::WA_DeleteOnClose); connect(ui->buttonBox, &QDialogButtonBox::clicked, diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 8c4d67e15..fe6b6736e 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -117,6 +117,7 @@ void TilesetEditor::setAttributesUi() { for (int num : project->metatileBehaviorMapInverse.keys()) { this->ui->comboBox_metatileBehaviors->addItem(project->metatileBehaviorMapInverse[num], num); } + this->ui->comboBox_metatileBehaviors->setMinimumContentsLength(0); } else { this->ui->comboBox_metatileBehaviors->setVisible(false); this->ui->label_metatileBehavior->setVisible(false); @@ -129,6 +130,7 @@ void TilesetEditor::setAttributesUi() { this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER); this->ui->comboBox_terrainType->addItem("Waterfall", TERRAIN_WATERFALL); this->ui->comboBox_terrainType->setEditable(false); + this->ui->comboBox_terrainType->setMinimumContentsLength(0); } else { this->ui->comboBox_terrainType->setVisible(false); this->ui->label_terrainType->setVisible(false); @@ -140,6 +142,7 @@ void TilesetEditor::setAttributesUi() { this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND); this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER); this->ui->comboBox_encounterType->setEditable(false); + this->ui->comboBox_encounterType->setMinimumContentsLength(0); } else { this->ui->comboBox_encounterType->setVisible(false); this->ui->label_encounterType->setVisible(false); @@ -151,6 +154,7 @@ void TilesetEditor::setAttributesUi() { this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE); this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP); this->ui->comboBox_layerType->setEditable(false); + this->ui->comboBox_layerType->setMinimumContentsLength(0); if (!Metatile::getLayerTypeMask()) { // User doesn't have triple layer metatiles, but has no layer type attribute. // Porymap is still using the layer type value to render metatiles, and with From 8054a808a66d5c57b3c97b2806bae6cfeedc761f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 18 Sep 2023 16:49:26 -0400 Subject: [PATCH 31/34] Add images to settings/project files manual pages --- .../manual/images/project-files/settings.png | Bin 0 -> 117372 bytes .../base-game-version.png | Bin 0 -> 15346 bytes .../settings-and-options/default-tilesets.png | Bin 0 -> 34094 bytes .../images/settings-and-options/events.png | Bin 0 -> 48085 bytes .../images/settings-and-options/maps.png | Bin 0 -> 30494 bytes .../settings-and-options/new-map-defaults.png | Bin 0 -> 41836 bytes .../images/settings-and-options/prefabs.png | Bin 0 -> 27581 bytes .../settings-and-options/preferences.png | Bin 0 -> 25304 bytes .../tilesets-metatiles.png | Bin 0 -> 82220 bytes docsrc/manual/project-files.rst | 8 ++- docsrc/manual/settings-and-options.rst | 58 +++++++++++++++--- 11 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 docsrc/manual/images/project-files/settings.png create mode 100644 docsrc/manual/images/settings-and-options/base-game-version.png create mode 100644 docsrc/manual/images/settings-and-options/default-tilesets.png create mode 100644 docsrc/manual/images/settings-and-options/events.png create mode 100644 docsrc/manual/images/settings-and-options/maps.png create mode 100644 docsrc/manual/images/settings-and-options/new-map-defaults.png create mode 100644 docsrc/manual/images/settings-and-options/prefabs.png create mode 100644 docsrc/manual/images/settings-and-options/preferences.png create mode 100644 docsrc/manual/images/settings-and-options/tilesets-metatiles.png diff --git a/docsrc/manual/images/project-files/settings.png b/docsrc/manual/images/project-files/settings.png new file mode 100644 index 0000000000000000000000000000000000000000..91d55b4e90a44ae1a2fa845a128b80938c1ef922 GIT binary patch literal 117372 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 W0`!I!Rr2)z!)=yGtU1NhJ>h@m{)ET? literal 0 HcmV?d00001 diff --git a/docsrc/manual/images/settings-and-options/base-game-version.png b/docsrc/manual/images/settings-and-options/base-game-version.png new file mode 100644 index 0000000000000000000000000000000000000000..4cc450995bfc948a3babf4e37953476507d228e3 GIT binary patch literal 15346 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 VJYAt7LEvpLDKUA`3K4^^{|`jUEI0rF literal 0 HcmV?d00001 diff --git a/docsrc/manual/images/settings-and-options/default-tilesets.png b/docsrc/manual/images/settings-and-options/default-tilesets.png new file mode 100644 index 0000000000000000000000000000000000000000..073e90de9746f4613534c83a69c993d1a9932af6 GIT binary patch literal 34094 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

!0jKLW^K!I=(gNbYe(YwA|8(Tu{6X=@O_y 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 literal 0 HcmV?d00001 diff --git a/docsrc/manual/images/settings-and-options/events.png b/docsrc/manual/images/settings-and-options/events.png new file mode 100644 index 0000000000000000000000000000000000000000..ea6e517099b37824f094f35f4883b0f05dbf9555 GIT binary patch literal 48085 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 literal 0 HcmV?d00001 diff --git a/docsrc/manual/images/settings-and-options/maps.png b/docsrc/manual/images/settings-and-options/maps.png new file mode 100644 index 0000000000000000000000000000000000000000..3054c15518b551c0ecac4e3562bd445f97b75473 GIT binary patch literal 30494 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 literal 0 HcmV?d00001 diff --git a/docsrc/manual/images/settings-and-options/new-map-defaults.png b/docsrc/manual/images/settings-and-options/new-map-defaults.png new file mode 100644 index 0000000000000000000000000000000000000000..776984d1df0fc298022df307c224f59a4d7246c8 GIT binary patch literal 41836 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 n=y|rMqJO5&|M`aySi*>%U}^j$W literal 0 HcmV?d00001 diff --git a/docsrc/manual/images/settings-and-options/preferences.png b/docsrc/manual/images/settings-and-options/preferences.png new file mode 100644 index 0000000000000000000000000000000000000000..b1b5bf5e92798ee655ed2c7cba92453038ec2053 GIT binary patch literal 25304 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

w1xM=9UdX&s?6rGTO8^nQw-IZ6dzSGlo#P zzA&Q17#^j^V6?g@$b6_LBExu)!Xl9|7_GeY!EATzcuh&MXMOT6*2C+_A&9xR#nt02 zkOJ|U^^NJ~Ny%ru`&NT-=caJv@BKA&|Gk`+EH?Hvcy{QbmwUP_ZLDn1cZuM&H1`7> zrUb6{?Wl%cLn1eYcePNsgu#p((=lqp=z*citK%w>7)_pT1SU~x)nNF63zLHWbUrDs zLa?mmMNgVL+a7yC3UNKEpnz_5_ZP1#Id^ z`QaKFLoKJ!Y;L0zlzHML9Vcj_?`UH^s)vWMszQ|ZW)jvN7XP+bXz?scM#jtJo0X2R zroRgot#6ng@p_Y#H{GORx>ApYXN|_Lxc=dec>2x_`=tnx>{+nc|9GY6LXVpr-t=g| z#!K~}`N7NG1`N*Io2lx9t|%WOu*+Cmc`L?Ql@eXeH?PcM%M9$jXH(wEMScRB_Vqiy zMku$wQahY_IxSnx)6@RK_6E#Itea`nnmJ5wIU&|X!Zd8u$XMN*r(iGcp6pNsiR`h5 zP4(ngLuKc!nBGN4gmPs|>%Tg$YFdwB9(3{rTk0@yt!S8M>pe-CqfSluUe>tds{B1zS#Et1nd(iRqZpo~>P16QCFjoe?=l35S_E2FoZarYsALaHgZ!Z#4DAWk!USyIOM8i4sw1}`sJGg4ZYKbX{ zSDhum)eCx=-gMy9m!s$Y(s~z+oz-MeWwV(+{M9;P1%wH$KG4K6**(+Nv4NJS(0gajPb zAN5)><-gm|=68lvhOnhEM??CtcBZti?qy`%XM;zNILOxiCnnxNgw`faIOl>_;|sk~Br(Qq z0NE#KtbAo(Fq`vd$D}*GRhuZ84*w|C%ms$&qBK~R{Bb4E(dl&Ms39#94ws@k7@a%R z8D+t1b1o*XL(XpJLgP-9-nfJ*j-ia$9$u@b_)`k8u&meFzIu77qUBp=*1)vuk9e6y z0$*JvE@=cO*3@8c>mF`;Yk7-|_vsB{#$bz6JRK_Eg^L>KdtQgkEyEbFqV~p&Z085% zGAH*g2l|dJV8*9YyCy#dqBFbMx!FuM_AzVa939Q?TzPc8izBfgH17;h1x5F6y8Gv* zt4R!o4~g!=$_+9~Ua&=r3dqn+O zUQ&5P9?>j$z{B`1a&J8XHiHz^utxNj)5_NGniWJ|C5@&$UrXY!@d-_dAe~qEyV%_i zDK64+gSyn#zV*TCuezP@HM8cPk8D6}z)@_hAvbOjeA;T`koZ7H2&S25mf8&@k=@hZ zldowvVLXOkiqniH91+I8-UkB|2sa*f)FAT?}M(pVRXL1tt$bvM=nb=|HXtR*Yy_oif=%=b@T zLG}z}&g@j^8P9(hDi%v7`D6$xeL2UoD0=YmC^Gpbm{@LK?KmU|_0$Ft2=ddL1{;i} z=}s${SRwBCc+yO;Dm_J>?GIMJh8$+uIoPf7Esp+x4c*Q3O07XE`0>)H>Jk`xNjx_VkXszGQ2eNcIrAbKyIyrWP=6oUZ$v7=aU#dLY4FIP4-lz@H1%6{ zV-Z}Hk1vPNJMv|`;5|NuX(h8hg%Rl2I(D4vAHP*dynvdIH_!0^xUS=C zH@a2n*>>QUyV_5&6;KK9-@T7DeRSqCmvfDF-wW9VUdHUwG%#&E6v^KYhpI#fdUY9E zhaf9$h~*V7PEefO&(e?*#YBZ=pqLC4nx01x@4DY+vmdH(Cu(;l9U&7? zjA+r)ez`USY2$kO()MEW5pE6XC^Mm09L9tb7_e?TKRa%-ne2%Y$N(Z-1&C%hQ=~GNQMp*pX@dTHf#>h1J`D zBF`k}*6Pr^`-l4AyApJLe2eIMMzzD8C`X*tq{tzn)J`UHCblBmGr@J=q5CS~x7h`& zNLR2V?a`m|8wvdVY*~HIed|;Z-JWx zdaka&5<++laQ1#ozq7=P=*$9jzyWq1V=F264q-cN_Z2CIw+L56@lU2td9RJ@_O5Co z)L_M2Gd;@(8;9NRbM`zO-vmacSbgxLQ6yNPDPFM@OBS!pe4~jp6I0Llu70qKOIVOR z92(+$xU1rg4E)in?totuTlXc76dhw5X(P_&?P0RX?2|-3>YIxUVUct5aO?*;ck^*C z**GonrAi27GPVk2rU|nNCsnwH@b)Vf}~u8oj)Pxp28F3#Wi z^kaqzbKff#IDl{JraKN;TwHbQ9Y%Lm1-2c5TkqqatS6_C_R@pc$8z280U^x8~jK;^33`e6k-fR?Ny=iJvk^K?^ix^o70_t8JI22^edI+beh;TFk$U-Zb$#aw4A74>Y-7lV`)N&svt|9p1GPJ_La9UueXsi z>t-4*YD~=y0^D=w!RG_O-EW$v#bdNxJ;PoX0hVWOs8MXqKe3yxtU?5g&M$waPUrcS zgA>KH@8I@Z*?Gor+dQ%*J+qOFhGG<@`%Xk7*U}g0y|2nR6Wub-CAZ}CIs4dwhw~LU z5$Ks5ee@P@X5y-5+L44q>nD>dkVE0K4+6IVUbp{-0{DI~=aG?N5{>YIey+ zOQh@~f+4!mlGXcSqxW8dL@%QyN`#4Sf(+54&LRkA3?UeVL>pxgiEbDS2BUl@@8-MK z`+EQS{`>wr*Y#ZIJomZ#^W4At_8C-%SG|{zsiik|w2v1T?54Rgg;EJ&Knza*ZoAl& zxeaaam68Mb9KX`-*0d~}IH=zYS>Q{Mwf(wz~%0oGT!^*ptEuWcCGPV=OH5IBSzmo<%7|N|z z%#{x@@@!h>4LaJvtqt5o_)9#+W_Mjkc=^st;TNhTpfhY+rT!DzP;LF>d#O z7%OF)q!O#Z&^xT}?gn2AMDrcCKYIdaJRu0(yf$Rh>toc~{ZgsKES9UXpIJ&1@hR>} zuP7_6*T{p^g)517IWw%j^`l+@DTR2))KLp4K_YF%ut~iBO426ODXf3@vk-)sAko2- zg!GX+oDvW#H&#I%6X&xwqPAXuQQOA3`zY;zU>WxLc`k0d9ItKqO)8NC?TJ+T%#qY@ zasxn~>Ormqa}030UPg2Z<$A7No&%jR+k8Mg~QoPz1NR7 zE;P$ktO3|pEM=OkK(`w=d6kVMX2Zo0fj=No4 z>2-N{fy=CRVEAPj1iM!<8r1f!03Mg2d+KSnB2(C|XANd8oU?Kpfjp1WwB^gPslxZ+L z_cfTLtI_;+gY(*!-q&n&8CmXFwW)aqHzu)|`gwcu5Ee|jk0<^5l)=f(c~U^k{aF`3 zLZGAz!IuD;r8Ry9ttIBU1|Mrj;(dML4NZR@`(Xn|)eDxytGuM{GfU~HA5UGYeFE3f z@{8szpWfb>r{#y)sCN5>ytH%?CFg|t4d#k}uD5PM*~Q5%tAY=^5PAzUZ|jhJLFUT_ z5OMe4{arH52NHrE7u-iLt>Q_T1W*F+y36=29)?N`32$8S)?ht+gWFUDEls`=a_Um% zoia@f6x4YqR*gGI+0D%jf2&#{e3rqwyO|uH-WGka^_|p$dGv>ilFH(NcoKmLxyd8N-WwcM4gm zi)DB9UaVp!*A;?Dk2@T2n~QTgK!7;ocoB1;vK*G|Y0i2sTqfVV1=4_c3)ZWttZ+Y)K5wd4@P%*?ri!43k$yJmTu? zv<(pxhvC|npaYlt`XAaXTEh1ZR9|Ib@6nY|5H;N6B?W2?Gi<78o%Kj4s%>*d4(8$LYY6N5aCS_uk^&6?XYUy zbsZ3I`cl#f+22gn{UnAf-Y-4N(=AHoaha^c?fkZH1D)=uELi^AeroU7erh`j$0nv{ z>_7p|n*3pD(_jW_;dCuby?9kHdtq?6U%sm>081|K$I>8POO-S{KXC&38kL;CLh{Na z<~^Z{R*l83IVJ@m?|H3vc-JaZ&=iF`qy-b!(oSEhPmA8XpgQmhknq4912D*H_bM94 zZS@*adK5lLh-&|Q3avu0W5&!Uo{ybxSodjdlu_x$s74$hSmynfKN#(u$w6FnB)l(aXGDXK^`ysb1V)+53F0yM zLh)Y4UKLS&jl)g^D(3ZK;p4qnu5w!rKjA$~A9Mfyya{xdA5T5>GAtgFy`$?0jO7)$mo3mN>(Y>Dq^US|$BEA|G>B+vta{4mlza zDkW$c>pLqAJ$%f+vw*RO+BX;)%`g(^*Cnfm*cUXT(~|dki9~x z>5G=t!U@N&Q6hG-DTZ`GQO4S->#f3)#1tKZRHX&U0|42+b@^_|eg%f3%gTdHqq&-Y z?$hjMlL;BN>YQYgj-PmketVlE!=_mxVNrn8FTmd`%MR%FLktCz))%?^B%O41xA2IMAR%q$UHLOcqx3Z{VFAA7tnNq4yZFb z%}DIc!?aW;hTk6YX81bC3uf1g)Y>Iiy&0?!DC?-uxS!7{H_Fr~jJ!*9zr4@OKJw)` zSj}9lc}%`{dV?ucG;F!Q*xN{cOP9WQIjIgpxGg5{%KKp3q0I_B<+0yKh|)((pcehN z#6lLODX#*4IGB$y#W`t%Uj}Ie-Z`Mf|MFR)NaXt*aS9_^{nqSE?J8UB(Nz0R{;Egr zc#29kwJNm}f-+z4s#U|9W28aCLLM76_^-e9=+ewgHq|ph#U*~kx{;7tPD#I3u(iic z)lE#^njE_MWhq0?2IGSn4GD0?+p}0D8Z>$1q6j^fkn?&k9-8N5hGXB|bM95mtQQ$_ z?`NcX7Zl**r79^u?Mq@B#%iBe1@Vf%9w|D9#AZgobH1GDic}E#e6cQ;3o`E#cH&BK zn&UMD>$++O-)(X-CTw_JJ|AsEFs(>%9vzv;SaI_hHBlqCz_3+*nfnWdOqoRaZ-Uk! zr`+>4ng?Ueo!!|wr|x;d8LfZOwVJ$E1e(i=3JW`&v-OBE67O(D8{o{3*;>PwVy5d=oQht z$sRLJVj+vW2O5%AM9H;{vrMVo1Q=l?FLp}R<8?J*eZZA)5F5PIuJvs?q{#QZv{6WWYUYgLSq(6>F3J(n6s9C#F6?+3rC?XB6{b?ln z32wOkoLU2vin2C2a6Dwm8IXQQ$Gl2lTkcU;mm^{6v1sWSVcG9#)q46zK_i~Y>u4=a zg~0T}=CG1>8*ZtXwmoC=%6ikn(R}mTLbf4a<*PoP{Pgk~EAEyOiz$fP*z?GF|N8Zztt7Fna7?p49Nyq$*n@iYpp&4dil$%Ss<@uMGdZ8r zIJDh-tMbDkL(t)BFP>6{FJpBc5UQ^gf9lf|l|nFUR#w=(S&kc--1?d)Z&2%?vrAE1 z%!jn-Ji|EjM2G)_N&pK*+Wrzz{d}QcmYC)-S>ITc_FW$et!QnwQNwX1^M;O@JZ4kz zY92JeQ7FTfSuzkMh_dczAM{;9l6l6hiD;ig^Xjt7tv{#mN&CVqHIF+lV_)R6)XvV$ zee!cD(9T)xD>dX7LP~ZQ=D@&@YA&KEAtQhe7h{TLVUFPj;ROSjn&*l|zeJec5v!Q@ zq+$vRz)1R&m;Z=osf{#WsA$7H$HF5A8(p0c8K(qoOo?^hiS#1=VZ zGUw9GtxnmGWf(izs`>0@4mb_Rb^j8VkV8M~YB1OoQa+4);}ddE1}BItg9|^H;jezb zaoY^JngUTk=jmo}pam-2JA29)`c=95`5(YkJ_^FlScGK)LAQ=vI; zAf+5?=}L}k{-&YCnVw5VD=66m#7~FQ8*-KN1H>fzW+@kWmkr!gljw(`+qRjqBTT6d z+#lYAv_TQhI{ym+1N-kjTQEII3|I{7GL0Rgli3?{3X<+Uy%f#F zFKb51ORgW{);uh?uI_NIm;@FnzIl8sKvqzJq}T9$9tp2#^li5urI$lEJER>an~*+O zS(@B_+W4l@dufm|tRF2}k0WQLRCP>3Ow>(X{dzKoZ--n=NoX{qXXvYP zoZU8~+fiVFbZatnl_eUxhhFX5(@$&*I~9bezE{p~EKV~N&M!WJ9h?cW!vT-2zRD8o=LYx3(|Mp7x)1c#$Mq}`+<;(W)MQ9$ zXSoysES>);SL;9fS0h?Ce!2k?lk3SWQ9i?^a{!7;EMm`s^9&I&u>c-wR=;14=PZ|A z154*R76;D~@&8&>j3%Js*RNZ{2>J!8OkckJ7yjS-@}8k^$dz)-($aF5vbPD$Nn3iR zd~4H6!TFU!=!C8=i1)h0;8`^&5`6TTS_FyS&06zYtHVtY3)B)@(vIE*oRRRoFDNP? zg47Nj9+NQ*Gf2$w0V&6xx4ZcQ<2m-!M2|BsurpJ!$%9Be0?4r{W9!hmBL$~EcFIvr zFBpIrC$QUMNTzdhED>iJfIzH2 z7pS_ZbG=UNUmwrEJ$`n8q>@f69ZH(WCIk{2z7fQI=3no9`JG{IihAMqnVLEFr^ ZgyrHdmHwP%@_kaNhKjCo)$cY>{s&Xj3p)S+ literal 0 HcmV?d00001 diff --git a/docsrc/manual/images/settings-and-options/tilesets-metatiles.png b/docsrc/manual/images/settings-and-options/tilesets-metatiles.png new file mode 100644 index 0000000000000000000000000000000000000000..96f312c95d4c49773ba717c2b8e771a2767d9e98 GIT binary patch literal 82220 zcmeFYWmsIv6E}(k2qBOF0fIXOf;%&~6WlF8a2ebNw**K+@Zjza!GpWIy9IX{2A6lT zyZ_zI=6<}-eeQ=Bo;eKXbXRvtS9RB~&L>5AN%SWKPvGF-(50osl;PkW@xZ|$7(PaZ z-JzItpn`*YN^2o1swgcgN~Y*wYieO-0tYAcDLNKKHL4facZ*qCO3K{tu@q_}s&bZ0 zDg2|XCtM;}Qm@FV9$^B@^IEhO%if7=h+Bc+jmr#Ls~?}=3yF(q;h}MXcdK^rcH z>bC|Sd}ZLC>7fOXG@hNzI7hw_g#Eu#|8;HXpP?9~ft~ z##VV{-({Y5rn8nOnK<_kpvJP|oVpoU8ow|`@0mt=Tif_0^)x&EMD(1LClXGRy#)>~ z+hNvkH5^Jth*m*C8F;p2;r|ZTSkr?;KD_(0$`|q4A4zfK59aU+STBGBR%M<{@pAbb z>`S&iTQmY;ock4J;iR#7AF-|b@u6Zj3Eu-q|bS+C}X;M3jnKj$(^MO|$6OB(yDBxP38b?b=kq^^G|#AH@Qh)AK`FyceH*J|>~k z_+q>?I#zVaUp5O$6fGV4E_jG^C%VjoIE_?&$-@&xdWg8?5;%8c6dh`OTO1?W)N^k9 zmGASuO!X}*0uBgg3zND0jh8-}_}hHS$tN#&u2{o-k9NBQj*dwg%Q|Psi;#c;x-ALc z+*>;2-=WW#?8kkPoa(~9ntPeTC_$n?b4Gb-A#gsDR9+yx4?6JJ7kmcw3}{ZcO00}Jj#IZyT>$Eclu zds_u=`>1J0RcuRfHn^B^9c)@E9gJg}5mtS_E4bf>xN7xMlcq zL}m}&I>K1!f-oS0WS#RAwNsJ4;L~pA=CJBVrpE~2 z?1ejOqn}F}^N9D;cYQAr+1spGxf$Ss+ak+2WWNk{zA1ZCL@*!3+2(UiFy#j|B(

  • TviW@x%Lvv?1_>wJcSPVkg{6N-ygbR^nGl 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 g-|5MkhZ#17j58eDm2qa~yMT|bwjm_ Project Settings``. A new path can be specified by entering it in the text box or choosing it with the folder button. Paths are expected to be relative to the root project folder. If no path is specified, or if the file/folder specified does not exist, then the default path will be used instead. The name of each setting in this section is listed in the table below under ``Override``. + +.. figure:: images/project-files/settings.png + :align: center + :width: 75% + :alt: Settings .. csv-table:: diff --git a/docsrc/manual/settings-and-options.rst b/docsrc/manual/settings-and-options.rst index 12de5626a..359a81c84 100644 --- a/docsrc/manual/settings-and-options.rst +++ b/docsrc/manual/settings-and-options.rst @@ -34,6 +34,11 @@ Each of the settings in the ``Project Settings...`` window are described below. Preferences ----------- +.. figure:: images/settings-and-options/preferences.png + :align: left + :width: 60% + :alt: Preferences + Use Poryscript If this is checked, a ``scripts.pory`` (and ``text.pory``, if applicable) file will be created alongside new maps, instead of a ``scripts.inc`` file. Additionally, ``.pory`` files will be considered when searching for scripts labels and when opening scripts files (in addition to the regular ``.inc`` files). @@ -41,7 +46,7 @@ Use Poryscript Field name: ``use_poryscript`` -Show Wild Encounters +Show Wild Encounter Tables If this is checked, the ``Wild Pokemon`` tab will be enabled and wild encounter data will be read from the project's encounters JSON file. If no encounters JSON file is found this will be automatically unchecked. @@ -52,6 +57,11 @@ Show Wild Encounters Default Tilesets ---------------- +.. figure:: images/settings-and-options/default-tilesets.png + :align: left + :width: 60% + :alt: Default Tilesets + Default Primary/Secondary Tilesest These will be the initially-selected tilesets when creating a new map, and will be used if a layout's tileset fails to load. If a default tileset is not found then the first tileset in the respective list will be used instead. @@ -65,6 +75,11 @@ Default Primary/Secondary Tilesest New Map Defaults ---------------- +.. figure:: images/settings-and-options/new-map-defaults.png + :align: left + :width: 60% + :alt: New Map Defaults + Border Metatiles This is a comma-separated list of metatile ID values that will be used to fill the border on new maps. If the number of metatiles in the border is not the same as the number of values in the list then the border will be filled with metatile ID ``0x000`` instead. @@ -97,6 +112,11 @@ Create separate text file Prefabs ------- +.. figure:: images/settings-and-options/prefabs.png + :align: left + :width: 60% + :alt: Prefabs + Prefabs Path This is the file path to a ``.json`` file that contains definitions of prefabs. This will be used to populate the ``Prefabs`` panel on the ``Map`` tab. If no path is specified prefabs will be saved to a new ``prefabs.json`` file in the root project folder. A new file can be selected with the folder button. @@ -110,14 +130,24 @@ Prefabs Path Base game version ----------------- - This is the name of base pret repository for this project. The options are ``pokeruby``, ``pokefirered``, and ``pokeemerald``, and can be selected (or automatically from the project folder name) when the project is first opened. Changing the base game version setting will prompt you to restore the default project settings for any of the three versions. You can also do this for the currently-selected base game version by selecting ``Restore Defaults`` at the bottom. For up-to-date projects changing this setting has no other effect. +.. figure:: images/settings-and-options/base-game-version.png + :align: left + :width: 60% + :alt: Base Game Version - Field name: ``base_game_version`` +This is the name of base pret repository for this project. The options are ``pokeruby``, ``pokefirered``, and ``pokeemerald``, and can be selected (or automatically from the project folder name) when the project is first opened. Changing the base game version setting will prompt you to restore the default project settings for any of the three versions. You can also do this for the currently-selected base game version by selecting ``Restore Defaults`` at the bottom. For up-to-date projects changing this setting has no other effect. + +Field name: ``base_game_version`` Tilesets / Metatiles -------------------- +.. figure:: images/settings-and-options/tilesets-metatiles.png + :align: left + :width: 60% + :alt: Tilesets / Metatiles + Enable Triple Layer Metatiles Metatile data normally consists of 2 layers with 4 tiles each. If this is checked, they should instead consist of 3 layers with 4 tiles each. Additionally, the ``Layer Type`` option in the ``Tileset Editor`` will be removed. Note that layer type data will still be read and written according to your ``Layer Type mask`` setting. @@ -173,7 +203,7 @@ Terrain Type mask Field name: ``metatile_terrain_type_mask`` -Output ``callback`` and ``isCompressed`` fields +Output 'callback' and 'isCompressed' fields If these are checked, then ``callback`` and ``isCompressed`` fields will be output in the C data for new tilesets. Their default values will be ``NULL`` and ``TRUE``, respectively. Defaults to ``checked`` for both. @@ -192,6 +222,11 @@ Project Files Events ------ +.. figure:: images/settings-and-options/events.png + :align: left + :width: 60% + :alt: Events + Enable Clone Objects If this is checked Clone Object Events will be available on the ``Events`` tab. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#clone-object-events @@ -213,21 +248,21 @@ Enable Weather Triggers Field name: ``enable_event_weather_trigger`` -Enable ``Quantity`` for Hidden Items +Enable 'Quantity' for Hidden Items If this is checked the ``Quantity`` property will be available for Hidden Item Events. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#hidden-item-event Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. Field name: ``enable_hidden_item_quantity`` -Enable ``Requires Itemfinder`` for Hidden Items +Enable 'Requires Itemfinder' for Hidden Items If this is checked the ``Requires Itemfinder`` property will be available for Hidden Item Events. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#hidden-item-event Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. Field name: ``enable_hidden_item_requires_itemfinder`` -Enable ``Repsawn Map/NPC`` for Heal Locations +Enable 'Repsawn Map/NPC' for Heal Locations If this is checked the ``Respawn Map`` and ``Respawn NPC`` properties will be available for Heal Location events. For more information see https://huderlem.github.io/porymap/manual/editing-map-events.html#heal-location-healspots Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. @@ -238,14 +273,19 @@ Enable ``Repsawn Map/NPC`` for Heal Locations Maps ---- -Enable ``Floor Number`` +.. figure:: images/settings-and-options/maps.png + :align: left + :width: 60% + :alt: Maps + +Enable 'Floor Number' If this is checked, a ``Floor Number`` option will become available on the ``Header`` tab and on the new map prompt. For more information see https://huderlem.github.io/porymap/manual/editing-map-header.html Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions. Field name: ``enable_floor_number`` -Enable ``Allow Running/Biking/Escaping`` +Enable 'Allow Running/Biking/Escaping' If this is checked, ``Allow Running``, ``Allow Biking``, and ``Allow Dig & Escape Rope`` options will become available on the ``Header`` tab and on the new map prompt. For more information see https://huderlem.github.io/porymap/manual/editing-map-header.html Defaults to ``unchecked`` for ``pokeruby`` and ``checked`` for other versions. From 22fe7f2963f5f70af4be64314f85a59cbf43a593 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 19 Sep 2023 14:21:36 -0400 Subject: [PATCH 32/34] Use spin boxes for border metatile settings if using default size --- .../settings-and-options/new-map-defaults.png | Bin 41836 -> 42525 bytes docsrc/manual/settings-and-options.rst | 6 +- forms/projectsettingseditor.ui | 179 ++++++++++++------ include/config.h | 1 - include/core/metatile.h | 10 +- include/ui/projectsettingseditor.h | 4 + include/ui/uintspinbox.h | 2 +- src/config.cpp | 10 +- src/project.cpp | 4 - src/ui/projectsettingseditor.cpp | 66 +++++-- 10 files changed, 198 insertions(+), 84 deletions(-) diff --git a/docsrc/manual/images/settings-and-options/new-map-defaults.png b/docsrc/manual/images/settings-and-options/new-map-defaults.png index 776984d1df0fc298022df307c224f59a4d7246c8..50b557f7702a58f7a7b25a210bb098e4bbef593a 100644 GIT binary patch literal 42525 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 kHdgtE&I&;yf&_P$m)tYYH8WT8 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 Map Defaults - - + + - A comma-separated list of metatile values that will be used to fill new map borders + The default metatile value that will be used to fill new maps + + + 0x + + + 16 - + Elevation - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Whether a separate text.inc or text.pory file will be created for new maps, alongside the scripts file - - - Create separate text file - - - - + The default elevation that will be used to fill new maps - + Fill Metatile - - + + + + Whether a separate text.inc or text.pory file will be created for new maps, alongside the scripts file + - Border Metatiles + Create separate text file - - - - The default metatile value that will be used to fill new maps - - - 0x - - - 16 - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Border Metatiles + + + + + + + A comma-separated list of metatile values that will be used to fill new map borders + + + + - - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Border Metatiles + + + + + + + The default metatile value that will be used for the top-left border metatile on new maps. + + + 0x + + + 16 + + + + + + + The default metatile value that will be used for the top-right border metatile on new maps. + + + 0x + + + 16 + + + + + + + The default metatile value that will be used for the bottom-left border metatile on new maps. + + + 0x + + + 16 + + + + + + + The default metatile value that will be used for the bottom-right border metatile on new maps. + + + 0x + + + 16 + + + + + diff --git a/include/config.h b/include/config.h index 96086749d..7f10ce917 100644 --- a/include/config.h +++ b/include/config.h @@ -267,7 +267,6 @@ class ProjectConfig: public KeyValueConfigBase int getNewMapElevation(); void setNewMapBorderMetatileIds(QList metatileIds); QList getNewMapBorderMetatileIds(); - QString getNewMapBorderMetatileIdsString(); QString getDefaultPrimaryTileset(); QString getDefaultSecondaryTileset(); void setDefaultPrimaryTileset(QString tilesetName); diff --git a/include/core/metatile.h b/include/core/metatile.h index c3bda046c..ed1f84ee4 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -93,7 +93,15 @@ class Metatile static QPoint coordFromPixmapCoord(const QPointF &pixelCoord); static int getDefaultAttributesSize(BaseGameVersion version); static void setCustomLayout(Project*); - static QString getMetatileIdString(uint16_t metatileId) { return "0x" + QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper(); }; + static QString getMetatileIdString(uint16_t metatileId) { + return "0x" + QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper(); + }; + static QString getMetatileIdStringList(const QList metatileIds) { + QStringList metatiles; + for (auto metatileId : metatileIds) + metatiles << Metatile::getMetatileIdString(metatileId); + return metatiles.join(","); + }; private: // Stores how each attribute should be laid out for all metatiles, according to the user's config diff --git a/include/ui/projectsettingseditor.h b/include/ui/projectsettingseditor.h index 5ba85813b..3bd4d9214 100644 --- a/include/ui/projectsettingseditor.h +++ b/include/ui/projectsettingseditor.h @@ -42,6 +42,10 @@ class ProjectSettingsEditor : public QMainWindow bool promptSaveChanges(); bool promptRestoreDefaults(); + void setBorderMetatilesUi(bool customSize); + void setBorderMetatileIds(bool customSize, QList metatileIds); + QList getBorderMetatileIds(bool customSize); + void createProjectPathsTable(); QString chooseProjectFile(const QString &defaultFilepath); diff --git a/include/ui/uintspinbox.h b/include/ui/uintspinbox.h index b561e2194..dc08c9eb6 100644 --- a/include/ui/uintspinbox.h +++ b/include/ui/uintspinbox.h @@ -64,4 +64,4 @@ public slots: void textChanged(const QString &text); }; -#endif // UINTSPINBOX_H \ No newline at end of file +#endif // UINTSPINBOX_H diff --git a/src/config.cpp b/src/config.cpp index 8c51de9f4..681dc3f90 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -735,7 +735,7 @@ QMap ProjectConfig::getKeyValueMap() { map.insert("enable_triple_layer_metatiles", QString::number(this->enableTripleLayerMetatiles)); map.insert("new_map_metatile", Metatile::getMetatileIdString(this->newMapMetatileId)); map.insert("new_map_elevation", QString::number(this->newMapElevation)); - map.insert("new_map_border_metatiles", this->getNewMapBorderMetatileIdsString()); + map.insert("new_map_border_metatiles", Metatile::getMetatileIdStringList(this->newMapBorderMetatileIds)); map.insert("default_primary_tileset", this->defaultPrimaryTileset); map.insert("default_secondary_tileset", this->defaultSecondaryTileset); map.insert("prefabs_filepath", this->prefabFilepath); @@ -983,14 +983,6 @@ QList ProjectConfig::getNewMapBorderMetatileIds() { return this->newMapBorderMetatileIds; } -QString ProjectConfig::getNewMapBorderMetatileIdsString() { - QStringList metatiles; - for (auto metatileId : this->newMapBorderMetatileIds){ - metatiles << Metatile::getMetatileIdString(metatileId); - } - return metatiles.join(","); -} - QString ProjectConfig::getDefaultPrimaryTileset() { return this->defaultPrimaryTileset; } diff --git a/src/project.cpp b/src/project.cpp index 66e5aba8f..588d0ee44 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -444,10 +444,6 @@ bool Project::readMapLayouts() { "blockdata_filepath", }; bool useCustomBorderSize = projectConfig.getUseCustomBorderSize(); - if (useCustomBorderSize) { - requiredFields.append("border_width"); - requiredFields.append("border_height"); - } for (int i = 0; i < layouts.size(); i++) { QJsonObject layoutObj = layouts[i].toObject(); if (layoutObj.isEmpty()) diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index 3afc77d1f..45f795791 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -37,6 +37,13 @@ void ProjectSettingsEditor::connectSignals() { connect(ui->button_ImportDefaultPrefabs, &QAbstractButton::clicked, this, &ProjectSettingsEditor::importDefaultPrefabsClicked); connect(ui->comboBox_BaseGameVersion, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::promptRestoreDefaults); connect(ui->comboBox_AttributesSize, &QComboBox::currentTextChanged, this, &ProjectSettingsEditor::updateAttributeLimits); + connect(ui->checkBox_EnableCustomBorderSize, &QCheckBox::stateChanged, [this](int state) { + bool customSize = (state == Qt::Checked); + // When switching between the spin boxes or line edit for border metatiles we set + // the newly-shown UI using the values from the hidden UI. + this->setBorderMetatileIds(customSize, this->getBorderMetatileIds(!customSize)); + this->setBorderMetatilesUi(customSize); + }); // Record that there are unsaved changes if any of the settings are modified for (auto combo : ui->centralwidget->findChildren()) @@ -69,9 +76,49 @@ void ProjectSettingsEditor::initUi() { static const QRegularExpression expression(QString("^(%1,)*%1$").arg(regex_Hex)); // Comma-separated list of hex values QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression); ui->lineEdit_BorderMetatiles->setValidator(validator); - + this->setBorderMetatilesUi(projectConfig.getUseCustomBorderSize()); + + int maxMetatileId = Project::getNumMetatilesTotal() - 1; + ui->spinBox_FillMetatile->setMaximum(maxMetatileId); + ui->spinBox_BorderMetatile1->setMaximum(maxMetatileId); + ui->spinBox_BorderMetatile2->setMaximum(maxMetatileId); + ui->spinBox_BorderMetatile3->setMaximum(maxMetatileId); + ui->spinBox_BorderMetatile4->setMaximum(maxMetatileId); ui->spinBox_Elevation->setMaximum(15); - ui->spinBox_FillMetatile->setMaximum(Project::getNumMetatilesTotal() - 1); +} + +void ProjectSettingsEditor::setBorderMetatilesUi(bool customSize) { + ui->widget_DefaultSizeBorderMetatiles->setVisible(!customSize); + ui->widget_CustomSizeBorderMetatiles->setVisible(customSize); +} + +void ProjectSettingsEditor::setBorderMetatileIds(bool customSize, QList metatileIds) { + if (customSize) { + ui->lineEdit_BorderMetatiles->setText(Metatile::getMetatileIdStringList(metatileIds)); + } else { + ui->spinBox_BorderMetatile1->setValue(metatileIds.value(0, 0x0)); + ui->spinBox_BorderMetatile2->setValue(metatileIds.value(1, 0x0)); + ui->spinBox_BorderMetatile3->setValue(metatileIds.value(2, 0x0)); + ui->spinBox_BorderMetatile4->setValue(metatileIds.value(3, 0x0)); + } +} + +QList ProjectSettingsEditor::getBorderMetatileIds(bool customSize) { + QList metatileIds; + if (customSize) { + // Custom border size, read metatiles from line edit + for (auto s : ui->lineEdit_BorderMetatiles->text().split(",")) { + uint16_t metatileId = s.toUInt(nullptr, 0); + metatileIds.append(qMin(metatileId, static_cast(Project::getNumMetatilesTotal() - 1))); + } + } else { + // Default border size, read metatiles from spin boxes + metatileIds.append(ui->spinBox_BorderMetatile1->value()); + metatileIds.append(ui->spinBox_BorderMetatile2->value()); + metatileIds.append(ui->spinBox_BorderMetatile3->value()); + metatileIds.append(ui->spinBox_BorderMetatile4->value()); + } + return metatileIds; } void ProjectSettingsEditor::updateAttributeLimits(const QString &attrSize) { @@ -186,8 +233,12 @@ void ProjectSettingsEditor::refresh() { ui->spinBox_LayerTypeMask->setValue(projectConfig.getMetatileLayerTypeMask()); ui->spinBox_TerrainTypeMask->setValue(projectConfig.getMetatileTerrainTypeMask()); + // Set (and sync) border metatile IDs + auto metatileIds = projectConfig.getNewMapBorderMetatileIds(); + this->setBorderMetatileIds(false, metatileIds); + this->setBorderMetatileIds(true, metatileIds); + // Set line edit texts - ui->lineEdit_BorderMetatiles->setText(projectConfig.getNewMapBorderMetatileIdsString()); ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath()); for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren()) lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), true)); @@ -230,14 +281,7 @@ void ProjectSettingsEditor::save() { projectConfig.setPrefabFilepath(ui->lineEdit_PrefabsPath->text()); for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren()) projectConfig.setFilePath(lineEdit->objectName(), lineEdit->text()); - - // Parse and save border metatile list - QList metatileIds; - for (auto s : ui->lineEdit_BorderMetatiles->text().split(",")) { - uint16_t metatileId = s.toUInt(nullptr, 0); - metatileIds.append(qMin(metatileId, static_cast(Project::getNumMetatilesTotal() - 1))); - } - projectConfig.setNewMapBorderMetatileIds(metatileIds); + projectConfig.setNewMapBorderMetatileIds(this->getBorderMetatileIds(ui->checkBox_EnableCustomBorderSize->isChecked())); projectConfig.setSaveDisabled(false); projectConfig.save(); From 4f459f5a06a0fa8e6243bc6d85500d1d16e0ab9b Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 18 Aug 2023 18:46:25 -0400 Subject: [PATCH 33/34] Improve speed of setMetatileTiles --- CHANGELOG.md | 1 + include/mainwindow.h | 2 +- include/ui/tileseteditor.h | 2 +- src/scriptapi/apimap.cpp | 31 +++++++++++++++---------------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d61cd0acd..5083eb0d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix default object sprites retaining dimensions and transparency of the previous sprite. - Fix connections not being deleted when the map name text box is cleared. - Fix the map border not updating when a tileset is changed. +- Improve the poor speed of the API functions `setMetatileTile` and `setMetatileTiles`. - Stop the Tileset Editor from scrolling to the initially selected metatile when saving. - Fix the selection outline sticking in single-tile mode on the Prefab tab. diff --git a/include/mainwindow.h b/include/mainwindow.h index 87ea30aa5..f68fc2c6c 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -333,7 +333,7 @@ private slots: MapSortOrder mapSortOrder; - bool needsFullRedraw = false; + bool tilesetNeedsRedraw = false; bool setMap(QString, bool scrollTreeView = false); void redrawMapScene(); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 09a828c3a..06aa2168c 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -52,11 +52,11 @@ class TilesetEditor : public QMainWindow public slots: void applyUserShortcuts(); + void onSelectedMetatileChanged(uint16_t); private slots: void onHoveredMetatileChanged(uint16_t); void onHoveredMetatileCleared(); - void onSelectedMetatileChanged(uint16_t); void onHoveredTileChanged(uint16_t); void onHoveredTileCleared(); void onSelectedTilesChanged(); diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index fde049dbc..21f38a51f 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -5,7 +5,7 @@ #include "config.h" #include "imageproviders.h" -// TODO: "needsFullRedraw" is used when redrawing the map after +// TODO: "tilesetNeedsRedraw" is used when redrawing the map after // changing a metatile's tiles via script. It is unnecessarily // resource intensive. The map metatiles that need to be updated are // not marked as changed, so they will not be redrawn if the cache @@ -16,13 +16,22 @@ void MainWindow::tryRedrawMapArea(bool forceRedraw) { if (!forceRedraw) return; - if (this->needsFullRedraw) { + if (this->tilesetNeedsRedraw) { + // Refresh anything that can display metatiles this->editor->map_item->draw(true); this->editor->collision_item->draw(true); this->editor->selected_border_metatiles_item->draw(); this->editor->updateMapBorder(); this->editor->updateMapConnections(); - this->needsFullRedraw = false; + if (this->tilesetEditor) + this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label); + if (this->editor->metatile_selector_item) + this->editor->metatile_selector_item->draw(); + if (this->editor->selected_border_metatiles_item) + this->editor->selected_border_metatiles_item->draw(); + if (this->editor->current_metatile_selection_item) + this->editor->current_metatile_selection_item->draw(); + this->tilesetNeedsRedraw = false; } else { this->editor->map_item->draw(); this->editor->collision_item->draw(); @@ -569,16 +578,6 @@ void MainWindow::saveMetatilesByMetatileId(int metatileId) { Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); if (this->editor->project && tileset) this->editor->project->saveTilesetMetatiles(tileset); - - // Refresh anything that can display metatiles (except the actual map view) - if (this->tilesetEditor) - this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label); - if (this->editor->metatile_selector_item) - this->editor->metatile_selector_item->draw(); - if (this->editor->selected_border_metatiles_item) - this->editor->selected_border_metatiles_item->draw(); - if (this->editor->current_metatile_selection_item) - this->editor->current_metatile_selection_item->draw(); } void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) { @@ -588,7 +587,7 @@ void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) { // If the Tileset Editor is currently displaying the updated metatile, refresh it if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatileId() == metatileId) - this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label); + this->tilesetEditor->onSelectedMetatileChanged(metatileId); } Metatile * MainWindow::getMetatile(int metatileId) { @@ -735,7 +734,7 @@ void MainWindow::setMetatileTiles(int metatileId, QJSValue tilesObj, int tileSta metatile->tiles[tileStart] = Tile(); this->saveMetatilesByMetatileId(metatileId); - this->needsFullRedraw = true; + this->tilesetNeedsRedraw = true; this->tryRedrawMapArea(forceRedraw); } @@ -751,7 +750,7 @@ void MainWindow::setMetatileTiles(int metatileId, int tileId, bool xflip, bool y metatile->tiles[i] = tile; this->saveMetatilesByMetatileId(metatileId); - this->needsFullRedraw = true; + this->tilesetNeedsRedraw = true; this->tryRedrawMapArea(forceRedraw); } From 31c5ad6b95ae1f8d9c53d33cef760cb4b9d38714 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 19 Sep 2023 19:08:17 -0400 Subject: [PATCH 34/34] Remove duplicate empty script labels in dropdown --- CHANGELOG.md | 1 + src/core/map.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5083eb0d4..54d292e5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix the map border not updating when a tileset is changed. - Improve the poor speed of the API functions `setMetatileTile` and `setMetatileTiles`. - Stop the Tileset Editor from scrolling to the initially selected metatile when saving. +- Fix `0x0`/`NULL` appearing more than once in the scripts dropdown. - Fix the selection outline sticking in single-tile mode on the Prefab tab. ## [5.1.1] - 2023-02-20 diff --git a/src/core/map.cpp b/src/core/map.cpp index 5114b01d4..176d4d2f5 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -479,9 +479,9 @@ QStringList Map::eventScriptLabels(Event::Group group) const { } scriptLabels.removeAll(""); - scriptLabels.removeDuplicates(); scriptLabels.prepend("0x0"); scriptLabels.prepend("NULL"); + scriptLabels.removeDuplicates(); return scriptLabels; }