Add edit-undo history to tileset metatile editing

This commit is contained in:
Marcus Huderle 2018-10-06 17:07:36 -05:00
parent 888270f3ef
commit e42c2e1a81
7 changed files with 149 additions and 14 deletions

View file

@ -407,7 +407,15 @@
<addaction name="actionChange_Metatiles_Count"/>
<addaction name="actionChange_Palettes"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>Edit</string>
</property>
<addaction name="actionUndo"/>
<addaction name="actionRedo"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuTools"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
@ -439,6 +447,22 @@
<string>Change Palettes</string>
</property>
</action>
<action name="actionUndo">
<property name="text">
<string>Undo</string>
</property>
<property name="shortcut">
<string>Ctrl+Z</string>
</property>
</action>
<action name="actionRedo">
<property name="text">
<string>Redo</string>
</property>
<property name="shortcut">
<string>Ctrl+Y</string>
</property>
</action>
</widget>
<resources/>
<connections/>

View file

@ -14,6 +14,7 @@ public:
uint8_t layerType;
Metatile *copy();
void copyInPlace(Metatile*);
static int getBlockIndex(int);
};

View file

@ -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);

View file

@ -3,6 +3,7 @@
#include <QMainWindow>
#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<MetatileHistoryItem*> metatileHistory;
TilesetEditorMetatileSelector *metatileSelector = nullptr;
TilesetEditorTileSelector *tileSelector = nullptr;
MetatileLayersItem *metatileLayersItem = nullptr;

View file

@ -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;

View file

@ -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<int>(pos.x()) / 16;
int y = static_cast<int>(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<int>(pos.x()) / 16;
int y = static_cast<int>(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<int>(pos.x()) / 16;
*y = static_cast<int>(pos.y()) / 16;
if (*x < 0) *x = 0;
if (*y < 0) *y = 0;
if (*x > 3) *x = 3;
if (*y > 1) *y = 1;
}

View file

@ -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<Tile> 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<uint8_t>(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<uint8_t>(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();
}
}