Reimplement metatile label edit history

This commit is contained in:
GriffinR 2023-02-15 13:44:09 -05:00
parent 44dba9edc5
commit 6508fd10af
5 changed files with 72 additions and 67 deletions

View file

@ -8,7 +8,7 @@
#include <QHash> #include <QHash>
struct MetatileLabelPair { struct MetatileLabelPair {
QString normal; QString owned;
QString shared; QString shared;
}; };
@ -43,6 +43,7 @@ public:
static Metatile* getMetatile(int, Tileset*, Tileset*); static Metatile* getMetatile(int, Tileset*, Tileset*);
static Tileset* getMetatileLabelTileset(int, Tileset*, Tileset*); static Tileset* getMetatileLabelTileset(int, Tileset*, Tileset*);
static QString getMetatileLabel(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 MetatileLabelPair getMetatileLabelPair(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset);
static bool setMetatileLabel(int, QString, Tileset *, Tileset *); static bool setMetatileLabel(int, QString, Tileset *, Tileset *);
QString getMetatileLabelPrefix(); QString getMetatileLabelPrefix();

View file

@ -16,10 +16,12 @@ class TilesetEditor;
class MetatileHistoryItem { class MetatileHistoryItem {
public: 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->metatileId = metatileId;
this->prevMetatile = prevMetatile; this->prevMetatile = prevMetatile;
this->newMetatile = newMetatile; this->newMetatile = newMetatile;
this->prevLabel = prevLabel;
this->newLabel = newLabel;
} }
~MetatileHistoryItem() { ~MetatileHistoryItem() {
delete this->prevMetatile; delete this->prevMetatile;
@ -28,6 +30,8 @@ public:
uint16_t metatileId; uint16_t metatileId;
Metatile *prevMetatile; Metatile *prevMetatile;
Metatile *newMetatile; Metatile *newMetatile;
QString prevLabel;
QString newLabel;
}; };
class TilesetEditor : public QMainWindow class TilesetEditor : public QMainWindow
@ -132,9 +136,11 @@ private:
void countMetatileUsage(); void countMetatileUsage();
void countTileUsage(); void countTileUsage();
void copyMetatile(bool cut); void copyMetatile(bool cut);
void pasteMetatile(const Metatile * toPaste); void pasteMetatile(const Metatile * toPaste, QString label);
bool replaceMetatile(uint16_t metatileId, const Metatile * src); bool replaceMetatile(uint16_t metatileId, const Metatile * src, QString label);
void setComboValue(QComboBox * combo, int value); void setComboValue(QComboBox * combo, int value);
void commitMetatileChange(Metatile * prevMetatile);
void commitMetatileAndLabelChange(Metatile * prevMetatile, QString prevLabel);
Ui::TilesetEditor *ui; Ui::TilesetEditor *ui;
History<MetatileHistoryItem*> metatileHistory; History<MetatileHistoryItem*> metatileHistory;

View file

@ -113,18 +113,8 @@ Tileset* Tileset::getMetatileLabelTileset(int metatileId, Tileset *primaryTilese
return nullptr; 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. // 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. // "shared" is the label for the tileset to which the metatile does not belong.
MetatileLabelPair Tileset::getMetatileLabelPair(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) { MetatileLabelPair Tileset::getMetatileLabelPair(int metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) {
MetatileLabelPair labels; MetatileLabelPair labels;
@ -132,15 +122,29 @@ MetatileLabelPair Tileset::getMetatileLabelPair(int metatileId, Tileset *primary
QString secondaryMetatileLabel = secondaryTileset ? secondaryTileset->metatileLabels.value(metatileId) : ""; QString secondaryMetatileLabel = secondaryTileset ? secondaryTileset->metatileLabels.value(metatileId) : "";
if (metatileId < Project::getNumMetatilesPrimary()) { if (metatileId < Project::getNumMetatilesPrimary()) {
labels.normal = primaryMetatileLabel; labels.owned = primaryMetatileLabel;
labels.shared = secondaryMetatileLabel; labels.shared = secondaryMetatileLabel;
} else if (metatileId < Project::getNumMetatilesTotal()) { } else if (metatileId < Project::getNumMetatilesTotal()) {
labels.normal = secondaryMetatileLabel; labels.owned = secondaryMetatileLabel;
labels.shared = primaryMetatileLabel; labels.shared = primaryMetatileLabel;
} }
return labels; 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) { bool Tileset::setMetatileLabel(int metatileId, QString label, Tileset *primaryTileset, Tileset *secondaryTileset) {
Tileset *tileset = Tileset::getMetatileTileset(metatileId, primaryTileset, secondaryTileset); Tileset *tileset = Tileset::getMetatileTileset(metatileId, primaryTileset, secondaryTileset);
if (!tileset) if (!tileset)

View file

@ -618,8 +618,6 @@ void MainWindow::setMetatileLabel(int metatileId, QString label) {
return; 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) if (this->editor->project)
this->editor->project->saveTilesetMetatileLabels(this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); this->editor->project->saveTilesetMetatileLabels(this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
} }

View file

@ -276,7 +276,7 @@ void TilesetEditor::restoreWindowState() {
} }
void TilesetEditor::initMetatileHistory() { 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); 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); this->ui->graphicsView_metatileLayers->setFixedSize(this->metatileLayersItem->pixmap().width() + 2, this->metatileLayersItem->pixmap().height() + 2);
MetatileLabelPair labels = Tileset::getMetatileLabelPair(metatileId, this->primaryTileset, this->secondaryTileset); 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); this->ui->lineEdit_metatileLabel->setPlaceholderText(labels.shared);
setComboValue(this->ui->comboBox_metatileBehaviors, this->metatile->behavior); setComboValue(this->ui->comboBox_metatileBehaviors, this->metatile->behavior);
@ -442,11 +442,7 @@ void TilesetEditor::onMetatileLayerTileChanged(int x, int y) {
this->metatileSelector->draw(); this->metatileSelector->draw();
this->metatileLayersItem->draw(); this->metatileLayersItem->draw();
this->hasUnsavedChanges = true; this->commitMetatileChange(prevMetatile);
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
} }
void TilesetEditor::onMetatileLayerSelectionChanged(QPoint selectionOrigin, int width, int height) { 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); Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->setBehavior(behavior); this->metatile->setBehavior(behavior);
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), this->commitMetatileChange(prevMetatile);
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
} }
} }
@ -545,31 +538,36 @@ void TilesetEditor::on_lineEdit_metatileLabel_editingFinished()
void TilesetEditor::commitMetatileLabel() void TilesetEditor::commitMetatileLabel()
{ {
// TODO: Reimplement edit history for labels
// Only commit if the field has changed. // Only commit if the field has changed.
uint16_t metatileId = this->getSelectedMetatileId(); 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(); QString newLabel = this->ui->lineEdit_metatileLabel->text();
if (currentLabel != newLabel) { if (oldLabel != newLabel) {
//Metatile *prevMetatile = new Metatile(*this->metatile); Metatile *prevMetatile = new Metatile(*this->metatile);
Tileset::setMetatileLabel(metatileId, newLabel, this->primaryTileset, this->secondaryTileset); Tileset::setMetatileLabel(metatileId, newLabel, this->primaryTileset, this->secondaryTileset);
/*MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), this->commitMetatileAndLabelChange(prevMetatile, oldLabel);
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);*/
this->hasUnsavedChanges = true;
} }
} }
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) void TilesetEditor::on_comboBox_layerType_activated(int layerType)
{ {
if (this->metatile) { if (this->metatile) {
Metatile *prevMetatile = new Metatile(*this->metatile); Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->setLayerType(layerType); this->metatile->setLayerType(layerType);
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), this->commitMetatileChange(prevMetatile);
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
this->metatileSelector->draw(); // Changing the layer type can affect how fully transparent metatiles appear 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) { if (this->metatile) {
Metatile *prevMetatile = new Metatile(*this->metatile); Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->setEncounterType(encounterType); this->metatile->setEncounterType(encounterType);
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), this->commitMetatileChange(prevMetatile);
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
} }
} }
@ -591,10 +586,7 @@ void TilesetEditor::on_comboBox_terrainType_activated(int terrainType)
if (this->metatile) { if (this->metatile) {
Metatile *prevMetatile = new Metatile(*this->metatile); Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->setTerrainType(terrainType); this->metatile->setTerrainType(terrainType);
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(), this->commitMetatileChange(prevMetatile);
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
} }
} }
@ -850,12 +842,16 @@ void TilesetEditor::onPaletteEditorChangedPalette(int paletteId) {
this->on_spinBox_paletteSelector_valueChanged(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); Metatile * dest = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset);
if (!dest || !src || *dest == *src) if (!dest || !src || *dest == *src)
return false; 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 = dest;
*this->metatile = *src; *this->metatile = *src;
this->metatileSelector->select(metatileId); this->metatileSelector->select(metatileId);
@ -872,22 +868,21 @@ void TilesetEditor::on_actionUndo_triggered()
Metatile *prev = commit->prevMetatile; Metatile *prev = commit->prevMetatile;
if (!prev) return; if (!prev) return;
this->metatileHistory.back(); this->metatileHistory.back();
this->replaceMetatile(commit->metatileId, prev); this->replaceMetatile(commit->metatileId, prev, commit->prevLabel);
} }
void TilesetEditor::on_actionRedo_triggered() void TilesetEditor::on_actionRedo_triggered()
{ {
MetatileHistoryItem *commit = this->metatileHistory.next(); MetatileHistoryItem *commit = this->metatileHistory.next();
if (!commit) return; if (!commit) return;
this->replaceMetatile(commit->metatileId, commit->newMetatile); this->replaceMetatile(commit->metatileId, commit->newMetatile, commit->newLabel);
} }
void TilesetEditor::on_actionCut_triggered() void TilesetEditor::on_actionCut_triggered()
{ {
Metatile * empty = new Metatile(projectConfig.getNumTilesInMetatile()); Metatile * empty = new Metatile(projectConfig.getNumTilesInMetatile());
this->copyMetatile(true); this->copyMetatile(true);
this->pasteMetatile(empty); this->pasteMetatile(empty, "");
this->setMetatileLabel("");
delete empty; delete empty;
} }
@ -898,8 +893,7 @@ void TilesetEditor::on_actionCopy_triggered()
void TilesetEditor::on_actionPaste_triggered() void TilesetEditor::on_actionPaste_triggered()
{ {
this->pasteMetatile(this->copiedMetatile); this->pasteMetatile(this->copiedMetatile, this->copiedMetatileLabel);
this->setMetatileLabel(this->copiedMetatileLabel);
} }
void TilesetEditor::copyMetatile(bool cut) { void TilesetEditor::copyMetatile(bool cut) {
@ -913,22 +907,21 @@ void TilesetEditor::copyMetatile(bool cut) {
*this->copiedMetatile = *toCopy; *this->copiedMetatile = *toCopy;
// Don't try to 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.
// Never copy the "shared" metatile label. this->copiedMetatileLabel = cut ? Tileset::getOwnedMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset) : QString();
this->copiedMetatileLabel = cut ? Tileset::getMetatileLabelPair(metatileId, this->primaryTileset, this->secondaryTileset).normal : "";
} }
void TilesetEditor::pasteMetatile(const Metatile * toPaste) void TilesetEditor::pasteMetatile(const Metatile * toPaste, QString newLabel)
{ {
Metatile *prevMetatile = new Metatile(*this->metatile); 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(); uint16_t metatileId = this->getSelectedMetatileId();
if (!this->replaceMetatile(metatileId, toPaste)) { if (!this->replaceMetatile(metatileId, toPaste, newLabel)) {
delete prevMetatile; delete prevMetatile;
return; return;
} }
MetatileHistoryItem *commit = new MetatileHistoryItem(metatileId, prevMetatile, new Metatile(*this->metatile)); this->commitMetatileAndLabelChange(prevMetatile, prevLabel);
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
} }
void TilesetEditor::on_actionExport_Primary_Tiles_Image_triggered() void TilesetEditor::on_actionExport_Primary_Tiles_Image_triggered()
@ -1024,9 +1017,12 @@ void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary)
break; break;
} }
uint16_t metatileId = static_cast<uint16_t>(metatileIdBase + i);
QString prevLabel = Tileset::getOwnedMetatileLabel(metatileId, this->primaryTileset, this->secondaryTileset);
Metatile *prevMetatile = new Metatile(*tileset->metatiles.at(i)); Metatile *prevMetatile = new Metatile(*tileset->metatiles.at(i));
MetatileHistoryItem *commit = new MetatileHistoryItem(static_cast<uint16_t>(metatileIdBase + i), MetatileHistoryItem *commit = new MetatileHistoryItem(metatileId,
prevMetatile, new Metatile(*metatiles.at(i))); prevMetatile, new Metatile(*metatiles.at(i)),
prevLabel, prevLabel);
metatileHistory.push(commit); metatileHistory.push(commit);
} }