create edit history for region map tilemap and layout

This commit is contained in:
garak
2022-04-26 17:02:03 -04:00
committed by garakmon
parent 43ebeb1662
commit 2b152ce64e
9 changed files with 152 additions and 176 deletions

View File

@@ -4,6 +4,7 @@
#include "project.h"
#include "log.h"
#include "config.h"
#include "regionmapeditcommands.h"
#include <QByteArray>
#include <QFile>
@@ -163,7 +164,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
layout.append(square);
}
}
this->layouts["main"] = layout;
setLayout("main", layout);
break;
}
case LayoutFormat::CArray:
@@ -226,7 +227,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
}
y++;
}
this->layouts[layerName] = layout;
setLayout(layerName, layout);
}
} else {
@@ -241,13 +242,23 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
return !errored;
}
void RegionMap::save() {
logInfo("Saving region map data.");
void RegionMap::commit(QUndoCommand *command) {
editHistory.push(command);
}
void RegionMap::undo() {
//
editHistory.undo();
}
void RegionMap::redo() {
//
editHistory.redo();
}
void RegionMap::save() {
saveTilemap();
saveLayout();
// TODO
}
void RegionMap::saveTilemap() {
@@ -320,18 +331,19 @@ void RegionMap::saveOptions(int id, QString sec, QString name, int x, int y) {
}
void RegionMap::resetSquare(int index) {
// TODO
this->layouts[this->current_layer][index].map_section = "MAPSEC_NONE";
this->layouts[this->current_layer][index].has_map = false;
}
void RegionMap::clearLayout() {
// TODO
for (int i = 0; i < this->layout_width * this->layout_height; i++) {
resetSquare(i);
}
}
void RegionMap::clearImage() {
// TODO
QByteArray zeros(this->tilemapSize(), 0);
this->setTilemap(zeros);
}
void RegionMap::replaceSectionId(unsigned oldId, unsigned newId) {
@@ -404,8 +416,17 @@ void RegionMap::setTilemap(QByteArray newTilemap) {
}
}
QList<LayoutSquare> RegionMap::getLayout(QString layer) {
return this->layouts[layer];
}
void RegionMap::setLayout(QString layer, QList<LayoutSquare> layout) {
this->layouts[layer] = layout;
}
QVector<uint8_t> RegionMap::getTiles() {
QVector<uint8_t> tileIds;
// unused? remove when redo history is fully transitioned
// TODO: change this to use TilemapTile instead of uint8_t
return tileIds;
@@ -423,7 +444,7 @@ int RegionMap::get_tilemap_index(int x, int y) {
// Layout coords to layout index.
int RegionMap::get_layout_index(int x, int y) {
return x + y * this->tilemap_width;
return x + y * this->layout_width;
}
unsigned RegionMap::getTileId(int index) {
@@ -526,7 +547,7 @@ MapSectionEntry RegionMap::getEntry(QString section) {
}
QString RegionMap::palPath() {
return this->project->root + "/" + this->palette_path;
return this->palette_path.isEmpty() ? QString() : this->project->root + "/" + this->palette_path;
}
QString RegionMap::pngPath() {

View File

@@ -1,6 +1,7 @@
#include "regionmapeditor.h"
#include "ui_regionmapeditor.h"
#include "regionmappropertiesdialog.h"
#include "regionmapeditcommands.h"
#include "imageexport.h"
#include "shortcut.h"
#include "config.h"
@@ -36,6 +37,11 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project_) :
RegionMapEditor::~RegionMapEditor()
{
delete ui;
// deletion must be done in this order else crashes
auto stacks = this->history.stacks();
for (auto *stack : stacks) {
this->history.removeStack(stack);
}
for (auto p : this->region_maps) {
delete p.second;
}
@@ -64,6 +70,21 @@ void RegionMapEditor::initShortcuts() {
shortcut_RM_Options_delete->setObjectName("shortcut_RM_Options_delete");
shortcut_RM_Options_delete->setWhatsThis("Map Layout: Delete Square");
QAction *undoAction = this->history.createUndoAction(this, tr("&Undo"));
undoAction->setObjectName("action_RegionMap_Undo");
undoAction->setShortcut(QKeySequence("Ctrl+Z"));
QAction *redoAction = this->history.createRedoAction(this, tr("&Redo"));
redoAction->setObjectName("action_RegionMap_Redo");
redoAction->setShortcuts({QKeySequence("Ctrl+Y"), QKeySequence("Ctrl+Shift+Z")});
ui->menuEdit->addAction(undoAction);
ui->menuEdit->addAction(redoAction);
connect(&(this->history), &QUndoGroup::indexChanged, [this](int) {
on_tabWidget_Region_Map_currentChanged(this->ui->tabWidget_Region_Map->currentIndex());
});
shortcutsConfig.load();
shortcutsConfig.setDefaultShortcuts(shortcutableObjects());
applyUserShortcuts();
@@ -409,6 +430,8 @@ bool RegionMapEditor::load() {
newMap->loadMapData(o);
region_maps[alias] = newMap;
this->history.addStack(&(newMap->editHistory));
}
// add to ui
@@ -420,6 +443,7 @@ bool RegionMapEditor::load() {
if (!region_maps.empty()) {
this->region_map = region_maps.begin()->second;
this->currIndex = this->region_map->firstLayoutIndex();
this->region_map->editHistory.setActive();
displayRegionMap();
}
@@ -477,11 +501,14 @@ void RegionMapEditor::on_comboBox_regionSelector_textActivated(const QString &re
//
if (this->region_maps.contains(region)) {
this->region_map = region_maps.at(region);
this->region_map->editHistory.setActive();
this->currIndex = this->region_map->firstLayoutIndex();
// TODO: make the above into a function that takes an alias string? in case there is more to it
// TODO: anything else needed here?
displayRegionMap();
//this->editGroup.setActiveStack(&(this->region_map->editHistory));
}
}
@@ -510,15 +537,6 @@ void RegionMapEditor::displayRegionMapImage() {
this->ui->graphicsView_Region_Map_BkgImg->setScene(this->scene_region_map_image);
on_verticalSlider_Zoom_Map_Image_valueChanged(this->ui->verticalSlider_Zoom_Map_Image->value());
// if (regionMapFirstDraw) {
// on_verticalSlider_Zoom_Map_Image_valueChanged(this->ui->verticalSlider_Zoom_Map_Image->value());
// RegionMapHistoryItem *commit = new RegionMapHistoryItem(
// RegionMapEditorBox::BackgroundImage, this->region_map->getTiles(), this->region_map->tilemapWidth(), this->region_map->height()
// );
// history.push(commit);
// regionMapFirstDraw = false;
// }
}
void RegionMapEditor::displayRegionMapLayout() {
@@ -670,6 +688,8 @@ void RegionMapEditor::displayRegionMapTileSelector() {
this->ui->graphicsView_RegionMap_Tiles->setScene(this->scene_region_map_tiles);
on_verticalSlider_Zoom_Image_Tiles_valueChanged(this->ui->verticalSlider_Zoom_Image_Tiles->value());
this->ui->frame_tileOptions->setEnabled(this->region_map->tilemapFormat() != TilemapFormat::Plain);
this->mapsquare_selector_item->select(this->selectedImageTile);
}
@@ -842,21 +862,9 @@ void RegionMapEditor::mouseEvent_region_map(QGraphicsSceneMouseEvent *event, Reg
item->select(event);
//} else if (event->buttons() & Qt::MiddleButton) {// TODO
} else {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
//< TODO: history
// RegionMapHistoryItem *current = history.current();
// bool addToHistory = !(current && current->tiles == this->region_map->getTiles());
// if (addToHistory) {
// RegionMapHistoryItem *commit = new RegionMapHistoryItem(
// RegionMapEditorBox::BackgroundImage, this->region_map->getTiles(), this->region_map->width(), this->region_map->height()
// );
// history.push(commit);
// }
} else {
item->paint(event);
this->region_map_layout_item->draw();
this->hasUnsavedChanges = true;
}
item->paint(event);
this->region_map_layout_item->draw();
this->hasUnsavedChanges = true;
}
}
@@ -894,15 +902,20 @@ void RegionMapEditor::mouseEvent_city_map(QGraphicsSceneMouseEvent *event, CityM
void RegionMapEditor::on_tabWidget_Region_Map_currentChanged(int index) {
this->ui->stackedWidget_RM_Options->setCurrentIndex(index);
if (!region_map) return;
switch (index)
{
case 0:
this->ui->verticalSlider_Zoom_Image_Tiles->setVisible(true);
this->region_map_item->draw();
if (this->region_map_item)
this->region_map_item->draw();
break;
case 1:
this->ui->verticalSlider_Zoom_Image_Tiles->setVisible(false);
this->region_map_layout_item->draw();
if (this->region_map_layout_item) {
this->region_map_layout_item->draw();
updateRegionMapLayoutOptions(this->currIndex);
}
break;
case 2:
this->ui->verticalSlider_Zoom_Image_Tiles->setVisible(false);
@@ -912,9 +925,17 @@ void RegionMapEditor::on_tabWidget_Region_Map_currentChanged(int index) {
}
void RegionMapEditor::on_comboBox_RM_ConnectedMap_textActivated(const QString &mapsec) {
QString layer = this->region_map->getLayer();
QList<LayoutSquare> oldLayout = this->region_map->getLayout(layer);
this->region_map->setSquareMapSection(this->currIndex, mapsec);
onRegionMapLayoutSelectedTileChanged(this->currIndex);// re-draw layout image
QList<LayoutSquare> newLayout = this->region_map->getLayout(layer);
EditLayout *command = new EditLayout(this->region_map, layer, this->currIndex, oldLayout, newLayout);
this->region_map->commit(command);
this->hasUnsavedChanges = true;// TODO: sometimes this is called for unknown reasons
onRegionMapLayoutSelectedTileChanged(this->currIndex);// re-draw layout image
}
void RegionMapEditor::on_comboBox_RM_Entry_MapSection_textActivated(const QString &text) {
@@ -988,10 +1009,21 @@ void RegionMapEditor::on_lineEdit_RM_MapName_textEdited(const QString &text) {
}
void RegionMapEditor::on_pushButton_RM_Options_delete_clicked() {
this->region_map->resetSquare(this->region_map_layout_item->selectedTile);
updateRegionMapLayoutOptions(this->region_map_layout_item->selectedTile);
// TODO: crashing
int index = this->region_map->tilemapToLayoutIndex(this->currIndex);
QList<LayoutSquare> oldLayout = this->region_map->getLayout(this->region_map->getLayer());
//this->region_map->resetSquare(this->region_map_layout_item->selectedTile);
this->region_map->resetSquare(index);
QList<LayoutSquare> newLayout = this->region_map->getLayout(this->region_map->getLayer());
EditLayout *commit = new EditLayout(this->region_map, this->region_map->getLayer(), this->currIndex, oldLayout, newLayout);
commit->setText("Reset Layout Square");
this->region_map->editHistory.push(commit);
//updateRegionMapLayoutOptions(this->region_map_layout_item->selectedTile);
updateRegionMapLayoutOptions(this->currIndex);
this->region_map_layout_item->draw();
this->region_map_layout_item->select(this->region_map_layout_item->selectedTile);
//this->region_map_layout_item->select(this->region_map_layout_item->selectedTile);
this->region_map_layout_item->select(this->currIndex);
// ^ this line necessary?
this->hasUnsavedChanges = true;
}
@@ -1082,63 +1114,6 @@ void RegionMapEditor::on_action_RegionMap_Resize_triggered() {
return;
}
void RegionMapEditor::on_action_RegionMap_Undo_triggered() {
//< TODO: edit history
undo();
this->hasUnsavedChanges = true;
}
void RegionMapEditor::undo() {
//< TODO: edit history
RegionMapHistoryItem *commit = history.back();
if (!commit) return;
switch (commit->which)
{
case RegionMapEditorBox::BackgroundImage:
//if (commit->mapWidth != this->region_map->width() || commit->mapHeight != this->region_map->height())
// this->resize(commit->mapWidth, commit->mapHeight);
this->region_map->setTiles(commit->tiles);
this->region_map_item->draw();
this->region_map_layout_item->draw();
this->region_map_entries_item->draw();
break;
case RegionMapEditorBox::CityMapImage:
//< if (commit->cityMap == this->city_map_item->file)
//< this->city_map_item->setTiles(commit->tiles);
//< this->city_map_item->draw();
break;
}
}
void RegionMapEditor::on_action_RegionMap_Redo_triggered() {
//< TODO: edit history
redo();
this->hasUnsavedChanges = true;
}
void RegionMapEditor::redo() {
//< TODO: edit history
RegionMapHistoryItem *commit = history.next();
if (!commit) return;
switch (commit->which)
{
case RegionMapEditorBox::BackgroundImage:
//if (commit->mapWidth != this->region_map->width() || commit->mapHeight != this->region_map->height())
// this->resize(commit->mapWidth, commit->mapHeight);
this->region_map->setTiles(commit->tiles);
this->region_map_item->draw();
this->region_map_layout_item->draw();
this->region_map_entries_item->draw();
break;
case RegionMapEditorBox::CityMapImage:
//< this->city_map_item->setTiles(commit->tiles);
//< this->city_map_item->draw();
break;
}
}
void RegionMapEditor::resize(int w, int h) {
this->region_map->resize(w, h);
this->currIndex = this->region_map->padLeft() * w + this->region_map->padTop();
@@ -1189,11 +1164,13 @@ void RegionMapEditor::on_action_Swap_triggered() {
}
void RegionMapEditor::on_action_RegionMap_ClearImage_triggered() {
QByteArray oldTilemap = this->region_map->getTilemap();
this->region_map->clearImage();
RegionMapHistoryItem *commit = new RegionMapHistoryItem(
RegionMapEditorBox::BackgroundImage, this->region_map->getTiles(), this->region_map->tilemapWidth(), this->region_map->tilemapHeight()
);
history.push(commit);
QByteArray newTilemap = this->region_map->getTilemap();
EditTilemap *commit = new EditTilemap(this->region_map, oldTilemap, newTilemap, -1);
commit->setText("Clear Tilemap");
this->region_map->editHistory.push(commit);
displayRegionMapImage();
displayRegionMapLayout();
@@ -1209,7 +1186,12 @@ void RegionMapEditor::on_action_RegionMap_ClearLayout_triggered() {
);
if (result == QMessageBox::Yes) {
QList<LayoutSquare> oldLayout = this->region_map->getLayout(this->region_map->getLayer());
this->region_map->clearLayout();
QList<LayoutSquare> newLayout = this->region_map->getLayout(this->region_map->getLayer());
EditLayout *commit = new EditLayout(this->region_map, this->region_map->getLayer(), -1, oldLayout, newLayout);
commit->setText("Clear Layout");
this->region_map->editHistory.push(commit);
displayRegionMapLayout();
} else {
return;

View File

@@ -1,4 +1,7 @@
#include "regionmappixmapitem.h"
#include "regionmapeditcommands.h"
static unsigned actionId_ = 0;
void RegionMapPixmapItem::draw() {
if (!region_map) return;
@@ -20,17 +23,25 @@ void RegionMapPixmapItem::draw() {
void RegionMapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
if (region_map) {
QPointF pos = event->pos();
int x = static_cast<int>(pos.x()) / 8;
int y = static_cast<int>(pos.y()) / 8;
int index = x + y * region_map->tilemapWidth();
this->region_map->setTileData(index,
this->tile_selector->selectedTile,
this->tile_selector->tile_hFlip,
this->tile_selector->tile_vFlip,
this->tile_selector->tile_palette
);
draw();
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++;
} else {
QPointF pos = event->pos();
int x = static_cast<int>(pos.x()) / 8;
int y = static_cast<int>(pos.y()) / 8;
int index = x + y * region_map->tilemapWidth();
QByteArray oldTilemap = this->region_map->getTilemap();
this->region_map->setTileData(index,
this->tile_selector->selectedTile,
this->tile_selector->tile_hFlip,
this->tile_selector->tile_vFlip,
this->tile_selector->tile_palette
);
QByteArray newTilemap = this->region_map->getTilemap();
EditTilemap *command = new EditTilemap(this->region_map, oldTilemap, newTilemap, actionId_);
this->region_map->commit(command);
draw();
}
}
}

View File

@@ -20,6 +20,7 @@ void TilemapTileSelector::select(unsigned tileId) {
QPoint coords = this->getTileIdCoords(tileId);
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
this->selectedTile = tileId;
this->drawSelection();
emit selectedTileChanged(tileId);
}
@@ -50,11 +51,7 @@ QImage TilemapTileSelector::tileImg(shared_ptr<TilemapTile> tile) {
switch(this->format) {
case TilemapFormat::Plain:
{
// TODO: even allow palettes for Plain tiles?
// 1 x palette x any colors
break;
}
case TilemapFormat::BPP_4:
{
// before Qt 6, the color table is a QVector which is deprecated now, and this method does not exits
@@ -67,10 +64,11 @@ QImage TilemapTileSelector::tileImg(shared_ptr<TilemapTile> tile) {
}
case TilemapFormat::BPP_8:
{
// TODO:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
tilesetImage.setColorTable(this->palette.toVector());
//tilesetImage.setColorTable(this->palette.toVector());
#else
tilesetImage.setColorTable(this->palette);
//tilesetImage.setColorTable(this->palette);
#endif
break;
}