diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index f5e0a0b8..0bc68401 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -2711,8 +2711,6 @@ Edit - - @@ -2832,25 +2830,6 @@ Ctrl+N - - - Undo - - - Ctrl+Z - - - - - Redo - - - - - - Ctrl+Y - - Export Map Image... diff --git a/include/core/editcommands.h b/include/core/editcommands.h new file mode 100644 index 00000000..45ac1346 --- /dev/null +++ b/include/core/editcommands.h @@ -0,0 +1,168 @@ +#ifndef EDITCOMMANDS_H +#define EDITCOMMANDS_H + +#include + +class MapPixmapItem; +class Map; +class Blockdata; + +enum CommandId { + ID_PaintMetatile, // - done + ID_BucketFillMetatile, // - done + ID_MagicFillMetatile, // - done + ID_ShiftMetatiles, // - done + ID_ResizeMap, // - done + ID_PaintBorder, // - done + ID_EventMove, // - + ID_EventCreate, // - + ID_EventDelete, // - + ID_EventSetData, // - + // Tileset editor history commands + // Region map editor history commands +}; + + + +/// TODO +class PaintMetatile : public QUndoCommand { +public: + PaintMetatile(Map *map, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + unsigned eventId, QUndoCommand *parent = nullptr); + ~PaintMetatile(); + + void undo() override; + void redo() override; + + bool mergeWith(const QUndoCommand *command) override; + int id() const override { return CommandId::ID_PaintMetatile; } + +private: + Map *map; + + Blockdata *newMetatiles; + Blockdata *oldMetatiles; + + unsigned eventId; +}; + + + +/// +class PaintBorder : public QUndoCommand { +public: + PaintBorder(Map *map, + Blockdata *oldBorder, Blockdata *newBorder, + unsigned eventId, QUndoCommand *parent = nullptr); + ~PaintBorder(); + + void undo() override; + void redo() override; + + bool mergeWith(const QUndoCommand *command) override { return false; }; + int id() const override { return CommandId::ID_PaintBorder; } + +private: + Map *map; + + Blockdata *newBorder; + Blockdata *oldBorder; + + unsigned eventId; +}; + + + +/// +class BucketFillMetatile : public PaintMetatile { +public: + BucketFillMetatile(Map *map, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + unsigned eventId, QUndoCommand *parent = nullptr); + ~BucketFillMetatile(); + + bool mergeWith(const QUndoCommand *command) override { return false; } + int id() const override { return CommandId::ID_BucketFillMetatile; } +}; + + + +/// +class MagicFillMetatile : public PaintMetatile { +public: + MagicFillMetatile(Map *map, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + unsigned eventId, QUndoCommand *parent = nullptr); + ~MagicFillMetatile(); + + bool mergeWith(const QUndoCommand *command) override { return false; } + int id() const override { return CommandId::ID_BucketFillMetatile; } +}; + + + + +/// +class ShiftMetatiles : public QUndoCommand { +public: + ShiftMetatiles(Map *map, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + unsigned eventId, QUndoCommand *parent = nullptr); + ~ShiftMetatiles(); + + void undo() override; + void redo() override; + + bool mergeWith(const QUndoCommand *command) override; + int id() const override { return CommandId::ID_ShiftMetatiles; } + +private: + Map *map; + + Blockdata *newMetatiles; + Blockdata *oldMetatiles; + + unsigned eventId; + bool mergeable = false; +}; + + + +/// +class ResizeMap : public QUndoCommand { +public: + ResizeMap(Map *map, QSize oldMapDimensions, QSize newMapDimensions, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + QSize oldBorderDimensions, QSize newBorderDimensions, + Blockdata *oldBorder, Blockdata *newBorder, + QUndoCommand *parent = nullptr); + ~ResizeMap(); + + void undo() override; + void redo() override; + + bool mergeWith(const QUndoCommand *command) override { return false; } + int id() const override { return CommandId::ID_ResizeMap; } + +private: + Map *map; + + int oldMapWidth; + int oldMapHeight; + int newMapWidth; + int newMapHeight; + + int oldBorderWidth; + int oldBorderHeight; + int newBorderWidth; + int newBorderHeight; + + Blockdata *newMetatiles; + Blockdata *oldMetatiles; + + Blockdata *newBorder; + Blockdata *oldBorder; +}; + +#endif // EDITCOMMANDS_H diff --git a/include/core/map.h b/include/core/map.h index d33f5458..a5391f4d 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -9,6 +9,7 @@ #include "tileset.h" #include "event.h" +#include #include #include #include @@ -21,6 +22,9 @@ // porymap will reflect changes to it, but the value is hard-coded in the projects at the moment #define BORDER_DISTANCE 7 +class MapPixmapItem; +class BorderMetatilesPixmapItem; + class Map : public QObject { Q_OBJECT @@ -80,9 +84,6 @@ public: void floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation); void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation); void magicFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation); - void undo(); - void redo(); - void commit(); QList getAllEvents(); void removeEvent(Event*); void addEvent(Event*); @@ -93,6 +94,16 @@ public: void cacheBorder(); bool hasUnsavedChanges(); + MapPixmapItem *mapItem = nullptr; + void setMapItem(MapPixmapItem *item) { mapItem = item; } + + BorderMetatilesPixmapItem *borderItem = nullptr; + void setBorderItem(BorderMetatilesPixmapItem *item) { borderItem = item; } + + void commit(); // TODO: delete this + + QUndoStack editHistory; + private: void setNewDimensionsBlockdata(int newWidth, int newHeight); void setNewBorderDimensionsBlockdata(int newWidth, int newHeight); diff --git a/include/core/maplayout.h b/include/core/maplayout.h index c2c71d8e..c0c603ee 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -23,7 +23,7 @@ public: QString tileset_secondary_label; Tileset *tileset_primary = nullptr; Tileset *tileset_secondary = nullptr; - Blockdata* blockdata = nullptr; + Blockdata *blockdata = nullptr; QImage border_image; QPixmap border_pixmap; Blockdata *border = nullptr; diff --git a/include/core/wildmoninfo.h b/include/core/wildmoninfo.h index 51eed213..f0868f7f 100644 --- a/include/core/wildmoninfo.h +++ b/include/core/wildmoninfo.h @@ -16,7 +16,7 @@ struct WildMonInfo { }; struct WildPokemonHeader { - QMap wildMons; + QHash wildMons; }; struct EncounterField { diff --git a/include/editor.h b/include/editor.h index bd0641e2..7edabbbb 100644 --- a/include/editor.h +++ b/include/editor.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "mapconnection.h" #include "metatileselector.h" @@ -45,8 +46,6 @@ public: Settings *settings; void saveProject(); void save(); - void undo(); - void redo(); void closeProject(); bool setMap(QString map_name); void saveUiFields(); @@ -144,6 +143,8 @@ public: int getBorderDrawDistance(int dimension); + QUndoGroup editGroup; // Manages the undo history for each map + private: void setConnectionItemsVisible(bool); void setBorderItemsVisible(bool, qreal = 1); diff --git a/include/mainwindow.h b/include/mainwindow.h index cd04dc7f..c4624efe 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -121,8 +121,6 @@ private slots: void on_action_Save_Project_triggered(); void openWarpMap(QString map_name, QString warp_num); - void undo(); - void redo(); void duplicate(); void openInTextEditor(); @@ -157,9 +155,6 @@ private slots: void on_mainTabBar_tabBarClicked(int index); - void on_actionUndo_triggered(); - void on_actionRedo_triggered(); - void on_actionZoom_In_triggered(); void on_actionZoom_Out_triggered(); void on_actionBetter_Cursors_triggered(); @@ -252,6 +247,9 @@ private: QIcon* mapEditedIcon; QIcon* mapOpenedIcon; + QAction *undoAction; + QAction *redoAction; + QWidget *eventTabObjectWidget; QWidget *eventTabWarpWidget; QWidget *eventTabTriggerWidget; diff --git a/include/ui/bordermetatilespixmapitem.h b/include/ui/bordermetatilespixmapitem.h index 11aae827..870c975e 100644 --- a/include/ui/bordermetatilespixmapitem.h +++ b/include/ui/bordermetatilespixmapitem.h @@ -10,11 +10,12 @@ class BorderMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem { public: BorderMetatilesPixmapItem(Map *map_, MetatileSelector *metatileSelector) { this->map = map_; + this->map->setBorderItem(this); this->metatileSelector = metatileSelector; setAcceptHoverEvents(true); } MetatileSelector *metatileSelector; - Map* map; + Map *map; void draw(); signals: void borderMetatilesChanged(); diff --git a/include/ui/mappixmapitem.h b/include/ui/mappixmapitem.h index 4ee10e56..fc9bfd2b 100644 --- a/include/ui/mappixmapitem.h +++ b/include/ui/mappixmapitem.h @@ -20,6 +20,7 @@ public: }; MapPixmapItem(Map *map_, MetatileSelector *metatileSelector, Settings *settings) { this->map = map_; + this->map->setMapItem(this); this->metatileSelector = metatileSelector; this->settings = settings; this->paintingMode = PaintMode::Metatiles; @@ -68,6 +69,8 @@ private: void paintSmartPath(int x, int y, bool fromScriptCall = false); static QList smartPathTable; + unsigned eventId_ = 0; + signals: void startPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *); void endPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *); diff --git a/porymap.pro b/porymap.pro index 0f600695..2f411ed4 100644 --- a/porymap.pro +++ b/porymap.pro @@ -30,6 +30,7 @@ SOURCES += src/core/block.cpp \ src/core/tileset.cpp \ src/core/regionmap.cpp \ src/core/wildmoninfo.cpp \ + src/core/editcommands.cpp \ src/lib/orderedjson.cpp \ src/mainwindow_scriptapi.cpp \ src/ui/aboutporymap.cpp \ @@ -95,6 +96,7 @@ HEADERS += include/core/block.h \ include/core/tileset.h \ include/core/regionmap.h \ include/core/wildmoninfo.h \ + include/core/editcommands.h \ include/lib/orderedmap.h \ include/lib/orderedjson.h \ include/ui/aboutporymap.h \ diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp new file mode 100644 index 00000000..8c492aed --- /dev/null +++ b/src/core/editcommands.cpp @@ -0,0 +1,268 @@ +#include "editcommands.h" +#include "mappixmapitem.h" +#include "bordermetatilespixmapitem.h" + +#include + + + +PaintMetatile::PaintMetatile(Map *map, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + unsigned eventId, QUndoCommand *parent) : QUndoCommand(parent) { + setText("Paint Metatiles"); + + this->map = map; + this->oldMetatiles = oldMetatiles; + this->newMetatiles = newMetatiles; + + this->eventId = eventId; +} + +PaintMetatile::~PaintMetatile() { + if (newMetatiles) delete newMetatiles; + if (oldMetatiles) delete oldMetatiles; +} + +void PaintMetatile::redo() { + QUndoCommand::redo(); + + if (!map) return; + + if (map->layout->blockdata) { + map->layout->blockdata->copyFrom(newMetatiles); + } + + map->mapItem->draw(); +} + +void PaintMetatile::undo() { + if (!map) return; + + if (map->layout->blockdata) { + map->layout->blockdata->copyFrom(oldMetatiles); + } + + map->mapItem->draw(); + + QUndoCommand::undo(); +} + +bool PaintMetatile::mergeWith(const QUndoCommand *command) { + // does an up merge + const PaintMetatile *other = static_cast(command); + + if (this->map != other->map) + return false; + + if (eventId != other->eventId) + return false; + + this->newMetatiles->copyFrom(other->newMetatiles); + + return true; +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +PaintBorder::PaintBorder(Map *map, + Blockdata *oldBorder, Blockdata *newBorder, + unsigned eventId, QUndoCommand *parent) : QUndoCommand(parent) { + setText("Paint Border"); + + this->map = map; + this->oldBorder = oldBorder; + this->newBorder = newBorder; + + this->eventId = eventId; +} + +PaintBorder::~PaintBorder() { + if (newBorder) delete newBorder; + if (oldBorder) delete oldBorder; +} + +void PaintBorder::redo() { + QUndoCommand::redo(); + + if (!map) return; + + if (map->layout->border) { + map->layout->border->copyFrom(newBorder); + } + + map->borderItem->draw(); +} + +void PaintBorder::undo() { + if (!map) return; + + if (map->layout->border) { + map->layout->border->copyFrom(oldBorder); + } + + map->borderItem->draw(); + + QUndoCommand::undo(); +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +BucketFillMetatile::BucketFillMetatile(Map *map, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + unsigned eventId, QUndoCommand *parent) + : PaintMetatile(map, oldMetatiles, newMetatiles, eventId, parent) { + setText("Bucket Fill Metatiles"); +} + +BucketFillMetatile::~BucketFillMetatile() { + PaintMetatile::~PaintMetatile(); +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +MagicFillMetatile::MagicFillMetatile(Map *map, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + unsigned eventId, QUndoCommand *parent) + : PaintMetatile(map, oldMetatiles, newMetatiles, eventId, parent) { + setText("Magic Fill Metatiles"); +} + +MagicFillMetatile::~MagicFillMetatile() { + PaintMetatile::~PaintMetatile(); +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +ShiftMetatiles::ShiftMetatiles(Map *map, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + unsigned eventId, QUndoCommand *parent) : QUndoCommand(parent) { + setText("Shift Metatiles"); + + this->map = map; + this->oldMetatiles = oldMetatiles; + this->newMetatiles = newMetatiles; + + this->eventId = eventId; +} + +ShiftMetatiles::~ShiftMetatiles() { + if (newMetatiles) delete newMetatiles; + if (oldMetatiles) delete oldMetatiles; +} + +void ShiftMetatiles::redo() { + QUndoCommand::redo(); + + if (!map) return; + + if (map->layout->blockdata) { + map->layout->blockdata->copyFrom(newMetatiles); + } + + map->mapItem->draw(true); +} + +void ShiftMetatiles::undo() { + if (!map) return; + + if (map->layout->blockdata) { + map->layout->blockdata->copyFrom(oldMetatiles); + } + + map->mapItem->draw(true); + + QUndoCommand::undo(); +} + +bool ShiftMetatiles::mergeWith(const QUndoCommand *command) { + const ShiftMetatiles *other = static_cast(command); + + if (this->map != other->map) + return false; + + if (eventId != other->eventId) + return false; + + this->newMetatiles->copyFrom(other->newMetatiles); + + return true; +} + +/****************************************************************************** + ************************************************************************ + ******************************************************************************/ + +ResizeMap::ResizeMap(Map *map, QSize oldMapDimensions, QSize newMapDimensions, + Blockdata *oldMetatiles, Blockdata *newMetatiles, + QSize oldBorderDimensions, QSize newBorderDimensions, + Blockdata *oldBorder, Blockdata *newBorder, + QUndoCommand *parent) : QUndoCommand(parent) { + setText("Resize Map"); + + this->map = map; + + this->oldMapWidth = oldMapDimensions.width(); + this->oldMapHeight = oldMapDimensions.height(); + + this->newMapWidth = newMapDimensions.width(); + this->newMapHeight = newMapDimensions.height(); + + this->oldMetatiles = oldMetatiles; + this->newMetatiles = newMetatiles; + + this->oldBorderWidth = oldBorderDimensions.width(); + this->oldBorderHeight = oldBorderDimensions.height(); + + this->newBorderWidth = newBorderDimensions.width(); + this->newBorderHeight = newBorderDimensions.height(); + + this->oldBorder = oldBorder; + this->newBorder = newBorder; +} + +ResizeMap::~ResizeMap() { + if (newMetatiles) delete newMetatiles; + if (oldMetatiles) delete oldMetatiles; +} + +void ResizeMap::redo() { + QUndoCommand::redo(); + + if (!map) return; + + if (map->layout->blockdata) { + map->layout->blockdata->copyFrom(newMetatiles); + map->setDimensions(newMapWidth, newMapHeight, false); + } + + if (map->layout->border) { + map->layout->border->copyFrom(newBorder); + map->setBorderDimensions(newBorderWidth, newBorderHeight, false); + } +} + +void ResizeMap::undo() { + if (!map) return; + + if (map->layout->blockdata) { + map->layout->blockdata->copyFrom(oldMetatiles); + map->setDimensions(oldMapWidth, oldMapHeight, false); + } + + if (map->layout->border) { + map->layout->border->copyFrom(oldBorder); + map->setBorderDimensions(oldBorderWidth, oldBorderHeight, false); + } + + QUndoCommand::undo(); +} + + diff --git a/src/core/map.cpp b/src/core/map.cpp index 2e365b81..d21a38de 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -4,6 +4,8 @@ #include "imageproviders.h" #include "scripting.h" +#include "editcommands.h" + #include #include #include @@ -343,6 +345,7 @@ void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata) { layout->height = QString::number(newHeight); emit mapChanged(this); + emit mapNeedsRedrawing(); } void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata) { @@ -354,6 +357,7 @@ void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata) layout->border_height = QString::number(newHeight); emit mapChanged(this); + emit mapNeedsRedrawing(); } Block* Map::getBlock(int x, int y) { @@ -413,93 +417,8 @@ void Map::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_ } } -void Map::undo() { - bool redraw = false, changed = false; - HistoryItem *commit = metatileHistory.back(); - if (!commit) - return; - - if (layout->blockdata) { - layout->blockdata->copyFrom(commit->metatiles); - if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight()) { - this->setDimensions(commit->layoutWidth, commit->layoutHeight, false); - redraw = true; - } - changed = true; - } - if (layout->border) { - layout->border->copyFrom(commit->border); - if (commit->borderWidth != this->getBorderWidth() || commit->borderHeight != this->getBorderHeight()) { - this->setBorderDimensions(commit->borderWidth, commit->borderHeight, false); - redraw = true; - } - changed = true; - } - - if (redraw) { - emit mapNeedsRedrawing(); - } - if (changed) { - emit mapChanged(this); - } -} - -void Map::redo() { - bool redraw = false, changed = false; - HistoryItem *commit = metatileHistory.next(); - if (!commit) - return; - - if (layout->blockdata) { - layout->blockdata->copyFrom(commit->metatiles); - if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight()) { - this->setDimensions(commit->layoutWidth, commit->layoutHeight, false); - redraw = true; - } - changed = true; - } - if (layout->border) { - layout->border->copyFrom(commit->border); - if (commit->borderWidth != this->getBorderWidth() || commit->borderHeight != this->getBorderHeight()) { - this->setBorderDimensions(commit->borderWidth, commit->borderHeight, false); - redraw = true; - } - changed = true; - } - - if (redraw) { - emit mapNeedsRedrawing(); - } - if (changed) { - emit mapChanged(this); - } -} - void Map::commit() { - if (!layout) { - return; - } - - int layoutWidth = this->getWidth(); - int layoutHeight = this->getHeight(); - int borderWidth = this->getBorderWidth(); - int borderHeight = this->getBorderHeight(); - - if (layout->blockdata) { - HistoryItem *item = metatileHistory.current(); - bool atCurrentHistory = item - && layout->blockdata->equals(item->metatiles) - && layout->border->equals(item->border) - && layoutWidth == item->layoutWidth - && layoutHeight == item->layoutHeight - && borderWidth == item->borderWidth - && borderHeight == item->borderHeight; - if (!atCurrentHistory) { - HistoryItem *commit = new HistoryItem(layout->blockdata->copy(), layout->border->copy(), layoutWidth, layoutHeight, borderWidth, borderHeight); - metatileHistory.push(commit); - emit mapChanged(this); - } - } + return; } void Map::floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) { diff --git a/src/editor.cpp b/src/editor.cpp index 505d7699..5f85242c 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -53,26 +53,6 @@ void Editor::saveUiFields() { saveEncounterTabData(); } -void Editor::undo() { - if (current_view && map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) { - map->undo(); - map_item->draw(); - collision_item->draw(); - selected_border_metatiles_item->draw(); - onBorderMetatilesChanged(); - } -} - -void Editor::redo() { - if (current_view && map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) { - map->redo(); - map_item->draw(); - collision_item->draw(); - selected_border_metatiles_item->draw(); - onBorderMetatilesChanged(); - } -} - void Editor::closeProject() { if (this->project) { delete this->project; @@ -981,6 +961,9 @@ bool Editor::setMap(QString map_name) { } map = loadedMap; + + editGroup.addStack(&map->editHistory); + editGroup.setActiveStack(&map->editHistory); selected_events->clear(); if (!displayMap()) { return false; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e39c534f..d1a7c6e4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -11,6 +11,7 @@ #include "customattributestable.h" #include "scripting.h" #include "adjustingstackedwidget.h" +#include "editcommands.h" #include #include @@ -146,6 +147,21 @@ void MainWindow::initEditor() { connect(this->editor, &Editor::wheelZoom, this, &MainWindow::onWheelZoom); this->loadUserSettings(); + + undoAction = editor->editGroup.createUndoAction(this, tr("&Undo")); + undoAction->setShortcut(QKeySequence("Ctrl+Z")); + + redoAction = editor->editGroup.createRedoAction(this, tr("&Redo")); + redoAction->setShortcut(QKeySequence("Ctrl+Y")); + + ui->menuEdit->addAction(undoAction); + ui->menuEdit->addAction(redoAction); + + // TODO: show history UndoView here + QUndoView *undoView = new QUndoView(&editor->editGroup); + undoView->setWindowTitle(tr("Edit History")); + undoView->show(); + undoView->setAttribute(Qt::WA_QuitOnClose, false); } void MainWindow::initMiscHeapObjects() { @@ -1255,14 +1271,6 @@ void MainWindow::on_action_Save_Project_triggered() updateMapList(); } -void MainWindow::undo() { - editor->undo(); -} - -void MainWindow::redo() { - editor->redo(); -} - void MainWindow::duplicate() { editor->duplicateSelectedEvents(); } @@ -1322,16 +1330,6 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index) } } -void MainWindow::on_actionUndo_triggered() -{ - undo(); -} - -void MainWindow::on_actionRedo_triggered() -{ - redo(); -} - void MainWindow::on_actionZoom_In_triggered() { scaleMapView(1); } @@ -2498,10 +2496,23 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() form.addRow(errorLabel); if (dialog.exec() == QDialog::Accepted) { - editor->map->setDimensions(widthSpinBox->value(), heightSpinBox->value()); - editor->map->setBorderDimensions(bwidthSpinBox->value(), bheightSpinBox->value()); - editor->map->commit(); - onMapNeedsRedrawing(); + Map *map = editor->map; + Blockdata *oldMetatiles = map->layout->blockdata->copy(); + Blockdata *oldBorder = map->layout->border->copy(); + QSize oldMapDimensions(map->getWidth(), map->getHeight()); + QSize oldBorderDimensions(map->getBorderWidth(), map->getBorderHeight()); + QSize newMapDimensions(widthSpinBox->value(), heightSpinBox->value()); + QSize newBorderDimensions(bwidthSpinBox->value(), bheightSpinBox->value()); + if (oldMapDimensions != newMapDimensions || oldBorderDimensions != newBorderDimensions) { + editor->map->setDimensions(newMapDimensions.width(), newMapDimensions.height()); + editor->map->setBorderDimensions(newBorderDimensions.width(), newBorderDimensions.height()); + editor->map->editHistory.push(new ResizeMap(map, + oldMapDimensions, newMapDimensions, + oldMetatiles, map->layout->blockdata->copy(), + oldBorderDimensions, newBorderDimensions, + oldBorder, map->layout->border->copy() + )); + } } } diff --git a/src/ui/bordermetatilespixmapitem.cpp b/src/ui/bordermetatilespixmapitem.cpp index 4ecd9130..20c67aae 100644 --- a/src/ui/bordermetatilespixmapitem.cpp +++ b/src/ui/bordermetatilespixmapitem.cpp @@ -1,5 +1,6 @@ #include "bordermetatilespixmapitem.h" #include "imageproviders.h" +#include "editcommands.h" #include void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { @@ -11,6 +12,8 @@ void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) int width = map->getBorderWidth(); int height = map->getBorderHeight(); + Blockdata *oldBorder = map->layout->border->copy(); + for (int i = 0; i < selectionDimensions.x() && (i + x) < width; i++) { for (int j = 0; j < selectionDimensions.y() && (j + y) < height; j++) { int blockIndex = (j + y) * width + (i + x); @@ -19,11 +22,15 @@ void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) } } - draw(); + Blockdata *newBorder = map->layout->border->copy(); + map->editHistory.push(new PaintBorder(map, oldBorder, newBorder, 0)); + emit borderMetatilesChanged(); } void BorderMetatilesPixmapItem::draw() { + map->setBorderItem(this); + int width = map->getBorderWidth(); int height = map->getBorderHeight(); QImage image(16 * width, 16 * height, QImage::Format_RGBA8888); @@ -49,4 +56,6 @@ void BorderMetatilesPixmapItem::draw() { painter.end(); map->commit(); this->setPixmap(QPixmap::fromImage(image)); + + emit borderMetatilesChanged(); } diff --git a/src/ui/mappixmapitem.cpp b/src/ui/mappixmapitem.cpp index 7fec4421..d6914286 100644 --- a/src/ui/mappixmapitem.cpp +++ b/src/ui/mappixmapitem.cpp @@ -1,12 +1,14 @@ #include "mappixmapitem.h" #include "log.h" +#include "editcommands.h" + #define SWAP(a, b) do { if (a != b) { a ^= b; b ^= a; a ^= b; } } while (0) void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) { if (map) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { - map->commit(); + eventId_++; } else { QPointF pos = event->pos(); int x = static_cast(pos.x()) / 16; @@ -21,15 +23,13 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) { paintNormal(x, y); } } - - draw(); } } void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) { if (map) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { - map->commit(); + eventId_++; } else { QPointF pos = event->pos(); int x = static_cast(pos.x()) / 16; @@ -70,7 +70,9 @@ void MapPixmapItem::shift(int xDelta, int yDelta) { map->setBlock(destX, destY, srcBlock); } - delete backupBlockdata; + Blockdata *newMetatiles = map->layout->blockdata->copy(); + ShiftMetatiles *paintEvent = new ShiftMetatiles(map, backupBlockdata, newMetatiles, eventId_); + map->editHistory.push(paintEvent); } void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) { @@ -90,6 +92,9 @@ void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) { x = initialX + (xDiff / selectionDimensions.x()) * selectionDimensions.x(); y = initialY + (yDiff / selectionDimensions.y()) * selectionDimensions.y(); + // for edit history + Blockdata *oldMetatiles = map->layout->blockdata->copy(); + for (int i = 0; i < selectionDimensions.x() && i + x < map->getWidth(); i++) for (int j = 0; j < selectionDimensions.y() && j + y < map->getHeight(); j++) { int actualX = i + x; @@ -105,6 +110,10 @@ void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) { map->setBlock(actualX, actualY, *block, !fromScriptCall); } } + + Blockdata *newMetatiles = map->layout->blockdata->copy(); + PaintMetatile *paintEvent = new PaintMetatile(map, oldMetatiles, newMetatiles, eventId_); + map->editHistory.push(paintEvent); } // These are tile offsets from the top-left tile in the 3x3 smart path selection. @@ -150,6 +159,9 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) { setCollisions = true; } + // for edit history + Blockdata *oldMetatiles = map->layout->blockdata->copy(); + // Fill the region with the open tile. for (int i = 0; i <= 1; i++) for (int j = 0; j <= 1; j++) { @@ -211,6 +223,10 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) { } map->setBlock(actualX, actualY, *block, !fromScriptCall); } + + Blockdata *newMetatiles = map->layout->blockdata->copy(); + PaintMetatile *paintEvent = new PaintMetatile(map, oldMetatiles, newMetatiles, eventId_); + map->editHistory.push(paintEvent); } void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) { @@ -263,7 +279,7 @@ void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) { void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { if (map) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { - map->commit(); + eventId_++; } else { QPointF pos = event->pos(); int x = static_cast(pos.x()) / 16; @@ -280,23 +296,19 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { this->floodFill(x, y); } } - - draw(); } } void MapPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) { if (map) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { - map->commit(); + eventId_++; } else { QPointF pos = event->pos(); int initialX = static_cast(pos.x()) / 16; int initialY = static_cast(pos.y()) / 16; this->magicFill(initialX, initialY); } - - draw(); } } @@ -327,6 +339,8 @@ void MapPixmapItem::magicFill( return; } + Blockdata *oldMetatiles = map->layout->blockdata->copy(); + bool setCollisions = selectedCollisions && selectedCollisions->length() == selectedMetatiles->length(); uint16_t tile = block->tile; for (int y = 0; y < map->getHeight(); y++) { @@ -349,6 +363,10 @@ void MapPixmapItem::magicFill( } } } + + Blockdata *newMetatiles = map->layout->blockdata->copy(); + MagicFillMetatile *paintEvent = new MagicFillMetatile(map, oldMetatiles, newMetatiles, eventId_); + map->editHistory.push(paintEvent); } } @@ -379,6 +397,8 @@ void MapPixmapItem::floodFill( for (int i = 0; i < numMetatiles; i++) visited[i] = false; + Blockdata *oldMetatiles = map->layout->blockdata->copy(); + QList todo; todo.append(QPoint(initialX, initialY)); while (todo.length()) { @@ -427,6 +447,10 @@ void MapPixmapItem::floodFill( } } + Blockdata *newMetatiles = map->layout->blockdata->copy(); + BucketFillMetatile *paintEvent = new BucketFillMetatile(map, oldMetatiles, newMetatiles, eventId_); + map->editHistory.push(paintEvent); + delete[] visited; } @@ -449,6 +473,8 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri setCollisions = true; } + Blockdata *oldMetatiles = map->layout->blockdata->copy(); + // Flood fill the region with the open tile. QList todo; todo.append(QPoint(initialX, initialY)); @@ -548,6 +574,10 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri } } + Blockdata *newMetatiles = map->layout->blockdata->copy(); + BucketFillMetatile *paintEvent = new BucketFillMetatile(map, oldMetatiles, newMetatiles, eventId_); + map->editHistory.push(paintEvent); + delete[] visited; } @@ -595,6 +625,7 @@ void MapPixmapItem::select(QGraphicsSceneMouseEvent *event) { void MapPixmapItem::draw(bool ignoreCache) { if (map) { + map->setMapItem(this); setPixmap(map->render(ignoreCache)); } }