From 18eb3ceb1e7e8ea02dd73b46edb455df49782054 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 1 Feb 2023 20:28:54 -0500 Subject: [PATCH] setLayout to create layout-only edit mode --- include/core/maplayout.h | 2 + include/editor.h | 3 + include/mainwindow.h | 2 +- include/project.h | 1 + include/ui/maplistmodels.h | 4 +- src/core/map.cpp | 3 +- src/core/maplayout.cpp | 4 ++ src/editor.cpp | 107 +++++++++++++++++++++------------ src/mainwindow.cpp | 77 ++++++++++++++++++++++-- src/project.cpp | 13 ++++ src/ui/collisionpixmapitem.cpp | 2 +- src/ui/maplistmodels.cpp | 24 +++++--- 12 files changed, 186 insertions(+), 56 deletions(-) diff --git a/include/core/maplayout.h b/include/core/maplayout.h index 5e7c0f7c..7d4eb500 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -92,6 +92,8 @@ public: void clearBorderCache(); void cacheBorder(); + bool hasUnsavedChanges(); + bool layoutBlockChanged(int i, const Blockdata &cache); uint16_t getBorderMetatileId(int x, int y); diff --git a/include/editor.h b/include/editor.h index 8f12d88f..023451f4 100644 --- a/include/editor.h +++ b/include/editor.h @@ -60,11 +60,14 @@ public: void closeProject(); bool setMap(QString map_name); + bool setLayout(QString layoutName); void unsetMap(); Tileset *getCurrentMapPrimaryTileset(); bool displayMap(); + bool displayLayout(); + void displayMetatileSelector(); void displayMapMetatiles(); void displayMapMovementPermissions(); diff --git a/include/mainwindow.h b/include/mainwindow.h index 18b947f9..7a8b133f 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -357,7 +357,7 @@ private: bool tilesetNeedsRedraw = false; - bool setLayout(QString layoutName); + bool setLayout(QString layoutId); bool setMap(QString, bool scrollTreeView = false); void unsetMap(); diff --git a/include/project.h b/include/project.h index dd2e044b..ddffe49b 100644 --- a/include/project.h +++ b/include/project.h @@ -145,6 +145,7 @@ public: QSet getTopLevelMapFields(); bool loadMapData(Map*); bool readMapLayouts(); + Layout *loadLayout(QString layoutId); bool loadLayout(Layout *); bool loadMapLayout(Map*); bool loadLayoutTilesets(Layout *); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index d15adcd3..166fe79d 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -62,9 +62,9 @@ public: QVariant data(const QModelIndex &index, int role) const override; public: - void setLayout(QString layoutName) { this->openLayout = layoutName; } + void setLayout(QString layoutId) { this->openLayout = layoutId; } - QStandardItem *createLayoutItem(QString layoutName); + QStandardItem *createLayoutItem(QString layoutId); QStandardItem *createMapItem(QString mapName); QStandardItem *getItem(const QModelIndex &index) const; diff --git a/src/core/map.cpp b/src/core/map.cpp index fdfb030c..ee7a1884 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -154,5 +154,6 @@ void Map::clean() { } bool Map::hasUnsavedChanges() { - return !editHistory.isClean() /* || !this->layout->editHistory.isClean() */ || hasUnsavedDataChanges || !isPersistedToFile; + // !TODO: layout not working here? map needs to be in cache before the layout being edited works + return !editHistory.isClean() || !this->layout->editHistory.isClean() || hasUnsavedDataChanges || !isPersistedToFile; } diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index a56a982e..7002f908 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -388,3 +388,7 @@ QPixmap Layout::renderBorder(bool ignoreCache) { } return this->border_pixmap; } + +bool Layout::hasUnsavedChanges() { + return !this->editHistory.isClean(); +} diff --git a/src/editor.cpp b/src/editor.cpp index 4b1bafc5..ba422eda 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -81,6 +81,7 @@ void Editor::closeProject() { } void Editor::setEditingMap() { + qDebug() << "Editor::setEditingMap()"; current_view = map_item; if (map_item) { map_item->paintingMode = LayoutPixmapItem::PaintMode::Metatiles; @@ -932,8 +933,8 @@ void Editor::onHoveredMovementPermissionCleared() { } QString Editor::getMetatileDisplayMessage(uint16_t metatileId) { - Metatile *metatile = Tileset::getMetatile(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary); - QString label = Tileset::getMetatileLabel(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary); + Metatile *metatile = Tileset::getMetatile(metatileId, this->layout->tileset_primary, this->layout->tileset_secondary); + QString label = Tileset::getMetatileLabel(metatileId, this->layout->tileset_primary, this->layout->tileset_secondary); QString message = QString("Metatile: %1").arg(Metatile::getMetatileIdString(metatileId)); if (label.size()) message += QString(" \"%1\"").arg(label); @@ -1113,17 +1114,21 @@ bool Editor::setMap(QString map_name) { return false; } - map = loadedMap; - this->layout = map->layout; // !TODO: + this->map = loadedMap; + + // remove this + //this->layout = this->map->layout; + setLayout(map->layout->id); editGroup.addStack(&map->editHistory); + + // !TODO: determine which stack is active based on edit mode too since layout will have something different editGroup.setActiveStack(&map->editHistory); selected_events->clear(); if (!displayMap()) { return false; } - map_ruler->setMapDimensions(QSize(map->getWidth(), map->getHeight())); - connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); + connect(map, &Map::openScriptRequested, this, &Editor::openScript); updateSelectedEvents(); } @@ -1131,6 +1136,20 @@ bool Editor::setMap(QString map_name) { return true; } +bool Editor::setLayout(QString layoutId) { + // + this->layout = this->project->loadLayout(layoutId); + + if (!displayLayout()) { + return false; + } + + map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight())); + connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); + + return true; +} + void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) { if (item->paintingMode != LayoutPixmapItem::PaintMode::Metatiles) { return; @@ -1337,6 +1356,18 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm } bool Editor::displayMap() { + + displayMapEvents(); + displayMapConnections(); + displayWildMonTables(); + + if (events_group) { + events_group->setVisible(false); + } + return true; +} + +bool Editor::displayLayout() { if (!scene) { scene = new QGraphicsScene; MapSceneEventFilter *filter = new MapSceneEventFilter(); @@ -1351,17 +1382,15 @@ bool Editor::displayMap() { scene->removeItem(this->map_ruler); } + // !TODO: disassociate these functions from Map displayMetatileSelector(); - displayMovementPermissionSelector(); displayMapMetatiles(); + displayMovementPermissionSelector(); displayMapMovementPermissions(); displayBorderMetatiles(); displayCurrentMetatilesSelection(); - displayMapEvents(); - displayMapConnections(); displayMapBorder(); displayMapGrid(); - displayWildMonTables(); this->map_ruler->setZValue(1000); scene->addItem(this->map_ruler); @@ -1372,9 +1401,7 @@ bool Editor::displayMap() { if (collision_item) { collision_item->setVisible(false); } - if (events_group) { - events_group->setVisible(false); - } + return true; } @@ -1396,12 +1423,12 @@ void Editor::displayMetatileSelector() { } else { metatile_selector_item->setLayout(this->layout); if (metatile_selector_item->primaryTileset - && metatile_selector_item->primaryTileset != map->layout->tileset_primary) - emit tilesetUpdated(map->layout->tileset_primary->name); + && metatile_selector_item->primaryTileset != this->layout->tileset_primary) + emit tilesetUpdated(this->layout->tileset_primary->name); if (metatile_selector_item->secondaryTileset - && metatile_selector_item->secondaryTileset != map->layout->tileset_secondary) - emit tilesetUpdated(map->layout->tileset_secondary->name); - metatile_selector_item->setTilesets(map->layout->tileset_primary, map->layout->tileset_secondary); + && metatile_selector_item->secondaryTileset != this->layout->tileset_secondary) + emit tilesetUpdated(this->layout->tileset_secondary->name); + metatile_selector_item->setTilesets(this->layout->tileset_primary, this->layout->tileset_secondary); } scene_metatiles->addItem(metatile_selector_item); @@ -1548,11 +1575,13 @@ void Editor::displayMapConnections() { selected_connection_item = nullptr; connection_items.clear(); - for (MapConnection *connection : map->connections) { - if (connection->direction == "dive" || connection->direction == "emerge") { - continue; + if (map) { + for (MapConnection *connection : map->connections) { + if (connection->direction == "dive" || connection->direction == "emerge") { + continue; + } + createConnectionItem(connection); } - createConnectionItem(connection); } if (!connection_items.empty()) { @@ -1611,8 +1640,8 @@ void Editor::maskNonVisibleConnectionTiles() { mask.addRect( -BORDER_DISTANCE * 16, -BORDER_DISTANCE * 16, - (map->getWidth() + BORDER_DISTANCE * 2) * 16, - (map->getHeight() + BORDER_DISTANCE * 2) * 16 + (layout->getWidth() + BORDER_DISTANCE * 2) * 16, + (layout->getHeight() + BORDER_DISTANCE * 2) * 16 ); // Mask the tiles with the current theme's background color. @@ -1631,13 +1660,13 @@ void Editor::displayMapBorder() { } borderItems.clear(); - int borderWidth = map->getBorderWidth(); - int borderHeight = map->getBorderHeight(); + int borderWidth = this->layout->getBorderWidth(); + int borderHeight = this->layout->getBorderHeight(); int borderHorzDist = getBorderDrawDistance(borderWidth); int borderVertDist = getBorderDrawDistance(borderHeight); QPixmap pixmap = this->layout->renderBorder(); - for (int y = -borderVertDist; y < map->getHeight() + borderVertDist; y += borderHeight) - for (int x = -borderHorzDist; x < map->getWidth() + borderHorzDist; x += borderWidth) { + for (int y = -borderVertDist; y < this->layout->getHeight() + borderVertDist; y += borderHeight) + for (int x = -borderHorzDist; x < this->layout->getWidth() + borderHorzDist; x += borderWidth) { QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); item->setX(x * 16); item->setY(y * 16); @@ -1692,16 +1721,16 @@ void Editor::displayMapGrid() { gridLines.clear(); ui->checkBox_ToggleGrid->disconnect(); - int pixelWidth = map->getWidth() * 16; - int pixelHeight = map->getHeight() * 16; - for (int i = 0; i <= map->getWidth(); i++) { + int pixelWidth = this->layout->getWidth() * 16; + int pixelHeight = this->layout->getHeight() * 16; + for (int i = 0; i <= this->layout->getWidth(); i++) { int x = i * 16; QGraphicsLineItem *line = new QGraphicsLineItem(x, 0, x, pixelHeight); line->setVisible(ui->checkBox_ToggleGrid->isChecked()); gridLines.append(line); connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);}); } - for (int j = 0; j <= map->getHeight(); j++) { + for (int j = 0; j <= this->layout->getHeight(); j++) { int y = j * 16; QGraphicsLineItem *line = new QGraphicsLineItem(0, y, pixelWidth, y); line->setVisible(ui->checkBox_ToggleGrid->isChecked()); @@ -1921,20 +1950,20 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) { - if (map->layout->tileset_primary_label != tilesetLabel || forceLoad) + if (this->layout->tileset_primary_label != tilesetLabel || forceLoad) { - map->layout->tileset_primary_label = tilesetLabel; - map->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad); + this->layout->tileset_primary_label = tilesetLabel; + this->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad); layout->clearBorderCache(); } } void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad) { - if (map->layout->tileset_secondary_label != tilesetLabel || forceLoad) + if (this->layout->tileset_secondary_label != tilesetLabel || forceLoad) { - map->layout->tileset_secondary_label = tilesetLabel; - map->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad); + this->layout->tileset_secondary_label = tilesetLabel; + this->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad); layout->clearBorderCache(); } } @@ -1956,7 +1985,7 @@ void Editor::updateCustomMapHeaderValues(QTableWidget *table) Tileset* Editor::getCurrentMapPrimaryTileset() { - QString tilesetLabel = map->layout->tileset_primary_label; + QString tilesetLabel = this->layout->tileset_primary_label; return project->getTileset(tilesetLabel); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3d0bc6b3..0892a130 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -679,6 +679,53 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { return true; } +bool MainWindow::setLayout(QString layoutId) { + // if this->editor->setLayout(layoutName); + // this->editor->layout = layout; + + if (!this->editor->setLayout(layoutId)) { + return false; + } + + layoutTreeModel->setLayout(layoutId); + + refreshMapScene(); + + // if (scrollTreeView) { + // // Make sure we clear the filter first so we actually have a scroll target + // /// !TODO: make this onto a function that scrolls the current view taking a map name or layout name + // groupListProxyModel->setFilterRegularExpression(QString()); + // ui->mapList->setCurrentIndex(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(map_name))); + // ui->mapList->scrollTo(ui->mapList->currentIndex(), QAbstractItemView::PositionAtCenter); + // } + + showWindowTitle(); + + updateMapList(); + + // connect(editor->map, &Map::mapChanged, this, &MainWindow::onMapChanged); + // connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); + // connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); + + // displayMapProperties + ui->comboBox_PrimaryTileset->blockSignals(true); + ui->comboBox_SecondaryTileset->blockSignals(true); + ui->comboBox_PrimaryTileset->setCurrentText(this->editor->layout->tileset_primary_label); + ui->comboBox_SecondaryTileset->setCurrentText(this->editor->layout->tileset_secondary_label); + ui->comboBox_PrimaryTileset->blockSignals(false); + ui->comboBox_SecondaryTileset->blockSignals(false); + + // + // connect(editor->layout, &Layout::mapChanged, this, &MainWindow::onMapChanged); + // connect(editor->layout, &Layout::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); + // connect(editor->layout, &Layout::modified, [this](){ this->markMapEdited(); }); + + // + updateTilesetEditor(); + + return true; +} + void MainWindow::redrawMapScene() { if (!editor->displayMap()) @@ -1426,12 +1473,22 @@ void MainWindow::on_layoutList_activated(const QModelIndex &index) { QVariant data = index.data(Qt::UserRole); if (index.data(MapListRoles::TypeRole) == "map_layout" && !data.isNull()) { - QString layoutName = data.toString(); + QString layoutId = data.toString(); // logInfo("Switching to a layout-only editing mode"); setMap(QString()); + //setLayout(layoutId); // setLayout(layout) - qDebug() << "set layout" << layoutName; + qDebug() << "set layout" << layoutId; + + if (!setLayout(layoutId)) { + QMessageBox msgBox(this); + QString errorMsg = QString("There was an error opening layout %1. Please see %2 for full error details.\n\n%3") + .arg(layoutId) + .arg(getLogPath()) + .arg(getMostRecentError()); + msgBox.critical(nullptr, "Error Opening Layout", errorMsg); + } } } @@ -1468,8 +1525,15 @@ void MainWindow::drawMapListIcons(QAbstractItemModel *model) { void MainWindow::updateMapList() { //MapGroupModel *model = static_cast(this->ui->mapList->model()); - mapGroupModel->setMap(this->editor->map->name); - groupListProxyModel->layoutChanged(); + if (this->editor->map) { + mapGroupModel->setMap(this->editor->map->name); + groupListProxyModel->layoutChanged(); + } + + if (this->editor->layout) { + layoutTreeModel->setLayout(this->editor->layout->id); + layoutListProxyModel->layoutChanged(); + } //mapGroupModel->layoutChanged(); // drawMapListIcons(mapListModel); } @@ -1746,6 +1810,7 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index) Scripting::cb_MapViewTabChanged(oldIndex, index); if (index == 0) { + //if () editor->setEditingMap(); } else if (index == 1) { editor->setEditingCollision(); @@ -1768,6 +1833,8 @@ void MainWindow::on_action_Exit_triggered() void MainWindow::on_mainTabBar_tabBarClicked(int index) { + //if (!editor->map) return; + int oldIndex = ui->mainTabBar->currentIndex(); ui->mainTabBar->setCurrentIndex(index); if (index != oldIndex) @@ -1787,6 +1854,8 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index) } else if (index == 3) { editor->setEditingConnections(); } + + if (!editor->map) return; if (index != 4) { if (userConfig.getEncounterJsonActive()) editor->saveEncounterTabData(); diff --git a/src/project.cpp b/src/project.cpp index 4acaf94d..c5cbe2e5 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -390,6 +390,19 @@ bool Project::loadLayout(MapLayout *layout) { && loadedBorder; } +Layout *Project::loadLayout(QString layoutId) { + // + if (mapLayouts.contains(layoutId)) { + Layout *layout = mapLayouts[layoutId]; + if (loadLayout(layout)) { + return layout; + } + } + + logError(QString("Error: Failed to load layout '%1'").arg(layoutId)); + return nullptr; +} + bool Project::loadMapLayout(Map* map) { if (!map->isPersistedToFile) { return true; diff --git a/src/ui/collisionpixmapitem.cpp b/src/ui/collisionpixmapitem.cpp index 26680677..0c809c3f 100644 --- a/src/ui/collisionpixmapitem.cpp +++ b/src/ui/collisionpixmapitem.cpp @@ -51,7 +51,7 @@ void CollisionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::draw(bool ignoreCache) { if (this->layout) { // !TODO - // this->layout->setCollisionItem(this); + this->layout->setCollisionItem(this); setPixmap(this->layout->renderCollision(ignoreCache)); setOpacity(*this->opacity); } diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 53a65154..1add584f 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -272,14 +272,14 @@ LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : QStandardI initialize(); } -QStandardItem *LayoutTreeModel::createLayoutItem(QString layoutName) { +QStandardItem *LayoutTreeModel::createLayoutItem(QString layoutId) { QStandardItem *layout = new QStandardItem; - layout->setText(layoutName); + layout->setText(layoutId); layout->setEditable(false); - layout->setData(layoutName, Qt::UserRole); + layout->setData(layoutId, Qt::UserRole); layout->setData("map_layout", MapListRoles::TypeRole); // // group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); - this->layoutItems.insert(layoutName, layout); + this->layoutItems.insert(layoutId, layout); return layout; } @@ -298,17 +298,16 @@ void LayoutTreeModel::initialize() { for (int i = 0; i < this->project->mapLayoutsTable.length(); i++) { // QString layoutId = project->mapLayoutsTable.value(i); - MapLayout *layout = project->mapLayouts.value(layoutId); - QStandardItem *layoutItem = createLayoutItem(layout->name); + QStandardItem *layoutItem = createLayoutItem(layoutId); this->root->appendRow(layoutItem); } for (auto mapList : this->project->groupedMapNames) { for (auto mapName : mapList) { // - QString layoutName = project->readMapLayoutName(mapName); + QString layoutId = project->readMapLayoutId(mapName); QStandardItem *map = createMapItem(mapName); - this->layoutItems[layoutName]->appendRow(map); + this->layoutItems[layoutId]->appendRow(map); } } @@ -344,6 +343,15 @@ QVariant LayoutTreeModel::data(const QModelIndex &index, int role) const { QString type = item->data(MapListRoles::TypeRole).toString(); if (type == "map_layout") { + QString layoutId = item->data(Qt::UserRole).toString(); + if (layoutId == this->openLayout) { + return mapOpenedIcon; + } + else if (this->project->mapLayouts.contains(layoutId)) { + if (this->project->mapLayouts.value(layoutId)->hasUnsavedChanges()) { + return mapEditedIcon; + } + } return mapIcon; } else if (type == "map_name") {