From 72ae9dfc013813b90ba79d6079e5b27f77802f7d Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 14 Feb 2023 11:50:14 -0500 Subject: [PATCH 01/10] Fix regression in metatile label saving --- src/project.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project.cpp b/src/project.cpp index 095e540c..a16c5038 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1509,7 +1509,7 @@ bool Project::readTilesetMetatileLabels() { for (QString label : this->tilesetLabelsOrdered) { QString tilesetName = QString(label).replace("gTileset_", ""); for (QString key : labels.keys()) { - if (key.contains(QString("METATILE_") + tilesetName)) { + if (key.contains(QString("METATILE_") + tilesetName + "_")) { metatileLabelsMap[label][key] = labels[key]; } } From dbd6afb0c3983af74f23e07fb3690d003aa54a62 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 14 Feb 2023 14:10:05 -0500 Subject: [PATCH 02/10] Move metatile labels to tilesets --- include/core/metatile.h | 2 -- include/core/tileset.h | 4 +++ include/ui/tileseteditor.h | 3 +- src/core/tileset.cpp | 43 +++++++++++++++++++++++++++- src/editor.cpp | 11 ++++---- src/project.cpp | 33 +++++++--------------- src/scriptapi/apimap.cpp | 34 +++++++++++----------- src/ui/tileseteditor.cpp | 58 +++++++++++++++++++++++++------------- 8 files changed, 118 insertions(+), 70 deletions(-) diff --git a/include/core/metatile.h b/include/core/metatile.h index f606dcdb..49fb5c7b 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -70,7 +70,6 @@ public: uint32_t encounterType; uint32_t layerType; uint32_t unusedAttributes; - QString label; uint32_t getAttributes(); void setAttributes(uint32_t data); @@ -121,7 +120,6 @@ inline bool operator==(const Metatile &a, const Metatile &b) { a.encounterType == b.encounterType && a.terrainType == b.terrainType && a.unusedAttributes == b.unusedAttributes && - a.label == b.label && a.tiles == b.tiles; } diff --git a/include/core/tileset.h b/include/core/tileset.h index 2c6d658e..c25cbc62 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -5,6 +5,7 @@ #include "metatile.h" #include "tile.h" #include +#include class Tileset { @@ -28,12 +29,15 @@ public: QList tiles; QList metatiles; + QHash metatileLabels; QList> palettes; QList> palettePreviews; static Tileset* getMetatileTileset(int, Tileset*, Tileset*); static Tileset* getTileTileset(int, Tileset*, Tileset*); static Metatile* getMetatile(int, Tileset*, Tileset*); + static QString getMetatileLabel(int, Tileset *, Tileset *, bool * isAlternateLabel = nullptr); + static bool setMetatileLabel(int, QString, Tileset *, Tileset *); static QList> getBlockPalettes(Tileset*, Tileset*, bool useTruePalettes = false); static QList getPalette(int, Tileset*, Tileset*, bool useTruePalettes = false); static bool metatileIsValid(uint16_t metatileId, Tileset *, Tileset *); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index fcdd3bed..5501c8f8 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -127,7 +127,7 @@ private: void importTilesetTiles(Tileset*, bool); void importTilesetMetatiles(Tileset*, bool); void refresh(); - void saveMetatileLabel(); + void commitMetatileLabel(); void closeEvent(QCloseEvent*); void countMetatileUsage(); void countTileUsage(); @@ -146,6 +146,7 @@ private: Map *map = nullptr; Metatile *metatile = nullptr; Metatile *copiedMetatile = nullptr; + QString copiedMetatileLabel; int paletteId; bool tileXFlip; bool tileYFlip; diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index e3d00d8c..33ca9272 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -20,6 +20,7 @@ Tileset::Tileset(const Tileset &other) tilesImagePath(other.tilesImagePath), tilesImage(other.tilesImage.copy()), palettePaths(other.palettePaths), + metatileLabels(other.metatileLabels), palettes(other.palettes), palettePreviews(other.palettePreviews) { @@ -44,6 +45,7 @@ Tileset &Tileset::operator=(const Tileset &other) { tilesImagePath = other.tilesImagePath; tilesImage = other.tilesImage.copy(); palettePaths = other.palettePaths; + metatileLabels = other.metatileLabels; palettes = other.palettes; palettePreviews = other.palettePreviews; @@ -82,13 +84,52 @@ Tileset* Tileset::getMetatileTileset(int metatileId, Tileset *primaryTileset, Ti Metatile* Tileset::getMetatile(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { Tileset *tileset = Tileset::getMetatileTileset(metatileId, primaryTileset, secondaryTileset); - int index = Metatile::getIndexInTileset(metatileId); if (!tileset) { return nullptr; } + int index = Metatile::getIndexInTileset(metatileId); return tileset->metatiles.value(index, nullptr); } +// Metatile labels are stored per-tileset. When looking for a metatile label, first search in the tileset +// that the metatile belongs to. If one isn't found, search in the other tileset. Labels coming from the +// tileset that the metatile does not belong to cannot be edited via Porymap. +QString Tileset::getMetatileLabel(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset, bool * isAlternateLabel) { + Tileset *mainTileset = nullptr; + Tileset *backupTileset = nullptr; + if (isAlternateLabel) *isAlternateLabel = false; + if (metatileId < Project::getNumMetatilesPrimary()) { + mainTileset = primaryTileset; + backupTileset = secondaryTileset; + } else if (metatileId < Project::getNumMetatilesTotal()) { + mainTileset = secondaryTileset; + backupTileset = primaryTileset; + } + + if (mainTileset && mainTileset->metatileLabels.contains(metatileId)) { + return mainTileset->metatileLabels.value(metatileId); + } else if (backupTileset && backupTileset->metatileLabels.contains(metatileId)) { + if (isAlternateLabel) *isAlternateLabel = true; + return backupTileset->metatileLabels.value(metatileId); + } + return QString(); +} + +bool Tileset::setMetatileLabel(int metatileId, QString label, Tileset *primaryTileset, Tileset *secondaryTileset) { + Tileset *tileset = Tileset::getMetatileTileset(metatileId, primaryTileset, secondaryTileset); + if (!tileset) + return false; + + static const QRegularExpression expression("[_A-Za-z0-9]*$"); + QRegularExpressionValidator validator(expression); + int pos = 0; + if (validator.validate(label, pos) != QValidator::Acceptable) + return false; + + tileset->metatileLabels[metatileId] = label; + return true; +} + bool Tileset::metatileIsValid(uint16_t metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { if (metatileId >= Project::getNumMetatilesTotal()) return false; diff --git a/src/editor.cpp b/src/editor.cpp index 3f5b2e1a..c06f2589 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -932,14 +932,13 @@ 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); - if (metatile) { - if (metatile->label.size()) - message += QString(" \"%1\"").arg(metatile->label); - if (metatile->behavior) // Skip MB_NORMAL - message += QString(", Behavior: %1").arg(this->project->metatileBehaviorMapInverse.value(metatile->behavior, QString::number(metatile->behavior))); - } + if (label.size()) + message += QString(" \"%1\"").arg(label); + if (metatile && metatile->behavior) // Skip MB_NORMAL + message += QString(", Behavior: %1").arg(this->project->metatileBehaviorMapInverse.value(metatile->behavior, QString::number(metatile->behavior))); return message; } diff --git a/src/project.cpp b/src/project.cpp index a16c5038..23fce463 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -913,21 +913,15 @@ void Project::saveTilesetMetatileLabels(Tileset *primaryTileset, Tileset *second } // Add the new labels. - for (int i = 0; i < primaryTileset->metatiles.size(); i++) { - Metatile *metatile = primaryTileset->metatiles.at(i); - if (metatile->label.size() != 0) { - QString defineName = QString("%1%2").arg(primaryPrefix, metatile->label); - defines.insert(defineName, i); - definesFileModified = true; - } + for (int metatileId : primaryTileset->metatileLabels.keys()) { + QString defineName = QString("%1%2").arg(primaryPrefix, primaryTileset->metatileLabels.value(metatileId)); + defines.insert(defineName, metatileId); + definesFileModified = true; } - for (int i = 0; i < secondaryTileset->metatiles.size(); i++) { - Metatile *metatile = secondaryTileset->metatiles.at(i); - if (metatile->label.size() != 0) { - QString defineName = QString("%1%2").arg(secondaryPrefix, metatile->label); - defines.insert(defineName, i + Project::num_tiles_primary); - definesFileModified = true; - } + for (int metatileId : secondaryTileset->metatileLabels.keys()) { + QString defineName = QString("%1%2").arg(secondaryPrefix, secondaryTileset->metatileLabels.value(metatileId)); + defines.insert(defineName, metatileId); + definesFileModified = true; } if (!definesFileModified) { @@ -1521,17 +1515,10 @@ bool Project::readTilesetMetatileLabels() { void Project::loadTilesetMetatileLabels(Tileset* tileset) { QString tilesetPrefix = QString("METATILE_%1_").arg(QString(tileset->name).replace("gTileset_", "")); + // Reverse map for faster lookup by metatile id for (QString labelName : metatileLabelsMap[tileset->name].keys()) { int metatileId = metatileLabelsMap[tileset->name][labelName]; - // subtract Project::num_tiles_primary from secondary metatiles - int offset = tileset->is_secondary ? Project::num_tiles_primary : 0; - Metatile *metatile = Tileset::getMetatile(metatileId - offset, tileset, nullptr); - if (metatile) { - metatile->label = labelName.replace(tilesetPrefix, ""); - } else { - QString hexString = QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper(); - logError(QString("Metatile 0x%1 (%2) cannot be found in tileset '%3'").arg(hexString, labelName, tileset->name)); - } + tileset->metatileLabels[metatileId] = labelName.replace(tilesetPrefix, ""); } } diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index 046474de..4baa83f9 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -598,32 +598,30 @@ Metatile * MainWindow::getMetatile(int metatileId) { } QString MainWindow::getMetatileLabel(int metatileId) { - Metatile * metatile = this->getMetatile(metatileId); - if (!metatile || metatile->label.size() == 0) + if (!this->editor || !this->editor->map || !this->editor->map->layout) return QString(); - return metatile->label; + return Tileset::getMetatileLabel(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); } void MainWindow::setMetatileLabel(int metatileId, QString label) { - Metatile * metatile = this->getMetatile(metatileId); - if (!metatile) + if (!this->editor || !this->editor->map || !this->editor->map->layout) return; - static const QRegularExpression expression("[_A-Za-z0-9]*$"); - QRegularExpressionValidator validator(expression); - int pos = 0; - if (validator.validate(label, pos) != QValidator::Acceptable) { - logError(QString("Invalid metatile label %1").arg(label)); - return; - } - - if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatileId() == metatileId) { + // If the Tileset Editor is opened on this metatile we need to update the text box + if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatileId() == metatileId){ this->tilesetEditor->setMetatileLabel(label); - } else if (metatile->label != label) { - metatile->label = label; - if (this->editor->project) - this->editor->project->saveTilesetMetatileLabels(this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + return; } + + if (!Tileset::setMetatileLabel(metatileId, label, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary)) { + logError("Failed to set metatile label. Must be a valid metatile id and a label containing only letters, numbers, and underscores."); + return; + } + + // The user may not have the Tileset Editor open. This forcefully saves the change for them. + // If they do have the Tileset Editor open, this has the unintended side effect of saving other unsaved label changes. + if (this->editor->project) + this->editor->project->saveTilesetMetatileLabels(this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); } int MainWindow::getMetatileLayerType(int metatileId) { diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 7f5d7695..a5352fd3 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -343,13 +343,11 @@ void TilesetEditor::drawSelectedTiles() { } void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) { - Metatile *metatile = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset); - QString message; + QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset); QString hexString = QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper(); - if (metatile && metatile->label.size() != 0) { - message = QString("Metatile: 0x%1 \"%2\"").arg(hexString, metatile->label); - } else { - message = QString("Metatile: 0x%1").arg(hexString); + QString message = QString("Metatile: 0x%1").arg(hexString); + if (label.size() != 0) { + message += QString(" \"%1\"").arg(label); } this->ui->statusbar->showMessage(message); } @@ -381,7 +379,12 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->metatileLayersItem->setMetatile(metatile); this->metatileLayersItem->draw(); this->ui->graphicsView_metatileLayers->setFixedSize(this->metatileLayersItem->pixmap().width() + 2, this->metatileLayersItem->pixmap().height() + 2); - this->ui->lineEdit_metatileLabel->setText(this->metatile->label); + + bool isAlternateLabel = false; + QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset, &isAlternateLabel); + this->ui->lineEdit_metatileLabel->setText(label); + this->ui->lineEdit_metatileLabel->setReadOnly(isAlternateLabel); + setComboValue(this->ui->comboBox_metatileBehaviors, this->metatile->behavior); setComboValue(this->ui->comboBox_layerType, this->metatile->layerType); setComboValue(this->ui->comboBox_encounterType, this->metatile->encounterType); @@ -532,24 +535,31 @@ void TilesetEditor::on_comboBox_metatileBehaviors_currentTextChanged(const QStri void TilesetEditor::setMetatileLabel(QString label) { + if (this->ui->lineEdit_metatileLabel->isReadOnly()) + return; this->ui->lineEdit_metatileLabel->setText(label); - saveMetatileLabel(); + commitMetatileLabel(); } void TilesetEditor::on_lineEdit_metatileLabel_editingFinished() { - saveMetatileLabel(); + commitMetatileLabel(); } -void TilesetEditor::saveMetatileLabel() +void TilesetEditor::commitMetatileLabel() { + // TODO: Reimplement edit history for labels + // Only commit if the field has changed. - if (this->metatile && this->metatile->label != this->ui->lineEdit_metatileLabel->text()) { - Metatile *prevMetatile = new Metatile(*this->metatile); - this->metatile->label = this->ui->lineEdit_metatileLabel->text(); - MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), + uint16_t metatileId = this->getSelectedMetatileId(); + QString currentLabel = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset); + QString newLabel = this->ui->lineEdit_metatileLabel->text(); + if (currentLabel != newLabel) { + //Metatile *prevMetatile = new Metatile(*this->metatile); + Tileset::setMetatileLabel(metatileId, newLabel, this->primaryTileset, this->secondaryTileset); + /*MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), prevMetatile, new Metatile(*this->metatile)); - metatileHistory.push(commit); + metatileHistory.push(commit);*/ this->hasUnsavedChanges = true; } } @@ -597,8 +607,6 @@ void TilesetEditor::on_actionSave_Tileset_triggered() // when the tilesetsSaved signal is sent, it will be reset to the current map metatile uint16_t reselectMetatileID = this->metatileSelector->getSelectedMetatileId(); - saveMetatileLabel(); - this->project->saveTilesets(this->primaryTileset, this->secondaryTileset); emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name); this->metatileSelector->select(reselectMetatileID); @@ -882,6 +890,7 @@ void TilesetEditor::on_actionCut_triggered() Metatile * empty = new Metatile(projectConfig.getNumTilesInMetatile()); this->copyMetatile(true); this->pasteMetatile(empty); + this->setMetatileLabel(""); delete empty; } @@ -893,17 +902,27 @@ void TilesetEditor::on_actionCopy_triggered() void TilesetEditor::on_actionPaste_triggered() { this->pasteMetatile(this->copiedMetatile); + this->setMetatileLabel(this->copiedMetatileLabel); } void TilesetEditor::copyMetatile(bool cut) { - Metatile * toCopy = Tileset::getMetatile(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset); + uint16_t metatileId = this->getSelectedMetatileId(); + Metatile * toCopy = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset); if (!toCopy) return; if (!this->copiedMetatile) this->copiedMetatile = new Metatile(*toCopy); else *this->copiedMetatile = *toCopy; - if (!cut) this->copiedMetatile->label = ""; // Don't copy the label unless it's a cut, these should be unique to each metatile + + // Don't try to copy the label unless it's a cut, these should be unique to each metatile + this->copiedMetatileLabel = ""; + if (cut) { + bool isAlternateLabel = false; + QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset, &isAlternateLabel); + if (!isAlternateLabel) + this->copiedMetatileLabel = label; + } } void TilesetEditor::pasteMetatile(const Metatile * toPaste) @@ -1146,6 +1165,7 @@ void TilesetEditor::countTileUsage() { } void TilesetEditor::on_copyButton_metatileLabel_clicked() { + // TODO: Handle alternate labels QString label = this->ui->lineEdit_metatileLabel->text(); if (label.isEmpty()) return; Tileset * tileset = Tileset::getMetatileTileset(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset); From 16e5e9fad8043d3deb826cdf9c9970a34bf04491 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 14 Feb 2023 15:28:18 -0500 Subject: [PATCH 03/10] Update metatile label copy button --- include/core/tileset.h | 5 ++++- src/core/tileset.cpp | 39 ++++++++++++++++++++++++++++----------- src/project.cpp | 16 ++++++++-------- src/ui/tileseteditor.cpp | 17 ++++++++--------- 4 files changed, 48 insertions(+), 29 deletions(-) diff --git a/include/core/tileset.h b/include/core/tileset.h index c25cbc62..0b273e83 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -36,8 +36,11 @@ public: static Tileset* getMetatileTileset(int, Tileset*, Tileset*); static Tileset* getTileTileset(int, Tileset*, Tileset*); static Metatile* getMetatile(int, Tileset*, Tileset*); - static QString getMetatileLabel(int, Tileset *, Tileset *, bool * isAlternateLabel = nullptr); + static Tileset* getMetatileLabelTileset(int, Tileset*, Tileset*, bool * isShared = nullptr); + static QString getMetatileLabel(int, Tileset *, Tileset *, bool * isShared = nullptr); static bool setMetatileLabel(int, QString, Tileset *, Tileset *); + QString getMetatileLabelPrefix(); + static QString getMetatileLabelPrefix(const QString &name); static QList> getBlockPalettes(Tileset*, Tileset*, bool useTruePalettes = false); static QList getPalette(int, Tileset*, Tileset*, bool useTruePalettes = false); static bool metatileIsValid(uint16_t metatileId, Tileset *, Tileset *); diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index 33ca9272..593991e3 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -93,26 +93,33 @@ Metatile* Tileset::getMetatile(int metatileId, Tileset *primaryTileset, Tileset // Metatile labels are stored per-tileset. When looking for a metatile label, first search in the tileset // that the metatile belongs to. If one isn't found, search in the other tileset. Labels coming from the -// tileset that the metatile does not belong to cannot be edited via Porymap. -QString Tileset::getMetatileLabel(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset, bool * isAlternateLabel) { +// tileset that the metatile does not belong to are shared and cannot be edited via Porymap. +Tileset* Tileset::getMetatileLabelTileset(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset, bool * isShared) { Tileset *mainTileset = nullptr; - Tileset *backupTileset = nullptr; - if (isAlternateLabel) *isAlternateLabel = false; + Tileset *alternateTileset = nullptr; + if (isShared) *isShared = false; if (metatileId < Project::getNumMetatilesPrimary()) { mainTileset = primaryTileset; - backupTileset = secondaryTileset; + alternateTileset = secondaryTileset; } else if (metatileId < Project::getNumMetatilesTotal()) { mainTileset = secondaryTileset; - backupTileset = primaryTileset; + alternateTileset = primaryTileset; } if (mainTileset && mainTileset->metatileLabels.contains(metatileId)) { - return mainTileset->metatileLabels.value(metatileId); - } else if (backupTileset && backupTileset->metatileLabels.contains(metatileId)) { - if (isAlternateLabel) *isAlternateLabel = true; - return backupTileset->metatileLabels.value(metatileId); + return mainTileset; + } else if (alternateTileset && alternateTileset->metatileLabels.contains(metatileId)) { + if (isShared) *isShared = true; + return alternateTileset; } - return QString(); + return nullptr; +} + +QString Tileset::getMetatileLabel(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset, bool * isShared) { + Tileset * tileset = Tileset::getMetatileLabelTileset(metatileId, primaryTileset, secondaryTileset, isShared); + if (!tileset) + return QString(); + return tileset->metatileLabels.value(metatileId); } bool Tileset::setMetatileLabel(int metatileId, QString label, Tileset *primaryTileset, Tileset *secondaryTileset) { @@ -130,6 +137,16 @@ bool Tileset::setMetatileLabel(int metatileId, QString label, Tileset *primaryTi return true; } +QString Tileset::getMetatileLabelPrefix() +{ + return Tileset::getMetatileLabelPrefix(this->name); +} + +QString Tileset::getMetatileLabelPrefix(const QString &name) +{ + return QString("METATILE_%1_").arg(QString(name).replace("gTileset_", "")); +} + bool Tileset::metatileIsValid(uint16_t metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { if (metatileId >= Project::getNumMetatilesTotal()) return false; diff --git a/src/project.cpp b/src/project.cpp index 23fce463..1ab726da 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -891,8 +891,8 @@ void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { } void Project::saveTilesetMetatileLabels(Tileset *primaryTileset, Tileset *secondaryTileset) { - QString primaryPrefix = QString("METATILE_%1_").arg(QString(primaryTileset->name).replace("gTileset_", "")); - QString secondaryPrefix = QString("METATILE_%1_").arg(QString(secondaryTileset->name).replace("gTileset_", "")); + QString primaryPrefix = primaryTileset->getMetatileLabelPrefix(); + QString secondaryPrefix = secondaryTileset->getMetatileLabelPrefix(); QMap defines; bool definesFileModified = false; @@ -1500,11 +1500,11 @@ bool Project::readTilesetMetatileLabels() { QMap labels = parser.readCDefines(metatileLabelsFilename, QStringList() << "METATILE_"); - for (QString label : this->tilesetLabelsOrdered) { - QString tilesetName = QString(label).replace("gTileset_", ""); + for (QString tilesetLabel : this->tilesetLabelsOrdered) { + QString metatileLabelPrefix = Tileset::getMetatileLabelPrefix(tilesetLabel); for (QString key : labels.keys()) { - if (key.contains(QString("METATILE_") + tilesetName + "_")) { - metatileLabelsMap[label][key] = labels[key]; + if (key.startsWith(metatileLabelPrefix)) { + metatileLabelsMap[tilesetLabel][key] = labels[key]; } } } @@ -1513,12 +1513,12 @@ bool Project::readTilesetMetatileLabels() { } void Project::loadTilesetMetatileLabels(Tileset* tileset) { - QString tilesetPrefix = QString("METATILE_%1_").arg(QString(tileset->name).replace("gTileset_", "")); + QString metatileLabelPrefix = tileset->getMetatileLabelPrefix(); // Reverse map for faster lookup by metatile id for (QString labelName : metatileLabelsMap[tileset->name].keys()) { int metatileId = metatileLabelsMap[tileset->name][labelName]; - tileset->metatileLabels[metatileId] = labelName.replace(tilesetPrefix, ""); + tileset->metatileLabels[metatileId] = labelName.replace(metatileLabelPrefix, ""); } } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index a5352fd3..fcfe4266 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -380,10 +380,10 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->metatileLayersItem->draw(); this->ui->graphicsView_metatileLayers->setFixedSize(this->metatileLayersItem->pixmap().width() + 2, this->metatileLayersItem->pixmap().height() + 2); - bool isAlternateLabel = false; - QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset, &isAlternateLabel); + bool isShared = false; + QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset, &isShared); this->ui->lineEdit_metatileLabel->setText(label); - this->ui->lineEdit_metatileLabel->setReadOnly(isAlternateLabel); + this->ui->lineEdit_metatileLabel->setReadOnly(isShared); setComboValue(this->ui->comboBox_metatileBehaviors, this->metatile->behavior); setComboValue(this->ui->comboBox_layerType, this->metatile->layerType); @@ -918,9 +918,9 @@ void TilesetEditor::copyMetatile(bool cut) { // Don't try to copy the label unless it's a cut, these should be unique to each metatile this->copiedMetatileLabel = ""; if (cut) { - bool isAlternateLabel = false; - QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset, &isAlternateLabel); - if (!isAlternateLabel) + bool isShared = false; + QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset, &isShared); + if (!isShared) this->copiedMetatileLabel = label; } } @@ -1165,12 +1165,11 @@ void TilesetEditor::countTileUsage() { } void TilesetEditor::on_copyButton_metatileLabel_clicked() { - // TODO: Handle alternate labels QString label = this->ui->lineEdit_metatileLabel->text(); if (label.isEmpty()) return; - Tileset * tileset = Tileset::getMetatileTileset(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset); + Tileset * tileset = Tileset::getMetatileLabelTileset(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset); if (tileset) - label.prepend("METATILE_" + QString(tileset->name).replace("gTileset_", "") + "_"); + label.prepend(tileset->getMetatileLabelPrefix()); QGuiApplication::clipboard()->setText(label); QToolTip::showText(this->ui->copyButton_metatileLabel->mapToGlobal(QPoint(0, 0)), "Copied!"); } From 44dba9edc5dd36663ee5485e4d741e4a2c778fb3 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 14 Feb 2023 22:44:13 -0500 Subject: [PATCH 04/10] Set shared metatile labels as placeholders --- include/core/tileset.h | 10 ++++++++-- src/core/tileset.cpp | 33 ++++++++++++++++++++++++++------- src/project.cpp | 8 ++++++-- src/ui/tileseteditor.cpp | 27 ++++++++++----------------- 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/include/core/tileset.h b/include/core/tileset.h index 0b273e83..198cbca8 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -7,6 +7,11 @@ #include #include +struct MetatileLabelPair { + QString normal; + QString shared; +}; + class Tileset { public: @@ -36,8 +41,9 @@ public: static Tileset* getMetatileTileset(int, Tileset*, Tileset*); static Tileset* getTileTileset(int, Tileset*, Tileset*); static Metatile* getMetatile(int, Tileset*, Tileset*); - static Tileset* getMetatileLabelTileset(int, Tileset*, Tileset*, bool * isShared = nullptr); - static QString getMetatileLabel(int, Tileset *, Tileset *, bool * isShared = nullptr); + static Tileset* getMetatileLabelTileset(int, Tileset*, Tileset*); + static QString getMetatileLabel(int, Tileset *, Tileset *); + static MetatileLabelPair getMetatileLabelPair(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset); static bool setMetatileLabel(int, QString, Tileset *, Tileset *); QString getMetatileLabelPrefix(); static QString getMetatileLabelPrefix(const QString &name); diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index 593991e3..2130824f 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -94,10 +94,9 @@ Metatile* Tileset::getMetatile(int metatileId, Tileset *primaryTileset, Tileset // Metatile labels are stored per-tileset. When looking for a metatile label, first search in the tileset // that the metatile belongs to. If one isn't found, search in the other tileset. Labels coming from the // tileset that the metatile does not belong to are shared and cannot be edited via Porymap. -Tileset* Tileset::getMetatileLabelTileset(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset, bool * isShared) { +Tileset* Tileset::getMetatileLabelTileset(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { Tileset *mainTileset = nullptr; Tileset *alternateTileset = nullptr; - if (isShared) *isShared = false; if (metatileId < Project::getNumMetatilesPrimary()) { mainTileset = primaryTileset; alternateTileset = secondaryTileset; @@ -106,22 +105,42 @@ Tileset* Tileset::getMetatileLabelTileset(int metatileId, Tileset *primaryTilese alternateTileset = primaryTileset; } - if (mainTileset && mainTileset->metatileLabels.contains(metatileId)) { + if (mainTileset && !mainTileset->metatileLabels.value(metatileId).isEmpty()) { return mainTileset; - } else if (alternateTileset && alternateTileset->metatileLabels.contains(metatileId)) { - if (isShared) *isShared = true; + } else if (alternateTileset && !alternateTileset->metatileLabels.value(metatileId).isEmpty()) { return alternateTileset; } return nullptr; } -QString Tileset::getMetatileLabel(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset, bool * isShared) { - Tileset * tileset = Tileset::getMetatileLabelTileset(metatileId, primaryTileset, secondaryTileset, isShared); +// If the metatile has a label in the tileset it belongs to, return that label. +// If it doesn't, and the metatile has a label in the other tileset, return that label. +// Otherwise return an empty string. +QString Tileset::getMetatileLabel(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { + Tileset * tileset = Tileset::getMetatileLabelTileset(metatileId, primaryTileset, secondaryTileset); if (!tileset) return QString(); return tileset->metatileLabels.value(metatileId); } +// Return the pair of possible metatile labels for the specified metatile. +// "normal" is the label for the tileset to which the metatile belongs. +// "shared" is the label for the tileset to which the metatile does not belong. +MetatileLabelPair Tileset::getMetatileLabelPair(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { + MetatileLabelPair labels; + QString primaryMetatileLabel = primaryTileset ? primaryTileset->metatileLabels.value(metatileId) : ""; + QString secondaryMetatileLabel = secondaryTileset ? secondaryTileset->metatileLabels.value(metatileId) : ""; + + if (metatileId < Project::getNumMetatilesPrimary()) { + labels.normal = primaryMetatileLabel; + labels.shared = secondaryMetatileLabel; + } else if (metatileId < Project::getNumMetatilesTotal()) { + labels.normal = secondaryMetatileLabel; + labels.shared = primaryMetatileLabel; + } + return labels; +} + bool Tileset::setMetatileLabel(int metatileId, QString label, Tileset *primaryTileset, Tileset *secondaryTileset) { Tileset *tileset = Tileset::getMetatileTileset(metatileId, primaryTileset, secondaryTileset); if (!tileset) diff --git a/src/project.cpp b/src/project.cpp index 1ab726da..b0e3d43c 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -914,12 +914,16 @@ void Project::saveTilesetMetatileLabels(Tileset *primaryTileset, Tileset *second // Add the new labels. for (int metatileId : primaryTileset->metatileLabels.keys()) { - QString defineName = QString("%1%2").arg(primaryPrefix, primaryTileset->metatileLabels.value(metatileId)); + QString label = primaryTileset->metatileLabels.value(metatileId); + if (label.isEmpty()) continue; + QString defineName = QString("%1%2").arg(primaryPrefix, label); defines.insert(defineName, metatileId); definesFileModified = true; } for (int metatileId : secondaryTileset->metatileLabels.keys()) { - QString defineName = QString("%1%2").arg(secondaryPrefix, secondaryTileset->metatileLabels.value(metatileId)); + QString label = secondaryTileset->metatileLabels.value(metatileId); + if (label.isEmpty()) continue; + QString defineName = QString("%1%2").arg(secondaryPrefix, label); defines.insert(defineName, metatileId); definesFileModified = true; } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index fcfe4266..de2d93fc 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -380,10 +380,9 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->metatileLayersItem->draw(); this->ui->graphicsView_metatileLayers->setFixedSize(this->metatileLayersItem->pixmap().width() + 2, this->metatileLayersItem->pixmap().height() + 2); - bool isShared = false; - QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset, &isShared); - this->ui->lineEdit_metatileLabel->setText(label); - this->ui->lineEdit_metatileLabel->setReadOnly(isShared); + MetatileLabelPair labels = Tileset::getMetatileLabelPair(metatileId, this->primaryTileset, this->secondaryTileset); + this->ui->lineEdit_metatileLabel->setText(labels.normal); + this->ui->lineEdit_metatileLabel->setPlaceholderText(labels.shared); setComboValue(this->ui->comboBox_metatileBehaviors, this->metatile->behavior); setComboValue(this->ui->comboBox_layerType, this->metatile->layerType); @@ -535,8 +534,6 @@ void TilesetEditor::on_comboBox_metatileBehaviors_currentTextChanged(const QStri void TilesetEditor::setMetatileLabel(QString label) { - if (this->ui->lineEdit_metatileLabel->isReadOnly()) - return; this->ui->lineEdit_metatileLabel->setText(label); commitMetatileLabel(); } @@ -552,7 +549,7 @@ void TilesetEditor::commitMetatileLabel() // Only commit if the field has changed. uint16_t metatileId = this->getSelectedMetatileId(); - QString currentLabel = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset); + QString currentLabel = Tileset::getMetatileLabelPair(metatileId, this->primaryTileset, this->secondaryTileset).normal; QString newLabel = this->ui->lineEdit_metatileLabel->text(); if (currentLabel != newLabel) { //Metatile *prevMetatile = new Metatile(*this->metatile); @@ -915,14 +912,9 @@ void TilesetEditor::copyMetatile(bool cut) { else *this->copiedMetatile = *toCopy; - // Don't try to copy the label unless it's a cut, these should be unique to each metatile - this->copiedMetatileLabel = ""; - if (cut) { - bool isShared = false; - QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset, &isShared); - if (!isShared) - this->copiedMetatileLabel = label; - } + // Don't try to copy the label unless it's a cut, these should be unique to each metatile. + // Never copy the "shared" metatile label. + this->copiedMetatileLabel = cut ? Tileset::getMetatileLabelPair(metatileId, this->primaryTileset, this->secondaryTileset).normal : ""; } void TilesetEditor::pasteMetatile(const Metatile * toPaste) @@ -1165,9 +1157,10 @@ void TilesetEditor::countTileUsage() { } void TilesetEditor::on_copyButton_metatileLabel_clicked() { - QString label = this->ui->lineEdit_metatileLabel->text(); + uint16_t metatileId = this->getSelectedMetatileId(); + QString label = Tileset::getMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset); if (label.isEmpty()) return; - Tileset * tileset = Tileset::getMetatileLabelTileset(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset); + Tileset * tileset = Tileset::getMetatileLabelTileset(metatileId, this->primaryTileset, this->secondaryTileset); if (tileset) label.prepend(tileset->getMetatileLabelPrefix()); QGuiApplication::clipboard()->setText(label); From 6508fd10af643b07c961551c2972dd4212f891d1 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 15 Feb 2023 13:44:09 -0500 Subject: [PATCH 05/10] Reimplement metatile label edit history --- include/core/tileset.h | 3 +- include/ui/tileseteditor.h | 12 +++-- src/core/tileset.cpp | 30 +++++++------ src/scriptapi/apimap.cpp | 2 - src/ui/tileseteditor.cpp | 92 ++++++++++++++++++-------------------- 5 files changed, 72 insertions(+), 67 deletions(-) diff --git a/include/core/tileset.h b/include/core/tileset.h index 198cbca8..3f50f41b 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -8,7 +8,7 @@ #include struct MetatileLabelPair { - QString normal; + QString owned; QString shared; }; @@ -43,6 +43,7 @@ public: static Metatile* getMetatile(int, Tileset*, Tileset*); static Tileset* getMetatileLabelTileset(int, Tileset*, Tileset*); static QString getMetatileLabel(int, Tileset *, Tileset *); + static QString getOwnedMetatileLabel(int, Tileset *, Tileset *); static MetatileLabelPair getMetatileLabelPair(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset); static bool setMetatileLabel(int, QString, Tileset *, Tileset *); QString getMetatileLabelPrefix(); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 5501c8f8..b03964b5 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -16,10 +16,12 @@ class TilesetEditor; class MetatileHistoryItem { public: - MetatileHistoryItem(uint16_t metatileId, Metatile *prevMetatile, Metatile *newMetatile) { + MetatileHistoryItem(uint16_t metatileId, Metatile *prevMetatile, Metatile *newMetatile, QString prevLabel, QString newLabel) { this->metatileId = metatileId; this->prevMetatile = prevMetatile; this->newMetatile = newMetatile; + this->prevLabel = prevLabel; + this->newLabel = newLabel; } ~MetatileHistoryItem() { delete this->prevMetatile; @@ -28,6 +30,8 @@ public: uint16_t metatileId; Metatile *prevMetatile; Metatile *newMetatile; + QString prevLabel; + QString newLabel; }; class TilesetEditor : public QMainWindow @@ -132,9 +136,11 @@ private: void countMetatileUsage(); void countTileUsage(); void copyMetatile(bool cut); - void pasteMetatile(const Metatile * toPaste); - bool replaceMetatile(uint16_t metatileId, const Metatile * src); + 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); Ui::TilesetEditor *ui; History metatileHistory; diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index 2130824f..4809ba6d 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -113,18 +113,8 @@ Tileset* Tileset::getMetatileLabelTileset(int metatileId, Tileset *primaryTilese return nullptr; } -// If the metatile has a label in the tileset it belongs to, return that label. -// If it doesn't, and the metatile has a label in the other tileset, return that label. -// Otherwise return an empty string. -QString Tileset::getMetatileLabel(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { - Tileset * tileset = Tileset::getMetatileLabelTileset(metatileId, primaryTileset, secondaryTileset); - if (!tileset) - return QString(); - return tileset->metatileLabels.value(metatileId); -} - // Return the pair of possible metatile labels for the specified metatile. -// "normal" is the label for the tileset to which the metatile belongs. +// "owned" is the label for the tileset to which the metatile belongs. // "shared" is the label for the tileset to which the metatile does not belong. MetatileLabelPair Tileset::getMetatileLabelPair(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { MetatileLabelPair labels; @@ -132,15 +122,29 @@ MetatileLabelPair Tileset::getMetatileLabelPair(int metatileId, Tileset *primary QString secondaryMetatileLabel = secondaryTileset ? secondaryTileset->metatileLabels.value(metatileId) : ""; if (metatileId < Project::getNumMetatilesPrimary()) { - labels.normal = primaryMetatileLabel; + labels.owned = primaryMetatileLabel; labels.shared = secondaryMetatileLabel; } else if (metatileId < Project::getNumMetatilesTotal()) { - labels.normal = secondaryMetatileLabel; + labels.owned = secondaryMetatileLabel; labels.shared = primaryMetatileLabel; } return labels; } +// If the metatile has a label in the tileset it belongs to, return that label. +// If it doesn't, and the metatile has a label in the other tileset, return that label. +// Otherwise return an empty string. +QString Tileset::getMetatileLabel(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { + MetatileLabelPair labels = Tileset::getMetatileLabelPair(metatileId, primaryTileset, secondaryTileset); + return !labels.owned.isEmpty() ? labels.owned : labels.shared; +} + +// Just get the "owned" metatile label, i.e. the one for the tileset that the metatile belongs to. +QString Tileset::getOwnedMetatileLabel(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { + MetatileLabelPair labels = Tileset::getMetatileLabelPair(metatileId, primaryTileset, secondaryTileset); + return labels.owned; +} + bool Tileset::setMetatileLabel(int metatileId, QString label, Tileset *primaryTileset, Tileset *secondaryTileset) { Tileset *tileset = Tileset::getMetatileTileset(metatileId, primaryTileset, secondaryTileset); if (!tileset) diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index 4baa83f9..fde049db 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -618,8 +618,6 @@ void MainWindow::setMetatileLabel(int metatileId, QString label) { return; } - // The user may not have the Tileset Editor open. This forcefully saves the change for them. - // If they do have the Tileset Editor open, this has the unintended side effect of saving other unsaved label changes. if (this->editor->project) this->editor->project->saveTilesetMetatileLabels(this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index de2d93fc..7381b1c9 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -276,7 +276,7 @@ void TilesetEditor::restoreWindowState() { } void TilesetEditor::initMetatileHistory() { - MetatileHistoryItem *commit = new MetatileHistoryItem(0, nullptr, new Metatile(*metatile)); + MetatileHistoryItem *commit = new MetatileHistoryItem(0, nullptr, new Metatile(*metatile), QString(), QString()); metatileHistory.push(commit); } @@ -381,7 +381,7 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->ui->graphicsView_metatileLayers->setFixedSize(this->metatileLayersItem->pixmap().width() + 2, this->metatileLayersItem->pixmap().height() + 2); MetatileLabelPair labels = Tileset::getMetatileLabelPair(metatileId, this->primaryTileset, this->secondaryTileset); - this->ui->lineEdit_metatileLabel->setText(labels.normal); + this->ui->lineEdit_metatileLabel->setText(labels.owned); this->ui->lineEdit_metatileLabel->setPlaceholderText(labels.shared); setComboValue(this->ui->comboBox_metatileBehaviors, this->metatile->behavior); @@ -442,11 +442,7 @@ void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { this->metatileSelector->draw(); this->metatileLayersItem->draw(); - this->hasUnsavedChanges = true; - - MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), - prevMetatile, new Metatile(*this->metatile)); - metatileHistory.push(commit); + this->commitMetatileChange(prevMetatile); } void TilesetEditor::onMetatileLayerSelectionChanged(QPoint selectionOrigin, int width, int height) { @@ -525,10 +521,7 @@ void TilesetEditor::on_comboBox_metatileBehaviors_currentTextChanged(const QStri Metatile *prevMetatile = new Metatile(*this->metatile); this->metatile->setBehavior(behavior); - MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), - prevMetatile, new Metatile(*this->metatile)); - metatileHistory.push(commit); - this->hasUnsavedChanges = true; + this->commitMetatileChange(prevMetatile); } } @@ -545,31 +538,36 @@ void TilesetEditor::on_lineEdit_metatileLabel_editingFinished() void TilesetEditor::commitMetatileLabel() { - // TODO: Reimplement edit history for labels - // Only commit if the field has changed. uint16_t metatileId = this->getSelectedMetatileId(); - QString currentLabel = Tileset::getMetatileLabelPair(metatileId, this->primaryTileset, this->secondaryTileset).normal; + QString oldLabel = Tileset::getOwnedMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset); QString newLabel = this->ui->lineEdit_metatileLabel->text(); - if (currentLabel != newLabel) { - //Metatile *prevMetatile = new Metatile(*this->metatile); + if (oldLabel != newLabel) { + Metatile *prevMetatile = new Metatile(*this->metatile); Tileset::setMetatileLabel(metatileId, newLabel, this->primaryTileset, this->secondaryTileset); - /*MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), - prevMetatile, new Metatile(*this->metatile)); - metatileHistory.push(commit);*/ - this->hasUnsavedChanges = true; + this->commitMetatileAndLabelChange(prevMetatile, oldLabel); } } +void TilesetEditor::commitMetatileAndLabelChange(Metatile * prevMetatile, QString prevLabel) +{ + metatileHistory.push(new MetatileHistoryItem(this->getSelectedMetatileId(), + prevMetatile, new Metatile(*this->metatile), + prevLabel, this->ui->lineEdit_metatileLabel->text())); + this->hasUnsavedChanges = true; +} + +void TilesetEditor::commitMetatileChange(Metatile * prevMetatile) +{ + this->commitMetatileAndLabelChange(prevMetatile, this->ui->lineEdit_metatileLabel->text()); +} + void TilesetEditor::on_comboBox_layerType_activated(int layerType) { if (this->metatile) { Metatile *prevMetatile = new Metatile(*this->metatile); this->metatile->setLayerType(layerType); - MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), - prevMetatile, new Metatile(*this->metatile)); - metatileHistory.push(commit); - this->hasUnsavedChanges = true; + this->commitMetatileChange(prevMetatile); this->metatileSelector->draw(); // Changing the layer type can affect how fully transparent metatiles appear } } @@ -579,10 +577,7 @@ void TilesetEditor::on_comboBox_encounterType_activated(int encounterType) if (this->metatile) { Metatile *prevMetatile = new Metatile(*this->metatile); this->metatile->setEncounterType(encounterType); - MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), - prevMetatile, new Metatile(*this->metatile)); - metatileHistory.push(commit); - this->hasUnsavedChanges = true; + this->commitMetatileChange(prevMetatile); } } @@ -591,10 +586,7 @@ void TilesetEditor::on_comboBox_terrainType_activated(int terrainType) if (this->metatile) { Metatile *prevMetatile = new Metatile(*this->metatile); this->metatile->setTerrainType(terrainType); - MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), - prevMetatile, new Metatile(*this->metatile)); - metatileHistory.push(commit); - this->hasUnsavedChanges = true; + this->commitMetatileChange(prevMetatile); } } @@ -850,12 +842,16 @@ void TilesetEditor::onPaletteEditorChangedPalette(int paletteId) { this->on_spinBox_paletteSelector_valueChanged(paletteId); } -bool TilesetEditor::replaceMetatile(uint16_t metatileId, const Metatile * src) +bool TilesetEditor::replaceMetatile(uint16_t metatileId, const Metatile * src, QString label) { Metatile * dest = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset); if (!dest || !src || *dest == *src) return false; + Tileset::setMetatileLabel(metatileId, label, this->primaryTileset, this->secondaryTileset); + if (metatileId == this->getSelectedMetatileId()) + this->ui->lineEdit_metatileLabel->setText(label); + this->metatile = dest; *this->metatile = *src; this->metatileSelector->select(metatileId); @@ -872,22 +868,21 @@ void TilesetEditor::on_actionUndo_triggered() Metatile *prev = commit->prevMetatile; if (!prev) return; this->metatileHistory.back(); - this->replaceMetatile(commit->metatileId, prev); + this->replaceMetatile(commit->metatileId, prev, commit->prevLabel); } void TilesetEditor::on_actionRedo_triggered() { MetatileHistoryItem *commit = this->metatileHistory.next(); if (!commit) return; - this->replaceMetatile(commit->metatileId, commit->newMetatile); + this->replaceMetatile(commit->metatileId, commit->newMetatile, commit->newLabel); } void TilesetEditor::on_actionCut_triggered() { Metatile * empty = new Metatile(projectConfig.getNumTilesInMetatile()); this->copyMetatile(true); - this->pasteMetatile(empty); - this->setMetatileLabel(""); + this->pasteMetatile(empty, ""); delete empty; } @@ -898,8 +893,7 @@ void TilesetEditor::on_actionCopy_triggered() void TilesetEditor::on_actionPaste_triggered() { - this->pasteMetatile(this->copiedMetatile); - this->setMetatileLabel(this->copiedMetatileLabel); + this->pasteMetatile(this->copiedMetatile, this->copiedMetatileLabel); } void TilesetEditor::copyMetatile(bool cut) { @@ -913,22 +907,21 @@ void TilesetEditor::copyMetatile(bool cut) { *this->copiedMetatile = *toCopy; // Don't try to copy the label unless it's a cut, these should be unique to each metatile. - // Never copy the "shared" metatile label. - this->copiedMetatileLabel = cut ? Tileset::getMetatileLabelPair(metatileId, this->primaryTileset, this->secondaryTileset).normal : ""; + this->copiedMetatileLabel = cut ? Tileset::getOwnedMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset) : QString(); } -void TilesetEditor::pasteMetatile(const Metatile * toPaste) +void TilesetEditor::pasteMetatile(const Metatile * toPaste, QString newLabel) { Metatile *prevMetatile = new Metatile(*this->metatile); + QString prevLabel = this->ui->lineEdit_metatileLabel->text(); + if (newLabel.isNull()) newLabel = prevLabel; // Don't change the label if one wasn't copied uint16_t metatileId = this->getSelectedMetatileId(); - if (!this->replaceMetatile(metatileId, toPaste)) { + if (!this->replaceMetatile(metatileId, toPaste, newLabel)) { delete prevMetatile; return; } - MetatileHistoryItem *commit = new MetatileHistoryItem(metatileId, prevMetatile, new Metatile(*this->metatile)); - metatileHistory.push(commit); - this->hasUnsavedChanges = true; + this->commitMetatileAndLabelChange(prevMetatile, prevLabel); } void TilesetEditor::on_actionExport_Primary_Tiles_Image_triggered() @@ -1024,9 +1017,12 @@ void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary) break; } + uint16_t metatileId = static_cast(metatileIdBase + i); + QString prevLabel = Tileset::getOwnedMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset); Metatile *prevMetatile = new Metatile(*tileset->metatiles.at(i)); - MetatileHistoryItem *commit = new MetatileHistoryItem(static_cast(metatileIdBase + i), - prevMetatile, new Metatile(*metatiles.at(i))); + MetatileHistoryItem *commit = new MetatileHistoryItem(metatileId, + prevMetatile, new Metatile(*metatiles.at(i)), + prevLabel, prevLabel); metatileHistory.push(commit); } From 465d51f4a09fae974207e968d32317b562ae7732 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 17 Feb 2023 15:17:20 -0500 Subject: [PATCH 06/10] Update manual and changelog --- CHANGELOG.md | 1 + docsrc/manual/tileset-editor.rst | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19ccb55e..844ad12f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix null characters being unpredictably written to some JSON files. - Fix tilesets that share part of their name loading incorrectly. - Fix events being hidden behind connecting maps. +- Metatile labels with values defined outside their tileset are no longer deleted. - Fix some minor visual issues on the Connections tab. - Fix bug which caused encounter configurator to crash if slots in fields containing groups were deleted. - Fix bug which caused encounter configurator to crash if last field was deleted. diff --git a/docsrc/manual/tileset-editor.rst b/docsrc/manual/tileset-editor.rst index df9cfb95..18b3c810 100644 --- a/docsrc/manual/tileset-editor.rst +++ b/docsrc/manual/tileset-editor.rst @@ -76,12 +76,19 @@ Metatile Label *optional* A name can be given to metatiles so that they may be referenced in source code. -These are defined in ``include/constants/metatile_labels.h`` and can be used in -together with the ``METATILE_ID`` macro. +These are defined in ``include/constants/metatile_labels.h``. -For example, the metatile pictured above can be accessed like -``METATILE_ID(General, Plain_Grass)``. +For example, the metatile pictured above can be referenced using the define +``METATILE_General_Grass``. +This define name can be copied using the Copy button next to the metatile label text box. +Sometimes it may be useful to have a ``METATILE`` define that applies to many tilesets. +This can be done by manually creating a ``METATILE`` define with a value outside its tileset. +For example, the primary tileset ``SecretBase`` is associated with many secondary tilesets, +all of which use the same labels. ``#define METATILE_SecretBase_PC 0x220`` defines a label +for the secondary metatile id ``0x220`` which will be used by any secondary tileset that's +paired with ``SecretBase``. Labels like this will appear gray in the text box, and can't +be edited from within Porymap; they must be edited manually in ``metatile_labels.h``. From 096c26b85ae02ca972554085e24a3a757507ed56 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 17 Feb 2023 15:40:10 -0500 Subject: [PATCH 07/10] Fix label history being ignored if metatile didn't change --- src/ui/tileseteditor.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 7381b1c9..e06e33ad 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -842,15 +842,16 @@ void TilesetEditor::onPaletteEditorChangedPalette(int paletteId) { this->on_spinBox_paletteSelector_valueChanged(paletteId); } -bool TilesetEditor::replaceMetatile(uint16_t metatileId, const Metatile * src, QString label) +bool TilesetEditor::replaceMetatile(uint16_t metatileId, const Metatile * src, QString newLabel) { Metatile * dest = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset); - if (!dest || !src || *dest == *src) + QString oldLabel = Tileset::getOwnedMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset); + if (!dest || !src || (*dest == *src && oldLabel == newLabel)) return false; - Tileset::setMetatileLabel(metatileId, label, this->primaryTileset, this->secondaryTileset); + Tileset::setMetatileLabel(metatileId, newLabel, this->primaryTileset, this->secondaryTileset); if (metatileId == this->getSelectedMetatileId()) - this->ui->lineEdit_metatileLabel->setText(label); + this->ui->lineEdit_metatileLabel->setText(newLabel); this->metatile = dest; *this->metatile = *src; From f8bc65ad3f18d57ea1f1a620f7e572186e467e82 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 17 Feb 2023 17:48:03 -0500 Subject: [PATCH 08/10] Fix metatile label name in manual --- docsrc/manual/tileset-editor.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docsrc/manual/tileset-editor.rst b/docsrc/manual/tileset-editor.rst index 18b3c810..83b10012 100644 --- a/docsrc/manual/tileset-editor.rst +++ b/docsrc/manual/tileset-editor.rst @@ -79,7 +79,7 @@ A name can be given to metatiles so that they may be referenced in source code. These are defined in ``include/constants/metatile_labels.h``. For example, the metatile pictured above can be referenced using the define -``METATILE_General_Grass``. +``METATILE_General_Plain_Grass``. This define name can be copied using the Copy button next to the metatile label text box. Sometimes it may be useful to have a ``METATILE`` define that applies to many tilesets. From 26f07add795f0db90d052cf5b93196976b9256ca Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 17 Feb 2023 22:27:02 -0500 Subject: [PATCH 09/10] Reset Tileset Editor history when tileset changes --- include/core/history.h | 6 ++++++ src/ui/tileseteditor.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/core/history.h b/include/core/history.h index 0c26780c..c999a4e1 100644 --- a/include/core/history.h +++ b/include/core/history.h @@ -10,9 +10,15 @@ public: History() { } ~History() { + clear(); + } + + void clear() { while (!history.isEmpty()) { delete history.takeLast(); } + head = -1; + saved = -1; } T back() { diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index e06e33ad..c16aeaf4 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -22,7 +22,6 @@ TilesetEditor::TilesetEditor(Project *project, Map *map, QWidget *parent) : { this->setTilesets(this->map->layout->tileset_primary_label, this->map->layout->tileset_secondary_label); this->initUi(); - this->initMetatileHistory(); } TilesetEditor::~TilesetEditor() @@ -64,7 +63,6 @@ void TilesetEditor::updateTilesets(QString primaryTilesetLabel, QString secondar if (result == QMessageBox::Yes) this->on_actionSave_Tileset_triggered(); } - this->hasUnsavedChanges = false; this->setTilesets(primaryTilesetLabel, secondaryTilesetLabel); this->refresh(); } @@ -89,6 +87,7 @@ void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTi this->primaryTileset = new Tileset(*primaryTileset); this->secondaryTileset = new Tileset(*secondaryTileset); if (paletteEditor) paletteEditor->setTilesets(this->primaryTileset, this->secondaryTileset); + this->initMetatileHistory(); } void TilesetEditor::initUi() { @@ -276,12 +275,13 @@ void TilesetEditor::restoreWindowState() { } void TilesetEditor::initMetatileHistory() { - MetatileHistoryItem *commit = new MetatileHistoryItem(0, nullptr, new Metatile(*metatile), QString(), QString()); + metatileHistory.clear(); + MetatileHistoryItem *commit = new MetatileHistoryItem(0, nullptr, new Metatile(), QString(), QString()); metatileHistory.push(commit); + this->hasUnsavedChanges = false; } void TilesetEditor::reset() { - this->hasUnsavedChanges = false; this->setTilesets(this->primaryTileset->name, this->secondaryTileset->name); if (this->paletteEditor) this->paletteEditor->setTilesets(this->primaryTileset, this->secondaryTileset); From 5ffed045e41f89105d73e23d681c42d7cb77df7f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 17 Feb 2023 22:29:58 -0500 Subject: [PATCH 10/10] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 844ad12f..af961fa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix tilesets that share part of their name loading incorrectly. - Fix events being hidden behind connecting maps. - Metatile labels with values defined outside their tileset are no longer deleted. +- Fix the Tileset Editor retaining edit history after changing tilesets. - Fix some minor visual issues on the Connections tab. - Fix bug which caused encounter configurator to crash if slots in fields containing groups were deleted. - Fix bug which caused encounter configurator to crash if last field was deleted.