From e42c2e1a814ddba512cc43fccba3bff48abf8d67 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Sat, 6 Oct 2018 17:07:36 -0500 Subject: [PATCH] Add edit-undo history to tileset metatile editing --- forms/tileseteditor.ui | 24 ++++++++++++++ include/core/metatile.h | 1 + include/ui/metatilelayersitem.h | 4 +++ include/ui/tileseteditor.h | 30 ++++++++++++++--- src/core/metatile.cpp | 8 +++++ src/ui/metatilelayersitem.cpp | 38 ++++++++++++++++----- src/ui/tileseteditor.cpp | 58 +++++++++++++++++++++++++++++++-- 7 files changed, 149 insertions(+), 14 deletions(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index f8b6947f..7a56f4a9 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -407,7 +407,15 @@ + + + Edit + + + + + @@ -439,6 +447,22 @@ Change Palettes + + + Undo + + + Ctrl+Z + + + + + Redo + + + Ctrl+Y + + diff --git a/include/core/metatile.h b/include/core/metatile.h index 4f280608..955c4264 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -14,6 +14,7 @@ public: uint8_t layerType; Metatile *copy(); + void copyInPlace(Metatile*); static int getBlockIndex(int); }; diff --git a/include/ui/metatilelayersitem.h b/include/ui/metatilelayersitem.h index f76ddc3a..0417f907 100644 --- a/include/ui/metatilelayersitem.h +++ b/include/ui/metatilelayersitem.h @@ -13,14 +13,18 @@ public: this->metatile = metatile; this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; + this->clearLastModifiedCoords(); } void draw(); void setTilesets(Tileset*, Tileset*); void setMetatile(Metatile*); + void clearLastModifiedCoords(); private: Metatile* metatile; Tileset *primaryTileset; Tileset *secondaryTileset; + QPoint prevChangedTile; + void getBoundedCoords(QPointF, int*, int*); signals: void tileChanged(int, int); void selectedTilesChanged(QPoint, int, int); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index b4945d8a..776f78cc 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -3,6 +3,7 @@ #include #include "project.h" +#include "history.h" #include "paletteeditor.h" #include "tileseteditormetatileselector.h" #include "tileseteditortileselector.h" @@ -12,6 +13,22 @@ namespace Ui { class TilesetEditor; } +class MetatileHistoryItem { +public: + MetatileHistoryItem(uint16_t metatileId, Metatile *prevMetatile, Metatile *newMetatile) { + this->metatileId = metatileId; + this->prevMetatile = prevMetatile; + this->newMetatile = newMetatile; + } + ~MetatileHistoryItem() { + delete this->prevMetatile; + delete this->newMetatile; + } + uint16_t metatileId; + Metatile *prevMetatile; + Metatile *newMetatile; +}; + class TilesetEditor : public QMainWindow { Q_OBJECT @@ -41,10 +58,6 @@ private slots: void on_checkBox_yFlip_stateChanged(int arg1); - void on_comboBox_metatileBehaviors_currentIndexChanged(const QString &arg1); - - void on_comboBox_layerType_currentIndexChanged(int index); - void on_actionSave_Tileset_triggered(); void on_actionImport_Primary_Tiles_triggered(); @@ -55,6 +68,14 @@ private slots: void on_actionChange_Palettes_triggered(); + void on_actionUndo_triggered(); + + void on_actionRedo_triggered(); + + void on_comboBox_metatileBehaviors_activated(const QString &arg1); + + void on_comboBox_layerType_activated(int arg1); + private: void closeEvent(QCloseEvent*); void initMetatileSelector(); @@ -65,6 +86,7 @@ private: void importTilesetTiles(Tileset*, bool); void refresh(); Ui::TilesetEditor *ui; + History metatileHistory; TilesetEditorMetatileSelector *metatileSelector = nullptr; TilesetEditorTileSelector *tileSelector = nullptr; MetatileLayersItem *metatileLayersItem = nullptr; diff --git a/src/core/metatile.cpp b/src/core/metatile.cpp index a44b4fa3..e239085d 100644 --- a/src/core/metatile.cpp +++ b/src/core/metatile.cpp @@ -18,6 +18,14 @@ Metatile* Metatile::copy() { return copy; } +void Metatile::copyInPlace(Metatile *other) { + this->behavior = other->behavior; + this->layerType = other->layerType; + for (int i = 0; i < this->tiles->length(); i++) { + (*this->tiles)[i] = other->tiles->at(i); + } +} + int Metatile::getBlockIndex(int index) { if (index < Project::getNumMetatilesPrimary()) { return index; diff --git a/src/ui/metatilelayersitem.cpp b/src/ui/metatilelayersitem.cpp index f6186a78..68a58492 100644 --- a/src/ui/metatilelayersitem.cpp +++ b/src/ui/metatilelayersitem.cpp @@ -29,12 +29,14 @@ void MetatileLayersItem::draw() { void MetatileLayersItem::setMetatile(Metatile *metatile) { this->metatile = metatile; + this->clearLastModifiedCoords(); } void MetatileLayersItem::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; this->draw(); + this->clearLastModifiedCoords(); } void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { @@ -45,17 +47,17 @@ void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { emit this->selectedTilesChanged(selectionOrigin, dimensions.x(), dimensions.y()); this->drawSelection(); } else { - QPointF pos = event->pos(); - int x = static_cast(pos.x()) / 16; - int y = static_cast(pos.y()) / 16; - emit this->tileChanged(x, y); + int x, y; + this->getBoundedCoords(event->pos(), &x, &y); + if (prevChangedTile.x() != x || prevChangedTile.y() != y) { + this->prevChangedTile.setX(x); + this->prevChangedTile.setY(y); + emit this->tileChanged(x, y); + } } } void MetatileLayersItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - QPointF pos = event->pos(); - int x = static_cast(pos.x()) / 16; - int y = static_cast(pos.y()) / 16; if (event->buttons() & Qt::RightButton) { SelectablePixmapItem::mouseMoveEvent(event); QPoint selectionOrigin = this->getSelectionStart(); @@ -63,7 +65,13 @@ void MetatileLayersItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { emit this->selectedTilesChanged(selectionOrigin, dimensions.x(), dimensions.y()); this->drawSelection(); } else { - emit this->tileChanged(x, y); + int x, y; + this->getBoundedCoords(event->pos(), &x, &y); + if (prevChangedTile.x() != x || prevChangedTile.y() != y) { + this->prevChangedTile.setX(x); + this->prevChangedTile.setY(y); + emit this->tileChanged(x, y); + } } } @@ -77,3 +85,17 @@ void MetatileLayersItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { this->draw(); } + +void MetatileLayersItem::clearLastModifiedCoords() { + this->prevChangedTile.setX(-1); + this->prevChangedTile.setY(-1); +} + +void MetatileLayersItem::getBoundedCoords(QPointF pos, int *x, int *y) { + *x = static_cast(pos.x()) / 16; + *y = static_cast(pos.y()) / 16; + if (*x < 0) *x = 0; + if (*y < 0) *y = 0; + if (*x > 3) *x = 3; + if (*y > 1) *y = 1; +} diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 773ed4d8..56adc6a5 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -49,6 +49,9 @@ void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString this->initTileSelector(); this->initSelectedTileItem(); this->metatileSelector->select(0); + + MetatileHistoryItem *commit = new MetatileHistoryItem(0, nullptr, this->metatile->copy()); + metatileHistory.push(commit); } void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) { @@ -191,6 +194,7 @@ void TilesetEditor::onSelectedTilesChanged() { } void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { + Metatile *prevMetatile = this->metatile->copy(); int maxTileIndex = x < 2 ? 3 : 7; QPoint dimensions = this->tileSelector->getSelectionDimensions(); QList tiles = this->tileSelector->getSelectedTiles(); @@ -213,6 +217,9 @@ void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { this->metatileSelector->draw(); this->metatileLayersItem->draw(); this->hasUnsavedChanges = true; + + MetatileHistoryItem *commit = new MetatileHistoryItem(metatileSelector->getSelectedMetatile(), prevMetatile, this->metatile->copy()); + metatileHistory.push(commit); } void TilesetEditor::onMetatileLayerSelectionChanged(QPoint selectionOrigin, int width, int height) { @@ -228,6 +235,7 @@ void TilesetEditor::onMetatileLayerSelectionChanged(QPoint selectionOrigin, int } } this->tileSelector->setExternalSelection(width, height, tiles); + this->metatileLayersItem->clearLastModifiedCoords(); } void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId) @@ -241,6 +249,7 @@ void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId) if (this->paletteEditor) { this->paletteEditor->setPaletteId(paletteId); } + this->metatileLayersItem->clearLastModifiedCoords(); } void TilesetEditor::on_checkBox_xFlip_stateChanged(int checked) @@ -248,6 +257,7 @@ void TilesetEditor::on_checkBox_xFlip_stateChanged(int checked) this->tileXFlip = checked; this->tileSelector->setTileFlips(this->tileXFlip, this->tileYFlip); this->drawSelectedTiles(); + this->metatileLayersItem->clearLastModifiedCoords(); } void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked) @@ -255,19 +265,26 @@ void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked) this->tileYFlip = checked; this->tileSelector->setTileFlips(this->tileXFlip, this->tileYFlip); this->drawSelectedTiles(); + this->metatileLayersItem->clearLastModifiedCoords(); } -void TilesetEditor::on_comboBox_metatileBehaviors_currentIndexChanged(const QString &metatileBehavior) +void TilesetEditor::on_comboBox_metatileBehaviors_activated(const QString &metatileBehavior) { if (this->metatile) { + Metatile *prevMetatile = this->metatile->copy(); this->metatile->behavior = static_cast(project->metatileBehaviorMap[metatileBehavior]); + MetatileHistoryItem *commit = new MetatileHistoryItem(metatileSelector->getSelectedMetatile(), prevMetatile, this->metatile->copy()); + metatileHistory.push(commit); } } -void TilesetEditor::on_comboBox_layerType_currentIndexChanged(int layerType) +void TilesetEditor::on_comboBox_layerType_activated(int layerType) { if (this->metatile) { + Metatile *prevMetatile = this->metatile->copy(); this->metatile->layerType = static_cast(layerType); + MetatileHistoryItem *commit = new MetatileHistoryItem(metatileSelector->getSelectedMetatile(), prevMetatile, this->metatile->copy()); + metatileHistory.push(commit); } } @@ -475,3 +492,40 @@ void TilesetEditor::onPaletteEditorChangedPaletteColor() { void TilesetEditor::onPaletteEditorChangedPalette(int paletteId) { this->on_spinBox_paletteSelector_valueChanged(paletteId); } + +void TilesetEditor::on_actionUndo_triggered() +{ + MetatileHistoryItem *commit = this->metatileHistory.current(); + if (!commit) return; + Metatile *prev = commit->prevMetatile; + if (!prev) return; + this->metatileHistory.back(); + + Metatile *temp = Tileset::getMetatile(commit->metatileId, this->primaryTileset, this->secondaryTileset); + if (temp) { + this->metatile = temp; + this->metatile->copyInPlace(prev); + this->metatileSelector->select(commit->metatileId); + this->metatileSelector->draw(); + this->metatileLayersItem->draw(); + this->metatileLayersItem->clearLastModifiedCoords(); + } +} + +void TilesetEditor::on_actionRedo_triggered() +{ + MetatileHistoryItem *commit = this->metatileHistory.next(); + if (!commit) return; + Metatile *next = commit->newMetatile; + if (!next) return; + + Metatile *temp = Tileset::getMetatile(commit->metatileId, this->primaryTileset, this->secondaryTileset); + if (temp) { + this->metatile = Tileset::getMetatile(commit->metatileId, this->primaryTileset, this->secondaryTileset); + this->metatile->copyInPlace(next); + this->metatileSelector->select(commit->metatileId); + this->metatileSelector->draw(); + this->metatileLayersItem->draw(); + this->metatileLayersItem->clearLastModifiedCoords(); + } +}