From 61256d39ca5f519c4d4f9b8b1fcb3951a22a14ec Mon Sep 17 00:00:00 2001 From: garak Date: Mon, 23 Jan 2023 12:19:21 -0500 Subject: [PATCH 01/70] reorganize some class data --- include/core/map.h | 35 +++++++++++++++++++++++++++++------ include/core/maplayout.h | 15 +++++++++++++++ include/editor.h | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index 779afefe6..d0617c43c 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -39,6 +39,7 @@ class Map : public QObject public: QString name; QString constantName; + QString song; QString layoutId; QString location; @@ -51,14 +52,20 @@ class Map : public QObject bool allowEscaping; int floorNumber = 0; QString battle_scene; + QString sharedEventsMap = ""; QString sharedScriptsMap = ""; + QMap customHeaders; + MapLayout *layout; + bool isPersistedToFile = true; bool hasUnsavedDataChanges = false; + bool needsLayoutDir = true; bool needsHealLocation = false; + QImage collision_image; QPixmap collision_pixmap; QImage image; @@ -68,42 +75,62 @@ class Map : public QObject QList ownedEvents; // for memory management QList connections; + QList metatileLayerOrder; QList metatileLayerOpacity; + void setName(QString mapName); static QString mapConstantFromName(QString mapName); + + /// !HERE /* layout related stuff */ int getWidth(); int getHeight(); int getBorderWidth(); int getBorderHeight(); + + QUndoStack editHistory; + void modify(); + void clean(); + QPixmap render(bool ignoreCache = false, MapLayout *fromLayout = nullptr, QRect bounds = QRect(0, 0, -1, -1)); QPixmap renderCollision(bool ignoreCache); + QPixmap renderConnection(MapConnection, MapLayout *); + QPixmap renderBorder(bool ignoreCache = false); + bool mapBlockChanged(int i, const Blockdata &cache); bool borderBlockChanged(int i, const Blockdata &cache); + void cacheBlockdata(); void cacheCollision(); + bool getBlock(int x, int y, Block *out); void setBlock(int x, int y, Block block, bool enableScriptCallback = false); void setBlockdata(Blockdata blockdata, bool enableScriptCallback = false); + uint16_t getBorderMetatileId(int x, int y); void setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback = false); void setBorderBlockData(Blockdata blockdata, bool enableScriptCallback = false); + 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); + QList getAllEvents() const; QStringList eventScriptLabels(Event::Group group = Event::Group::None) const; void removeEvent(Event *); void addEvent(Event *); - QPixmap renderConnection(MapConnection, MapLayout *); - QPixmap renderBorder(bool ignoreCache = false); + void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); + void clearBorderCache(); void cacheBorder(); + bool hasUnsavedChanges(); + bool isWithinBounds(int x, int y); bool isWithinBorderBounds(int x, int y); + void openScript(QString label); MapPixmapItem *mapItem = nullptr; @@ -115,10 +142,6 @@ class Map : public QObject BorderMetatilesPixmapItem *borderItem = nullptr; void setBorderItem(BorderMetatilesPixmapItem *item) { borderItem = item; } - QUndoStack editHistory; - void modify(); - void clean(); - 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 13215fff0..41fa6946e 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -8,25 +8,40 @@ #include #include +class Map; + class MapLayout { public: MapLayout() {} + static QString layoutConstantFromName(QString mapName); + + /// !TODO + /* NEW */ + QList maps; + QString id; QString name; + int width; int height; int border_width; int border_height; + QString border_path; QString blockdata_path; + QString tileset_primary_label; QString tileset_secondary_label; + Tileset *tileset_primary = nullptr; Tileset *tileset_secondary = nullptr; + Blockdata blockdata; + QImage border_image; QPixmap border_pixmap; + Blockdata border; Blockdata cached_blockdata; Blockdata cached_collision; diff --git a/include/editor.h b/include/editor.h index 2282fba71..0b0bc5910 100644 --- a/include/editor.h +++ b/include/editor.h @@ -43,15 +43,26 @@ class Editor : public QObject public: Ui::MainWindow* ui; QObject *parent = nullptr; + Project *project = nullptr; Map *map = nullptr; + MapLayout *layout = nullptr; /* NEW */ + + QUndoGroup editGroup; // Manages the undo history for each map + Settings *settings; - void saveProject(); + void save(); - void closeProject(); - bool setMap(QString map_name); + void saveProject(); void saveUiFields(); void saveEncounterTabData(); + + void closeProject(); + + bool setMap(QString map_name); + + Tileset *getCurrentMapPrimaryTileset(); + bool displayMap(); void displayMetatileSelector(); void displayMapMetatiles(); @@ -74,6 +85,7 @@ class Editor : public QObject void setEditingObjects(); void setEditingConnections(); void setMapEditingButtonsEnabled(bool enabled); + void setCurrentConnectionDirection(QString curDirection); void updateCurrentConnectionDirection(QString curDirection); void setConnectionsVisibility(bool visible); @@ -81,19 +93,21 @@ class Editor : public QObject void setConnectionMap(QString mapName); void addNewConnection(); void removeCurrentConnection(); - void addNewWildMonGroup(QWidget *window); - void deleteWildMonGroup(); void updateDiveMap(QString mapName); void updateEmergeMap(QString mapName); void setSelectedConnectionFromMap(QString mapName); + + void addNewWildMonGroup(QWidget *window); + void deleteWildMonGroup(); + void configureEncounterJSON(QWidget *); + void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false); void updateSecondaryTileset(QString tilesetLabel, bool forceLoad = false); void toggleBorderVisibility(bool visible, bool enableScriptCallback = true); void updateCustomMapHeaderValues(QTableWidget *); - void configureEncounterJSON(QWidget *); - Tileset *getCurrentMapPrimaryTileset(); DraggablePixmapItem *addMapEvent(Event *event); + bool eventLimitReached(Map *, Event::Type); void selectMapEvent(DraggablePixmapItem *object); void selectMapEvent(DraggablePixmapItem *object, bool toggle); DraggablePixmapItem *addNewEvent(Event::Type type); @@ -101,10 +115,11 @@ class Editor : public QObject void duplicateSelectedEvents(); void redrawObject(DraggablePixmapItem *item); QList getObjects(); + void updateCursorRectPos(int x, int y); void setCursorRectVisible(bool visible); - bool eventLimitReached(Map *, Event::Type); + QGraphicsScene *scene = nullptr; QGraphicsPixmapItem *current_view = nullptr; @@ -114,17 +129,20 @@ class Editor : public QObject QGraphicsPathItem *connection_mask = nullptr; CollisionPixmapItem *collision_item = nullptr; QGraphicsItemGroup *events_group = nullptr; + QList borderItems; QList gridLines; + MapRuler *map_ruler = nullptr; + MovableRect *playerViewRect = nullptr; CursorTileRect *cursorMapTileRect = nullptr; - MapRuler *map_ruler = nullptr; QGraphicsScene *scene_metatiles = nullptr; QGraphicsScene *scene_current_metatile_selection = nullptr; QGraphicsScene *scene_selected_border_metatiles = nullptr; QGraphicsScene *scene_collision_metatiles = nullptr; QGraphicsScene *scene_elevation_metatiles = nullptr; + MetatileSelector *metatile_selector_item = nullptr; BorderMetatilesPixmapItem *selected_border_metatiles_item = nullptr; @@ -133,6 +151,7 @@ class Editor : public QObject QList *selected_events = nullptr; + /// !TODO this QString map_edit_mode = "paint"; QString obj_edit_mode = "select"; @@ -143,8 +162,6 @@ class Editor : public QObject int getBorderDrawDistance(int dimension); - QUndoGroup editGroup; // Manages the undo history for each map - bool selectingEvent = false; void shouldReselectEvents(); From 917e61b98a68c8cd50a9130a34b3d9487a130a0e Mon Sep 17 00:00:00 2001 From: garak Date: Mon, 30 Jan 2023 18:47:37 -0500 Subject: [PATCH 02/70] add different tabs for map list views --- forms/mainwindow.ui | 614 ++++++++++++++++++++++++++----------- include/mainwindow.h | 35 ++- include/ui/maplistmodels.h | 58 ++++ porymap.pro | 2 + src/mainwindow.cpp | 549 +++++++++++++++++---------------- src/ui/maplistmodels.cpp | 219 +++++++++++++ 6 files changed, 1015 insertions(+), 462 deletions(-) create mode 100644 include/ui/maplistmodels.h create mode 100644 src/ui/maplistmodels.cpp diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 7b8aa8b49..fb340222d 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -32,7 +32,7 @@ Qt::Horizontal - + true @@ -42,168 +42,414 @@ 0 - - - 0 - - - 0 - - - 0 - - - 3 - - - 0 - - - - - 0 - - - 3 - - - 3 - - - 3 - - - - - true - - - <html><head/><body><p>Sort map list</p></body></html> - - - - :/icons/sort_alphabet.ico:/icons/sort_alphabet.ico - - - - 16 - 16 - - - - QToolButton::InstantPopup - - - Qt::ToolButtonIconOnly - - - true - - - Qt::NoArrow - - - - - - - <html><head/><body><p>Expand all map folders</p></body></html> - - - - - - - :/icons/expand_all.ico:/icons/expand_all.ico - - - QToolButton::InstantPopup - - - true - - - - - - - <html><head/><body><p>Collapse all map list folders</p></body></html> - - - - - - - :/icons/collapse_all.ico:/icons/collapse_all.ico - - - QToolButton::InstantPopup - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 12 - 20 - - - - - - - - true - - - - - - Filter maps... - - - true - - - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectItems - - - false - - - - + + 0 + + + + Groups + + + + 0 + + + 0 + + + 0 + + + 3 + + + 0 + + + + + 0 + + + 3 + + + 3 + + + 3 + + + + + <html><head/><body><p>Expand all map folders</p></body></html> + + + + + + + :/icons/expand_all.ico:/icons/expand_all.ico + + + QToolButton::InstantPopup + + + true + + + + + + + <html><head/><body><p>Collapse all map list folders</p></body></html> + + + + + + + :/icons/collapse_all.ico:/icons/collapse_all.ico + + + QToolButton::InstantPopup + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 12 + 20 + + + + + + + + true + + + + + + Filter... + + + true + + + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectItems + + + false + + + + + + + + Areas + + + + 0 + + + 0 + + + 0 + + + 3 + + + 0 + + + + + 0 + + + 3 + + + 3 + + + 3 + + + + + <html><head/><body><p>Expand all map folders</p></body></html> + + + + + + + :/icons/expand_all.ico:/icons/expand_all.ico + + + QToolButton::InstantPopup + + + true + + + + + + + <html><head/><body><p>Collapse all map list folders</p></body></html> + + + + + + + :/icons/collapse_all.ico:/icons/collapse_all.ico + + + QToolButton::InstantPopup + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 12 + 20 + + + + + + + + true + + + + + + Filter... + + + true + + + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectItems + + + false + + + + + + + + Layouts + + + + 0 + + + 0 + + + 0 + + + 3 + + + 0 + + + + + 0 + + + 3 + + + 3 + + + 3 + + + + + <html><head/><body><p>Expand all layout folders</p></body></html> + + + + + + + :/icons/expand_all.ico:/icons/expand_all.ico + + + QToolButton::InstantPopup + + + true + + + + + + + <html><head/><body><p>Collapse all layout folders</p></body></html> + + + + + + + :/icons/collapse_all.ico:/icons/collapse_all.ico + + + QToolButton::InstantPopup + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 12 + 20 + + + + + + + + true + + + + + + Filter... + + + true + + + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectItems + + + false + + + + + @@ -260,7 +506,7 @@ - 0 + 3 false @@ -813,7 +1059,7 @@ 0 0 - 423 + 256 74 @@ -1001,10 +1247,10 @@ - 8 + 0 0 - 411 - 413 + 91 + 74 @@ -1154,8 +1400,8 @@ 0 0 - 428 - 696 + 92 + 550 @@ -1314,8 +1560,8 @@ 0 0 - 398 - 631 + 91 + 460 @@ -1615,8 +1861,8 @@ 0 0 - 434 - 581 + 100 + 16 @@ -1709,8 +1955,8 @@ 0 0 - 434 - 581 + 100 + 16 @@ -1803,8 +2049,8 @@ 0 0 - 434 - 581 + 100 + 16 @@ -1903,8 +2149,8 @@ 0 0 - 434 - 581 + 100 + 16 @@ -1997,8 +2243,8 @@ 0 0 - 434 - 581 + 100 + 16 @@ -2051,8 +2297,8 @@ 0 0 - 434 - 625 + 100 + 30 diff --git a/include/mainwindow.h b/include/mainwindow.h index 0f1eeac79..09d39f3a5 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -21,6 +21,7 @@ #include "regionmapeditor.h" #include "mapimageexporter.h" #include "filterchildrenproxymodel.h" +#include "maplistmodels.h" #include "newmappopup.h" #include "newtilesetdialog.h" #include "shortcutseditor.h" @@ -257,8 +258,6 @@ private slots: void on_actionTileset_Editor_triggered(); - void mapSortOrder_changed(QAction *action); - void on_lineEdit_filterBox_textChanged(const QString &arg1); void moveEvent(QMoveEvent *event); @@ -267,8 +266,14 @@ private slots: void eventTabChanged(int index); void on_horizontalSlider_CollisionTransparency_valueChanged(int value); - void on_toolButton_ExpandAll_clicked(); - void on_toolButton_CollapseAll_clicked(); + + void on_toolButton_ExpandAll_Groups_clicked(); + void on_toolButton_CollapseAll_Groups_clicked(); + void on_toolButton_ExpandAll_Areas_clicked(); + void on_toolButton_CollapseAll_Areas_clicked(); + void on_toolButton_ExpandAll_Layouts_clicked(); + void on_toolButton_CollapseAll_Layouts_clicked(); + void on_actionAbout_Porymap_triggered(); void on_actionOpen_Log_File_triggered(); void on_actionOpen_Config_Folder_triggered(); @@ -302,13 +307,15 @@ private slots: QPointer preferenceEditor = nullptr; QPointer projectSettingsEditor = nullptr; QPointer customScriptsEditor = nullptr; - FilterChildrenProxyModel *mapListProxyModel; - QStandardItemModel *mapListModel; - QList *mapGroupItemsList; - QMap mapListIndexes; - QIcon* mapIcon; - QIcon* mapEditedIcon; - QIcon* mapOpenedIcon; + + FilterChildrenProxyModel *groupListProxyModel; + MapGroupModel *mapGroupModel; + // QStandardItemModel *mapListModel; + // QList *mapGroupItemsList; + // QMap mapListIndexes; + // QIcon* mapIcon; + // QIcon* mapEditedIcon; + // QIcon* mapOpenedIcon; QAction *undoAction = nullptr; QAction *redoAction = nullptr; @@ -397,10 +404,4 @@ private slots: int insertTilesetLabel(QStringList * list, QString label); }; -enum MapListUserRoles { - GroupRole = Qt::UserRole + 1, // Used to hold the map group number. - TypeRole, // Used to differentiate between the different layers of the map list tree view. - TypeRole2, // Used for various extra data needed. -}; - #endif // MAINWINDOW_H diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h new file mode 100644 index 000000000..972c86681 --- /dev/null +++ b/include/ui/maplistmodels.h @@ -0,0 +1,58 @@ +#pragma once +#ifndef MAPLISTMODELS_H +#define MAPLISTMODELS_H + +#include +#include + + + +class Project; + +enum MapListRoles { + GroupRole = Qt::UserRole + 1, // Used to hold the map group number. + TypeRole, // Used to differentiate between the different layers of the map list tree view. + TypeRole2, // Used for various extra data needed. +}; + +// or QStandardItemModel?? +class MapGroupModel : public QStandardItemModel { + Q_OBJECT + +public: + MapGroupModel(Project *project, QObject *parent = nullptr); + ~MapGroupModel() {} + + QVariant data(const QModelIndex &index, int role) const override; + +public: + void setMap(QString mapName) { this->openMap = mapName; } + + QStandardItem *createGroupItem(QString groupName, int groupIndex); + QStandardItem *createMapItem(QString mapName, int groupIndex, int mapIndex); + + QStandardItem *getItem(const QModelIndex &index) const; + QModelIndex indexOfMap(QString mapName); + + void initialize(); + +private: + Project *project; + QStandardItem *root = nullptr; + + QMap groupItems; + QMap mapItems; + // TODO: if reordering, will the item be the same? + + QString openMap; + + // QIcon *mapIcon = nullptr; + // QIcon *mapEditedIcon = nullptr; + // QIcon *mapOpenedIcon = nullptr; + // QIcon *mapFolderIcon = nullptr; + +signals: + void edited(); +}; + +#endif // MAPLISTMODELS_H diff --git a/porymap.pro b/porymap.pro index 63b97c1a2..7e39f0f82 100644 --- a/porymap.pro +++ b/porymap.pro @@ -58,6 +58,7 @@ SOURCES += src/core/block.cpp \ src/ui/customattributestable.cpp \ src/ui/eventframes.cpp \ src/ui/filterchildrenproxymodel.cpp \ + src/ui/maplistmodels.cpp \ src/ui/graphicsview.cpp \ src/ui/imageproviders.cpp \ src/ui/mappixmapitem.cpp \ @@ -147,6 +148,7 @@ HEADERS += include/core/block.h \ include/ui/customattributestable.h \ include/ui/eventframes.h \ include/ui/filterchildrenproxymodel.h \ + include/ui/maplistmodels.h \ include/ui/graphicsview.h \ include/ui/imageproviders.h \ include/ui/mappixmapitem.h \ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2a3b2735a..5c4aaf34c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -19,6 +19,7 @@ #include "prefab.h" #include "montabwidget.h" #include "imageexport.h" +#include "maplistmodels.h" #include #include @@ -151,13 +152,14 @@ void MainWindow::initExtraShortcuts() { shortcutToggle_Smart_Paths->setObjectName("shortcutToggle_Smart_Paths"); shortcutToggle_Smart_Paths->setWhatsThis("Toggle Smart Paths"); - auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_ExpandAll_clicked())); - shortcutExpand_All->setObjectName("shortcutExpand_All"); - shortcutExpand_All->setWhatsThis("Map List: Expand all folders"); + /// !TODO + // auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_ExpandAll_clicked())); + // shortcutExpand_All->setObjectName("shortcutExpand_All"); + // shortcutExpand_All->setWhatsThis("Map List: Expand all folders"); - auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_CollapseAll_clicked())); - shortcutCollapse_All->setObjectName("shortcutCollapse_All"); - shortcutCollapse_All->setWhatsThis("Map List: Collapse all folders"); + // auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_CollapseAll_clicked())); + // shortcutCollapse_All->setObjectName("shortcutCollapse_All"); + // shortcutCollapse_All->setWhatsThis("Map List: Collapse all folders"); auto *shortcut_Open_Scripts = new Shortcut(QKeySequence(), ui->toolButton_Open_Scripts, SLOT(click())); shortcut_Open_Scripts->setObjectName("shortcut_Open_Scripts"); @@ -210,6 +212,7 @@ void MainWindow::initCustomUI() { } void MainWindow::initExtraSignals() { + /// !TODO // Right-clicking on items in the map list tree view brings up a context menu. ui->mapList->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->mapList, &QTreeView::customContextMenuRequested, @@ -311,16 +314,17 @@ void MainWindow::initEditor() { } void MainWindow::initMiscHeapObjects() { - mapIcon = new QIcon(QStringLiteral(":/icons/map.ico")); - mapEditedIcon = new QIcon(QStringLiteral(":/icons/map_edited.ico")); - mapOpenedIcon = new QIcon(QStringLiteral(":/icons/map_opened.ico")); + // mapIcon = new QIcon(QStringLiteral(":/icons/map.ico")); + // mapEditedIcon = new QIcon(QStringLiteral(":/icons/map_edited.ico")); + // mapOpenedIcon = new QIcon(QStringLiteral(":/icons/map_opened.ico")); - mapListModel = new QStandardItemModel; - mapGroupItemsList = new QList; - mapListProxyModel = new FilterChildrenProxyModel; + /// !TODO + // mapListModel = new QStandardItemModel; + // mapGroupItemsList = new QList; + // mapListProxyModel = new FilterChildrenProxyModel; - mapListProxyModel->setSourceModel(mapListModel); - ui->mapList->setModel(mapListProxyModel); + // mapListProxyModel->setSourceModel(mapListModel); + // ui->mapList->setModel(mapListProxyModel); eventTabObjectWidget = ui->tab_Objects; eventTabWarpWidget = ui->tab_Warps; @@ -332,23 +336,23 @@ void MainWindow::initMiscHeapObjects() { } void MainWindow::initMapSortOrder() { - QMenu *mapSortOrderMenu = new QMenu(this); - QActionGroup *mapSortOrderActionGroup = new QActionGroup(ui->toolButton_MapSortOrder); + // QMenu *mapSortOrderMenu = new QMenu(this); + // QActionGroup *mapSortOrderActionGroup = new QActionGroup(ui->toolButton_MapSortOrder); - mapSortOrderMenu->addAction(ui->actionSort_by_Group); - mapSortOrderMenu->addAction(ui->actionSort_by_Area); - mapSortOrderMenu->addAction(ui->actionSort_by_Layout); - ui->toolButton_MapSortOrder->setMenu(mapSortOrderMenu); + // mapSortOrderMenu->addAction(ui->actionSort_by_Group); + // mapSortOrderMenu->addAction(ui->actionSort_by_Area); + // mapSortOrderMenu->addAction(ui->actionSort_by_Layout); + // ui->toolButton_MapSortOrder->setMenu(mapSortOrderMenu); - mapSortOrderActionGroup->addAction(ui->actionSort_by_Group); - mapSortOrderActionGroup->addAction(ui->actionSort_by_Area); - mapSortOrderActionGroup->addAction(ui->actionSort_by_Layout); + // mapSortOrderActionGroup->addAction(ui->actionSort_by_Group); + // mapSortOrderActionGroup->addAction(ui->actionSort_by_Area); + // mapSortOrderActionGroup->addAction(ui->actionSort_by_Layout); - connect(mapSortOrderActionGroup, &QActionGroup::triggered, this, &MainWindow::mapSortOrder_changed); + // connect(mapSortOrderActionGroup, &QActionGroup::triggered, this, &MainWindow::mapSortOrder_changed); - QAction* sortOrder = ui->toolButton_MapSortOrder->menu()->actions()[mapSortOrder]; - ui->toolButton_MapSortOrder->setIcon(sortOrder->icon()); - sortOrder->setChecked(true); + // QAction* sortOrder = ui->toolButton_MapSortOrder->menu()->actions()[mapSortOrder]; + // ui->toolButton_MapSortOrder->setIcon(sortOrder->icon()); + // sortOrder->setChecked(true); } void MainWindow::showWindowTitle() { @@ -393,46 +397,20 @@ void MainWindow::setProjectSpecificUIVisibility() ui->label_FloorNumber->setVisible(floorNumEnabled); } -void MainWindow::mapSortOrder_changed(QAction *action) -{ - QList items = ui->toolButton_MapSortOrder->menu()->actions(); - int i = 0; - for (; i < items.count(); i++) - { - if (items[i] == action) - { - break; - } - } - - if (i != mapSortOrder) - { - ui->toolButton_MapSortOrder->setIcon(action->icon()); - mapSortOrder = static_cast(i); - porymapConfig.setMapSortOrder(mapSortOrder); - if (isProjectOpen()) - { - sortMapList(); - applyMapListFilter(ui->lineEdit_filterBox->text()); - } - } +void MainWindow::on_lineEdit_filterBox_textChanged(const QString &text) { + this->applyMapListFilter(text); } -void MainWindow::on_lineEdit_filterBox_textChanged(const QString &arg1) -{ - this->applyMapListFilter(arg1); -} - -void MainWindow::applyMapListFilter(QString filterText) -{ - mapListProxyModel->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption)); +void MainWindow::applyMapListFilter(QString filterText) { + /// !TODO + groupListProxyModel->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption)); if (filterText.isEmpty()) { ui->mapList->collapseAll(); } else { ui->mapList->expandToDepth(0); } - ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), true); - ui->mapList->scrollTo(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), QAbstractItemView::PositionAtCenter); + // ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), true); + // ui->mapList->scrollTo(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), QAbstractItemView::PositionAtCenter); } void MainWindow::loadUserSettings() { @@ -650,8 +628,9 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { return false; } - if (editor->map != nullptr && !editor->map->name.isNull()) { - ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), false); + if (editor->map && !editor->map->name.isNull()) { + // !TODO: function to act on current view? or that does all the views + ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(map_name)), false); } refreshMapScene(); @@ -659,13 +638,12 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { if (scrollTreeView) { // Make sure we clear the filter first so we actually have a scroll target - mapListProxyModel->setFilterRegularExpression(QString()); - ui->mapList->setCurrentIndex(mapListProxyModel->mapFromSource(mapListIndexes.value(map_name))); + /// !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); } - ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(map_name)), true); - showWindowTitle(); connect(editor->map, &Map::mapChanged, this, &MainWindow::onMapChanged); @@ -973,169 +951,187 @@ bool MainWindow::loadProjectCombos() { return true; } +/// !TODO bool MainWindow::populateMapList() { + // bool success = editor->project->readMapGroups(); + // if (success) { + // sortMapList(); + // } + // return success; bool success = editor->project->readMapGroups(); - if (success) { - sortMapList(); - } - return success; -} -void MainWindow::sortMapList() { - Project *project = editor->project; - - QIcon mapFolderIcon; - mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); - mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); + this->mapGroupModel = new MapGroupModel(editor->project); + this->groupListProxyModel = new FilterChildrenProxyModel(); + groupListProxyModel->setSourceModel(this->mapGroupModel); + ui->mapList->setModel(groupListProxyModel); - QIcon folderIcon; - folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off); - //folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On); + // ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); + // ui->mapList->setDragEnabled(true); + // ui->mapList->setAcceptDrops(true); + // ui->mapList->setDropIndicatorShown(true); - ui->mapList->setUpdatesEnabled(false); - mapListModel->clear(); - mapGroupItemsList->clear(); - QStandardItem *root = mapListModel->invisibleRootItem(); - - switch (mapSortOrder) - { - case MapSortOrder::Group: - for (int i = 0; i < project->groupNames.length(); i++) { - QString group_name = project->groupNames.value(i); - QStandardItem *group = new QStandardItem; - group->setText(group_name); - group->setIcon(mapFolderIcon); - group->setEditable(false); - group->setData(group_name, Qt::UserRole); - group->setData("map_group", MapListUserRoles::TypeRole); - group->setData(i, MapListUserRoles::GroupRole); - root->appendRow(group); - mapGroupItemsList->append(group); - QStringList names = project->groupedMapNames.value(i); - for (int j = 0; j < names.length(); j++) { - QString map_name = names.value(j); - QStandardItem *map = createMapItem(map_name, i, j); - group->appendRow(map); - mapListIndexes.insert(map_name, map->index()); - } - } - break; - case MapSortOrder::Area: - { - QMap mapsecToGroupNum; - for (int i = 0; i < project->mapSectionNameToValue.size(); i++) { - QString mapsec_name = project->mapSectionValueToName.value(i); - QStandardItem *mapsec = new QStandardItem; - mapsec->setText(mapsec_name); - mapsec->setIcon(folderIcon); - mapsec->setEditable(false); - mapsec->setData(mapsec_name, Qt::UserRole); - mapsec->setData("map_sec", MapListUserRoles::TypeRole); - mapsec->setData(i, MapListUserRoles::GroupRole); - root->appendRow(mapsec); - mapGroupItemsList->append(mapsec); - mapsecToGroupNum.insert(mapsec_name, i); - } - for (int i = 0; i < project->groupNames.length(); i++) { - QStringList names = project->groupedMapNames.value(i); - for (int j = 0; j < names.length(); j++) { - QString map_name = names.value(j); - QStandardItem *map = createMapItem(map_name, i, j); - QString location = project->readMapLocation(map_name); - QStandardItem *mapsecItem = mapGroupItemsList->at(mapsecToGroupNum[location]); - mapsecItem->setIcon(mapFolderIcon); - mapsecItem->appendRow(map); - mapListIndexes.insert(map_name, map->index()); - } - } - break; - } - case MapSortOrder::Layout: - { - QMap layoutIndices; - for (int i = 0; i < project->mapLayoutsTable.length(); i++) { - QString layoutId = project->mapLayoutsTable.value(i); - MapLayout *layout = project->mapLayouts.value(layoutId); - QStandardItem *layoutItem = new QStandardItem; - layoutItem->setText(layout->name); - layoutItem->setIcon(folderIcon); - layoutItem->setEditable(false); - layoutItem->setData(layout->name, Qt::UserRole); - layoutItem->setData("map_layout", MapListUserRoles::TypeRole); - layoutItem->setData(layout->id, MapListUserRoles::TypeRole2); - layoutItem->setData(i, MapListUserRoles::GroupRole); - root->appendRow(layoutItem); - mapGroupItemsList->append(layoutItem); - layoutIndices[layoutId] = i; - } - for (int i = 0; i < project->groupNames.length(); i++) { - QStringList names = project->groupedMapNames.value(i); - for (int j = 0; j < names.length(); j++) { - QString map_name = names.value(j); - QStandardItem *map = createMapItem(map_name, i, j); - QString layoutId = project->readMapLayoutId(map_name); - QStandardItem *layoutItem = mapGroupItemsList->at(layoutIndices.value(layoutId)); - layoutItem->setIcon(mapFolderIcon); - layoutItem->appendRow(map); - mapListIndexes.insert(map_name, map->index()); - } - } - break; - } - } + return success; - ui->mapList->setUpdatesEnabled(true); - ui->mapList->repaint(); - updateMapList(); + //MapGroupModel } +void MainWindow::sortMapList() { + // Project *project = editor->project; + + // QIcon mapFolderIcon; + // mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); + // mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); + + // QIcon folderIcon; + // folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off); + // //folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On); + + // ui->mapList->setUpdatesEnabled(false); + // mapListModel->clear(); + // mapGroupItemsList->clear(); + // QStandardItem *root = mapListModel->invisibleRootItem(); + + // switch (mapSortOrder) + // { + // case MapSortOrder::Group: + // for (int i = 0; i < project->groupNames.length(); i++) { + // QString group_name = project->groupNames.value(i); + // QStandardItem *group = new QStandardItem; + // group->setText(group_name); + // group->setIcon(mapFolderIcon); + // group->setEditable(false); + // group->setData(group_name, Qt::UserRole); + // group->setData("map_group", MapListUserRoles::TypeRole); + // group->setData(i, MapListUserRoles::GroupRole); + // root->appendRow(group); + // mapGroupItemsList->append(group); + // QStringList names = project->groupedMapNames.value(i); + // for (int j = 0; j < names.length(); j++) { + // QString map_name = names.value(j); + // QStandardItem *map = createMapItem(map_name, i, j); + // group->appendRow(map); + // mapListIndexes.insert(map_name, map->index()); + // } + // } + // break; + // case MapSortOrder::Area: + // { + // QMap mapsecToGroupNum; + // for (int i = 0; i < project->mapSectionNameToValue.size(); i++) { + // QString mapsec_name = project->mapSectionValueToName.value(i); + // QStandardItem *mapsec = new QStandardItem; + // mapsec->setText(mapsec_name); + // mapsec->setIcon(folderIcon); + // mapsec->setEditable(false); + // mapsec->setData(mapsec_name, Qt::UserRole); + // mapsec->setData("map_sec", MapListUserRoles::TypeRole); + // mapsec->setData(i, MapListUserRoles::GroupRole); + // root->appendRow(mapsec); + // mapGroupItemsList->append(mapsec); + // mapsecToGroupNum.insert(mapsec_name, i); + // } + // for (int i = 0; i < project->groupNames.length(); i++) { + // QStringList names = project->groupedMapNames.value(i); + // for (int j = 0; j < names.length(); j++) { + // QString map_name = names.value(j); + // QStandardItem *map = createMapItem(map_name, i, j); + // QString location = project->readMapLocation(map_name); + // QStandardItem *mapsecItem = mapGroupItemsList->at(mapsecToGroupNum[location]); + // mapsecItem->setIcon(mapFolderIcon); + // mapsecItem->appendRow(map); + // mapListIndexes.insert(map_name, map->index()); + // } + // } + // break; + // } + // case MapSortOrder::Layout: + // { + // QMap layoutIndices; + // for (int i = 0; i < project->mapLayoutsTable.length(); i++) { + // QString layoutId = project->mapLayoutsTable.value(i); + // MapLayout *layout = project->mapLayouts.value(layoutId); + // QStandardItem *layoutItem = new QStandardItem; + // layoutItem->setText(layout->name); + // layoutItem->setIcon(folderIcon); + // layoutItem->setEditable(false); + // layoutItem->setData(layout->name, Qt::UserRole); + // layoutItem->setData("map_layout", MapListUserRoles::TypeRole); + // layoutItem->setData(layout->id, MapListUserRoles::TypeRole2); + // layoutItem->setData(i, MapListUserRoles::GroupRole); + // root->appendRow(layoutItem); + // mapGroupItemsList->append(layoutItem); + // layoutIndices[layoutId] = i; + // } + // for (int i = 0; i < project->groupNames.length(); i++) { + // QStringList names = project->groupedMapNames.value(i); + // for (int j = 0; j < names.length(); j++) { + // QString map_name = names.value(j); + // QStandardItem *map = createMapItem(map_name, i, j); + // QString layoutId = project->readMapLayoutId(map_name); + // QStandardItem *layoutItem = mapGroupItemsList->at(layoutIndices.value(layoutId)); + // layoutItem->setIcon(mapFolderIcon); + // layoutItem->appendRow(map); + // mapListIndexes.insert(map_name, map->index()); + // } + // } + // break; + // } + // } + + // ui->mapList->setUpdatesEnabled(true); + // ui->mapList->repaint(); + // updateMapList(); +} + +/// !TODO QStandardItem* MainWindow::createMapItem(QString mapName, int groupNum, int inGroupNum) { - QStandardItem *map = new QStandardItem; - map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName); - map->setIcon(*mapIcon); - map->setEditable(false); - map->setData(mapName, Qt::UserRole); - map->setData("map_name", MapListUserRoles::TypeRole); - return map; + // QStandardItem *map = new QStandardItem; + // map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName); + // map->setIcon(*mapIcon); + // map->setEditable(false); + // map->setData(mapName, Qt::UserRole); + // map->setData("map_name", MapListUserRoles::TypeRole); + // return map; } void MainWindow::onOpenMapListContextMenu(const QPoint &point) { - QModelIndex index = mapListProxyModel->mapToSource(ui->mapList->indexAt(point)); - if (!index.isValid()) { - return; - } - - QStandardItem *selectedItem = mapListModel->itemFromIndex(index); - QVariant itemType = selectedItem->data(MapListUserRoles::TypeRole); - if (!itemType.isValid()) { - return; - } - - // Build custom context menu depending on which type of item was selected (map group, map name, etc.) - if (itemType == "map_group") { - QString groupName = selectedItem->data(Qt::UserRole).toString(); - int groupNum = selectedItem->data(MapListUserRoles::GroupRole).toInt(); - QMenu* menu = new QMenu(this); - QActionGroup* actions = new QActionGroup(menu); - actions->addAction(menu->addAction("Add New Map to Group"))->setData(groupNum); - connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToGroupClick); - menu->exec(QCursor::pos()); - } else if (itemType == "map_sec") { - QString secName = selectedItem->data(Qt::UserRole).toString(); - QMenu* menu = new QMenu(this); - QActionGroup* actions = new QActionGroup(menu); - actions->addAction(menu->addAction("Add New Map to Area"))->setData(secName); - connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToAreaClick); - menu->exec(QCursor::pos()); - } else if (itemType == "map_layout") { - QString layoutId = selectedItem->data(MapListUserRoles::TypeRole2).toString(); - QMenu* menu = new QMenu(this); - QActionGroup* actions = new QActionGroup(menu); - actions->addAction(menu->addAction("Add New Map with Layout"))->setData(layoutId); - connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToLayoutClick); - menu->exec(QCursor::pos()); - } + /// !TODO + // QModelIndex index = mapListProxyModel->mapToSource(ui->mapList->indexAt(point)); + // if (!index.isValid()) { + // return; + // } + + // QStandardItem *selectedItem = mapListModel->itemFromIndex(index); + // QVariant itemType = selectedItem->data(MapListUserRoles::TypeRole); + // if (!itemType.isValid()) { + // return; + // } + + // // Build custom context menu depending on which type of item was selected (map group, map name, etc.) + // if (itemType == "map_group") { + // QString groupName = selectedItem->data(Qt::UserRole).toString(); + // int groupNum = selectedItem->data(MapListUserRoles::GroupRole).toInt(); + // QMenu* menu = new QMenu(this); + // QActionGroup* actions = new QActionGroup(menu); + // actions->addAction(menu->addAction("Add New Map to Group"))->setData(groupNum); + // connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToGroupClick); + // menu->exec(QCursor::pos()); + // } else if (itemType == "map_sec") { + // QString secName = selectedItem->data(Qt::UserRole).toString(); + // QMenu* menu = new QMenu(this); + // QActionGroup* actions = new QActionGroup(menu); + // actions->addAction(menu->addAction("Add New Map to Area"))->setData(secName); + // connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToAreaClick); + // menu->exec(QCursor::pos()); + // } else if (itemType == "map_layout") { + // QString layoutId = selectedItem->data(MapListUserRoles::TypeRole2).toString(); + // QMenu* menu = new QMenu(this); + // QActionGroup* actions = new QActionGroup(menu); + // actions->addAction(menu->addAction("Add New Map with Layout"))->setData(layoutId); + // connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToLayoutClick); + // menu->exec(QCursor::pos()); + // } } void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) @@ -1170,14 +1166,15 @@ void MainWindow::onNewMapCreated() { editor->project->saveMap(newMap); editor->project->saveAllDataStructures(); - QStandardItem* groupItem = mapGroupItemsList->at(newMapGroup); - int numMapsInGroup = groupItem->rowCount(); + // !TODO + // QStandardItem* groupItem = mapGroupItemsList->at(newMapGroup); + // int numMapsInGroup = groupItem->rowCount(); - QStandardItem *newMapItem = createMapItem(newMapName, newMapGroup, numMapsInGroup); - groupItem->appendRow(newMapItem); - mapListIndexes.insert(newMapName, newMapItem->index()); + // QStandardItem *newMapItem = createMapItem(newMapName, newMapGroup, numMapsInGroup); + // groupItem->appendRow(newMapItem); + // mapListIndexes.insert(newMapName, newMapItem->index()); - sortMapList(); + // sortMapList(); setMap(newMapName, true); if (newMap->needsHealLocation) { @@ -1362,10 +1359,11 @@ void MainWindow::currentMetatilesSelectionChanged() } } +/// !TODO void MainWindow::on_mapList_activated(const QModelIndex &index) { QVariant data = index.data(Qt::UserRole); - if (index.data(MapListUserRoles::TypeRole) == "map_name" && !data.isNull()) { + if (index.data(MapListRoles::TypeRole) == "map_name" && !data.isNull()) { QString mapName = data.toString(); if (!setMap(mapName)) { QMessageBox msgBox(this); @@ -1378,38 +1376,43 @@ void MainWindow::on_mapList_activated(const QModelIndex &index) } } +/// !TODO something with the projectHasUnsavedChanges var void MainWindow::drawMapListIcons(QAbstractItemModel *model) { - projectHasUnsavedChanges = false; - QList list; - list.append(QModelIndex()); - while (list.length()) { - QModelIndex parent = list.takeFirst(); - for (int i = 0; i < model->rowCount(parent); i++) { - QModelIndex index = model->index(i, 0, parent); - if (model->hasChildren(index)) { - list.append(index); - } - QVariant data = index.data(Qt::UserRole); - if (!data.isNull()) { - QString map_name = data.toString(); - if (editor->project && editor->project->mapCache.contains(map_name)) { - QStandardItem *map = mapListModel->itemFromIndex(mapListIndexes.value(map_name)); - map->setIcon(*mapIcon); - if (editor->project->mapCache.value(map_name)->hasUnsavedChanges()) { - map->setIcon(*mapEditedIcon); - projectHasUnsavedChanges = true; - } - if (editor->map->name == map_name) { - map->setIcon(*mapOpenedIcon); - } - } - } - } - } + // projectHasUnsavedChanges = false; + // QList list; + // list.append(QModelIndex()); + // while (list.length()) { + // QModelIndex parent = list.takeFirst(); + // for (int i = 0; i < model->rowCount(parent); i++) { + // QModelIndex index = model->index(i, 0, parent); + // if (model->hasChildren(index)) { + // list.append(index); + // } + // QVariant data = index.data(Qt::UserRole); + // if (!data.isNull()) { + // QString map_name = data.toString(); + // if (editor->project && editor->project->mapCache.contains(map_name)) { + // QStandardItem *map = mapListModel->itemFromIndex(mapListIndexes.value(map_name)); + // map->setIcon(*mapIcon); + // if (editor->project->mapCache.value(map_name)->hasUnsavedChanges()) { + // map->setIcon(*mapEditedIcon); + // projectHasUnsavedChanges = true; + // } + // if (editor->map->name == map_name) { + // map->setIcon(*mapOpenedIcon); + // } + // } + // } + // } + // } } void MainWindow::updateMapList() { - drawMapListIcons(mapListModel); + //MapGroupModel *model = static_cast(this->ui->mapList->model()); + mapGroupModel->setMap(this->editor->map->name); + groupListProxyModel->layoutChanged(); + //mapGroupModel->layoutChanged(); + // drawMapListIcons(mapListModel); } void MainWindow::on_action_Save_Project_triggered() { @@ -2667,18 +2670,42 @@ void MainWindow::initTilesetEditor() { connect(this->tilesetEditor, &TilesetEditor::tilesetsSaved, this, &MainWindow::onTilesetsSaved); } -void MainWindow::on_toolButton_ExpandAll_clicked() -{ - if (ui->mapList) { - ui->mapList->expandToDepth(0); - } +// void MainWindow::on_toolButton_ExpandAll_clicked() +// { +// if (ui->mapList) { +// ui->mapList->expandToDepth(0); +// } +// } + +// void MainWindow::on_toolButton_CollapseAll_clicked() +// { +// if (ui->mapList) { +// ui->mapList->collapseAll(); +// } +// } + +void MainWindow::on_toolButton_ExpandAll_Groups_clicked() { + // } -void MainWindow::on_toolButton_CollapseAll_clicked() -{ - if (ui->mapList) { - ui->mapList->collapseAll(); - } +void MainWindow::on_toolButton_CollapseAll_Groups_clicked() { + // +} + +void MainWindow::on_toolButton_ExpandAll_Areas_clicked() { + // +} + +void MainWindow::on_toolButton_CollapseAll_Areas_clicked() { + // +} + +void MainWindow::on_toolButton_ExpandAll_Layouts_clicked() { + // +} + +void MainWindow::on_toolButton_CollapseAll_Layouts_clicked() { + // } void MainWindow::on_actionAbout_Porymap_triggered() diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp new file mode 100644 index 000000000..4a8eb262f --- /dev/null +++ b/src/ui/maplistmodels.cpp @@ -0,0 +1,219 @@ +#include "maplistmodels.h" + +#include "project.h" + + + +/* + + // QIcon mapFolderIcon; + // mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); + // mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); + + // QIcon folderIcon; + // folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off); + // //folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On); + + // ui->mapList->setUpdatesEnabled(false); + // mapListModel->clear(); + // mapGroupItemsList->clear(); + // QStandardItem *root = mapListModel->invisibleRootItem(); + + // switch (mapSortOrder) + // { + // case MapSortOrder::Group: + // for (int i = 0; i < project->groupNames.length(); i++) { + // QString group_name = project->groupNames.value(i); + // QStandardItem *group = new QStandardItem; + // group->setText(group_name); + // group->setIcon(mapFolderIcon); + // group->setEditable(false); + // group->setData(group_name, Qt::UserRole); + // group->setData("map_group", MapListUserRoles::TypeRole); + // group->setData(i, MapListUserRoles::GroupRole); + // root->appendRow(group); + // mapGroupItemsList->append(group); + // QStringList names = project->groupedMapNames.value(i); + // for (int j = 0; j < names.length(); j++) { + // QString map_name = names.value(j); + // QStandardItem *map = createMapItem(map_name, i, j); + // group->appendRow(map); + // mapListIndexes.insert(map_name, map->index()); + // } + // } + // break; + + // mapListModel = new QStandardItemModel; + // mapGroupItemsList = new QList; + // mapListProxyModel = new FilterChildrenProxyModel; + + // mapListProxyModel->setSourceModel(mapListModel); + // ui->mapList->setModel(mapListProxyModel); + + // createMapItem: + // QStandardItem *map = new QStandardItem; + // map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName); + // map->setIcon(*mapIcon); + // map->setEditable(false); + // map->setData(mapName, Qt::UserRole); + // map->setData("map_name", MapListUserRoles::TypeRole); + // return map; + + // scrolling: + if (scrollTreeView) { + // Make sure we clear the filter first so we actually have a scroll target + /// !TODO + // mapListProxyModel->setFilterRegularExpression(QString()); + // ui->mapList->setCurrentIndex(mapListProxyModel->mapFromSource(mapListIndexes.value(map_name))); + // ui->mapList->scrollTo(ui->mapList->currentIndex(), QAbstractItemView::PositionAtCenter); + } + + // ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(map_name)), true); + +*/ +MapGroupModel::MapGroupModel(Project *project, QObject *parent) : QStandardItemModel(parent) { + // + + this->project = project; + this->root = this->invisibleRootItem(); + + // mapIcon = new QIcon(QStringLiteral(":/icons/map.ico")); + // mapEditedIcon = new QIcon(QStringLiteral(":/icons/map_edited.ico")); + // mapOpenedIcon = new QIcon(QStringLiteral(":/icons/map_opened.ico")); + + // mapFolderIcon = new QIcon(QStringLiteral(":/icons/folder_closed_map.ico")); + + //mapFolderIcon = new QIcon; + //mapFolderIcon->addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); + //mapFolderIcon->addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); + + initialize(); +} + +QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex) { + QStandardItem *group = new QStandardItem; + group->setText(groupName); + group->setEditable(true); + group->setData(groupName, Qt::UserRole); + group->setData("map_group", MapListRoles::TypeRole); + group->setData(groupIndex, MapListRoles::GroupRole); + // group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + this->groupItems.insert(groupName, group); + return group; +} + +QStandardItem *MapGroupModel::createMapItem(QString mapName, int groupIndex, int mapIndex) { + QStandardItem *map = new QStandardItem; + map->setText(QString("[%1.%2] ").arg(groupIndex).arg(mapIndex, 2, 10, QLatin1Char('0')) + mapName); + map->setEditable(false); + map->setData(mapName, Qt::UserRole); + map->setData("map_name", MapListRoles::TypeRole); + // map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + this->mapItems.insert(mapName, map); + return map; +} + +void MapGroupModel::initialize() { + for (int i = 0; i < this->project->groupNames.length(); i++) { + QString group_name = this->project->groupNames.value(i); + QStandardItem *group = createGroupItem(group_name, i); + root->appendRow(group); + QList groupItems; + QMap inGroupItems; + //mapGroupItemsList->append(group); + QStringList names = this->project->groupedMapNames.value(i); + for (int j = 0; j < names.length(); j++) { + QString map_name = names.value(j); + QStandardItem *map = createMapItem(map_name, i, j); + group->appendRow(map); + } + } +} + +QStandardItem *MapGroupModel::getItem(const QModelIndex &index) const { + if (index.isValid()) { + QStandardItem *item = static_cast(index.internalPointer()); + if (item) + return item; + } + return this->root; +} + +QModelIndex MapGroupModel::indexOfMap(QString mapName) { + if (this->mapItems.contains(mapName)) { + return this->mapItems[mapName]->index(); + } + return QModelIndex(); +} + + // projectHasUnsavedChanges = false; + // QList list; + // list.append(QModelIndex()); + // while (list.length()) { + // QModelIndex parent = list.takeFirst(); + // for (int i = 0; i < model->rowCount(parent); i++) { + // QModelIndex index = model->index(i, 0, parent); + // if (model->hasChildren(index)) { + // list.append(index); + // } + // QVariant data = index.data(Qt::UserRole); + // if (!data.isNull()) { + // QString map_name = data.toString(); + // if (editor->project && editor->project->mapCache.contains(map_name)) { + // QStandardItem *map = mapListModel->itemFromIndex(mapListIndexes.value(map_name)); + // map->setIcon(*mapIcon); + // if (editor->project->mapCache.value(map_name)->hasUnsavedChanges()) { + // map->setIcon(*mapEditedIcon); + // projectHasUnsavedChanges = true; + // } + // if (editor->map->name == map_name) { + // map->setIcon(*mapOpenedIcon); + // } + // } + // } + // } + // } + +#include +QVariant MapGroupModel::data(const QModelIndex &index, int role) const { + int row = index.row(); + int col = index.column(); + + if (role == Qt::DecorationRole) { + static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico")); + static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico")); + static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico")); + + static QIcon mapFolderIcon; + static bool loaded = false; + if (!loaded) { + mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); + mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); + loaded = true; + } + + QStandardItem *item = this->getItem(index)->child(row, col); + QString type = item->data(MapListRoles::TypeRole).toString(); + + if (type == "map_group") { + return mapFolderIcon; + } else if (type == "map_name") { + QString mapName = item->data(Qt::UserRole).toString(); + if (mapName == this->openMap) { + return mapOpenedIcon; + } + else if (this->project->mapCache.contains(mapName)) { + if (this->project->mapCache.value(mapName)->hasUnsavedChanges()) { + return mapEditedIcon; + } + } + return mapIcon; + } + + // check if map or group + // if map, check if edited or open + //return QIcon(":/icons/porymap-icon-2.ico"); + } + + return QStandardItemModel::data(index, role); +} From 2bc51f1c291e339c7fb7964ee47f3985a9259cd6 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 1 Feb 2023 10:09:50 -0500 Subject: [PATCH 03/70] move map pixmap item and metatile rendering from Map to Layout --- forms/mainwindow.ui | 5 +- include/config.h | 8 +- include/core/editcommands.h | 39 +- include/core/map.h | 18 +- include/core/maplayout.h | 70 +++- include/core/mapparser.h | 2 +- include/editor.h | 13 +- include/mainwindow.h | 15 + include/project.h | 14 +- include/ui/bordermetatilespixmapitem.h | 10 +- include/ui/collisionpixmapitem.h | 10 +- .../{mappixmapitem.h => layoutpixmapitem.h} | 39 +- include/ui/maplistmodels.h | 38 +- include/ui/newmappopup.h | 4 +- porymap.pro | 4 +- src/config.cpp | 14 +- src/core/editcommands.cpp | 114 +++--- src/core/map.cpp | 53 +-- src/core/maplayout.cpp | 358 +++++++++++++++++- src/editor.cpp | 80 ++-- src/mainwindow.cpp | 135 +++++-- src/project.cpp | 15 +- src/ui/bordermetatilespixmapitem.cpp | 30 +- src/ui/collisionpixmapitem.cpp | 53 +-- ...mappixmapitem.cpp => layoutpixmapitem.cpp} | 269 ++++++------- src/ui/maplistmodels.cpp | 143 +++++++ src/ui/newmappopup.cpp | 6 +- 27 files changed, 1115 insertions(+), 444 deletions(-) rename include/ui/{mappixmapitem.h => layoutpixmapitem.h} (83%) rename src/ui/{mappixmapitem.cpp => layoutpixmapitem.cpp} (65%) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index fb340222d..a59c0ad06 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -180,7 +180,7 @@ - + Areas @@ -443,6 +443,9 @@ QAbstractItemView::SelectItems + + false + false diff --git a/include/config.h b/include/config.h index 7f10ce917..923abae27 100644 --- a/include/config.h +++ b/include/config.h @@ -16,9 +16,9 @@ #define CONFIG_BACKWARDS_COMPATABILITY enum MapSortOrder { - Group = 0, - Area = 1, - Layout = 2, + SortByGroup = 0, + SortByArea = 1, + SortByLayout = 2, }; class KeyValueConfigBase @@ -51,7 +51,7 @@ class PorymapConfig: public KeyValueConfigBase virtual void reset() override { this->recentProject = ""; this->reopenOnLaunch = true; - this->mapSortOrder = MapSortOrder::Group; + this->mapSortOrder = MapSortOrder::SortByGroup; this->prettyCursors = true; this->collisionOpacity = 50; this->metatilesZoom = 30; diff --git a/include/core/editcommands.h b/include/core/editcommands.h index ea66b7229..6cfaf3b99 100644 --- a/include/core/editcommands.h +++ b/include/core/editcommands.h @@ -7,8 +7,8 @@ #include #include -class MapPixmapItem; class Map; +class Layout; class Blockdata; class Event; class DraggablePixmapItem; @@ -43,7 +43,7 @@ enum CommandId { /// onto the map using the pencil tool. class PaintMetatile : public QUndoCommand { public: - PaintMetatile(Map *map, + PaintMetatile(Layout *layout, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, unsigned actionId, QUndoCommand *parent = nullptr); @@ -54,7 +54,7 @@ class PaintMetatile : public QUndoCommand { int id() const override { return CommandId::ID_PaintMetatile; } private: - Map *map; + Layout *layout; Blockdata newMetatiles; Blockdata oldMetatiles; @@ -68,10 +68,10 @@ class PaintMetatile : public QUndoCommand { /// on the metatile collision and elevation. class PaintCollision : public PaintMetatile { public: - PaintCollision(Map *map, + PaintCollision(Layout *layout, const Blockdata &oldCollision, const Blockdata &newCollision, unsigned actionId, QUndoCommand *parent = nullptr) - : PaintMetatile(map, oldCollision, newCollision, actionId, parent) { + : PaintMetatile(layout, oldCollision, newCollision, actionId, parent) { setText("Paint Collision"); } @@ -83,7 +83,7 @@ class PaintCollision : public PaintMetatile { /// Implements a command to commit paint actions on the map border. class PaintBorder : public QUndoCommand { public: - PaintBorder(Map *map, + PaintBorder(Layout *layout, const Blockdata &oldBorder, const Blockdata &newBorder, unsigned actionId, QUndoCommand *parent = nullptr); @@ -94,7 +94,7 @@ class PaintBorder : public QUndoCommand { int id() const override { return CommandId::ID_PaintBorder; } private: - Map *map; + Layout *layout; Blockdata newBorder; Blockdata oldBorder; @@ -108,10 +108,10 @@ class PaintBorder : public QUndoCommand { /// with the bucket tool onto the map. class BucketFillMetatile : public PaintMetatile { public: - BucketFillMetatile(Map *map, + BucketFillMetatile(Layout *layout, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, unsigned actionId, QUndoCommand *parent = nullptr) - : PaintMetatile(map, oldMetatiles, newMetatiles, actionId, parent) { + : PaintMetatile(layout, oldMetatiles, newMetatiles, actionId, parent) { setText("Bucket Fill Metatiles"); } @@ -124,10 +124,10 @@ class BucketFillMetatile : public PaintMetatile { /// on the metatile collision and elevation. class BucketFillCollision : public PaintCollision { public: - BucketFillCollision(Map *map, + BucketFillCollision(Layout *layout, const Blockdata &oldCollision, const Blockdata &newCollision, QUndoCommand *parent = nullptr) - : PaintCollision(map, oldCollision, newCollision, -1, parent) { + : PaintCollision(layout, oldCollision, newCollision, -1, parent) { setText("Flood Fill Collision"); } @@ -141,10 +141,10 @@ class BucketFillCollision : public PaintCollision { /// with the bucket or paint tool onto the map. class MagicFillMetatile : public PaintMetatile { public: - MagicFillMetatile(Map *map, + MagicFillMetatile(Layout *layout, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, unsigned actionId, QUndoCommand *parent = nullptr) - : PaintMetatile(map, oldMetatiles, newMetatiles, actionId, parent) { + : PaintMetatile(layout, oldMetatiles, newMetatiles, actionId, parent) { setText("Magic Fill Metatiles"); } @@ -156,10 +156,10 @@ class MagicFillMetatile : public PaintMetatile { /// Implements a command to commit magic fill collision actions. class MagicFillCollision : public PaintCollision { public: - MagicFillCollision(Map *map, + MagicFillCollision(Layout *layout, const Blockdata &oldCollision, const Blockdata &newCollision, QUndoCommand *parent = nullptr) - : PaintCollision(map, oldCollision, newCollision, -1, parent) { + : PaintCollision(layout, oldCollision, newCollision, -1, parent) { setText("Magic Fill Collision"); } @@ -172,7 +172,7 @@ class MagicFillCollision : public PaintCollision { /// Implements a command to commit metatile shift actions. class ShiftMetatiles : public QUndoCommand { public: - ShiftMetatiles(Map *map, + ShiftMetatiles(Layout *layout, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, unsigned actionId, QUndoCommand *parent = nullptr); @@ -183,7 +183,7 @@ class ShiftMetatiles : public QUndoCommand { int id() const override { return CommandId::ID_ShiftMetatiles; } private: - Map *map; + Layout *layout= nullptr; Blockdata newMetatiles; Blockdata oldMetatiles; @@ -196,7 +196,7 @@ class ShiftMetatiles : public QUndoCommand { /// Implements a command to commit a map or border resize action. class ResizeMap : public QUndoCommand { public: - ResizeMap(Map *map, QSize oldMapDimensions, QSize newMapDimensions, + ResizeMap(Layout *layout, QSize oldMapDimensions, QSize newMapDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, QSize oldBorderDimensions, QSize newBorderDimensions, const Blockdata &oldBorder, const Blockdata &newBorder, @@ -209,7 +209,7 @@ class ResizeMap : public QUndoCommand { int id() const override { return CommandId::ID_ResizeMap; } private: - Map *map; + Layout *layout = nullptr; int oldMapWidth; int oldMapHeight; @@ -342,6 +342,7 @@ class EventPaste : public EventDuplicate { +// !TODO /// Implements a command to commit map edits from the scripting API. /// The scripting api can edit map/border blocks and dimensions. class ScriptEditMap : public QUndoCommand { diff --git a/include/core/map.h b/include/core/map.h index d0617c43c..33105c50c 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -25,7 +25,7 @@ // 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 LayoutPixmapItem; class CollisionPixmapItem; class BorderMetatilesPixmapItem; @@ -58,7 +58,7 @@ class Map : public QObject QMap customHeaders; - MapLayout *layout; + Layout *layout = nullptr; bool isPersistedToFile = true; bool hasUnsavedDataChanges = false; @@ -76,6 +76,7 @@ class Map : public QObject QList connections; + // !TODO QList metatileLayerOrder; QList metatileLayerOpacity; @@ -92,17 +93,19 @@ class Map : public QObject void modify(); void clean(); - QPixmap render(bool ignoreCache = false, MapLayout *fromLayout = nullptr, QRect bounds = QRect(0, 0, -1, -1)); + QPixmap render(bool ignoreCache = false, Layout *fromLayout = nullptr, QRect bounds = QRect(0, 0, -1, -1)); QPixmap renderCollision(bool ignoreCache); - QPixmap renderConnection(MapConnection, MapLayout *); + QPixmap renderConnection(MapConnection, Layout *); QPixmap renderBorder(bool ignoreCache = false); bool mapBlockChanged(int i, const Blockdata &cache); bool borderBlockChanged(int i, const Blockdata &cache); + // !TODO: remove void cacheBlockdata(); void cacheCollision(); + /// !TODO: remove this bool getBlock(int x, int y, Block *out); void setBlock(int x, int y, Block block, bool enableScriptCallback = false); void setBlockdata(Blockdata blockdata, bool enableScriptCallback = false); @@ -133,8 +136,11 @@ class Map : public QObject void openScript(QString label); - MapPixmapItem *mapItem = nullptr; - void setMapItem(MapPixmapItem *item) { mapItem = item; } +private: + LayoutPixmapItem *mapItem = nullptr; + +public: + void setMapItem(LayoutPixmapItem *item) { mapItem = item; } CollisionPixmapItem *collisionItem = nullptr; void setCollisionItem(CollisionPixmapItem *item) { collisionItem = item; } diff --git a/include/core/maplayout.h b/include/core/maplayout.h index 41fa6946e..ffbe61275 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -7,12 +7,17 @@ #include #include #include +#include class Map; +class LayoutPixmapItem; +class CollisionPixmapItem; +class BorderMetatilesPixmapItem; -class MapLayout { +class Layout : public QObject { + Q_OBJECT public: - MapLayout() {} + Layout() {} static QString layoutConstantFromName(QString mapName); @@ -39,8 +44,12 @@ class MapLayout { Blockdata blockdata; + QImage image; + QPixmap pixmap; QImage border_image; QPixmap border_pixmap; + QImage collision_image; + QPixmap collision_pixmap; Blockdata border; Blockdata cached_blockdata; @@ -53,10 +62,67 @@ class MapLayout { QSize borderDimensions; } lastCommitBlocks; // to track map changes + QList metatileLayerOrder; + QList metatileLayerOpacity; + + LayoutPixmapItem *layoutItem = nullptr; + CollisionPixmapItem *collisionItem = nullptr; + BorderMetatilesPixmapItem *borderItem = nullptr; + + QUndoStack editHistory; + +public: int getWidth(); int getHeight(); int getBorderWidth(); int getBorderHeight(); + + bool isWithinBounds(int x, int y) { + return (x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight()); + } + + bool getBlock(int x, int y, Block *out); + void setBlock(int x, int y, Block block, bool enableScriptCallback = false); + void setBlockdata(Blockdata blockdata, bool enableScriptCallback = false); + + void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); + void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); + + void cacheBlockdata(); + void cacheCollision(); + void clearBorderCache(); + void cacheBorder(); + + bool layoutBlockChanged(int i, const Blockdata &cache); + + uint16_t getBorderMetatileId(int x, int y); + void setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback = false); + void setBorderBlockData(Blockdata blockdata, bool enableScriptCallback = false); + + 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); + + QPixmap render(bool ignoreCache = false, Layout *fromLayout = nullptr, QRect bounds = QRect(0, 0, -1, -1)); + QPixmap renderCollision(bool ignoreCache); + // QPixmap renderConnection(MapConnection, Layout *); + QPixmap renderBorder(bool ignoreCache = false); + + void setLayoutItem(LayoutPixmapItem *item) { layoutItem = item; } + void setCollisionItem(CollisionPixmapItem *item) { collisionItem = item; } + void setBorderItem(BorderMetatilesPixmapItem *item) { borderItem = item; } + +private: + void setNewDimensionsBlockdata(int newWidth, int newHeight); + void setNewBorderDimensionsBlockdata(int newWidth, int newHeight); + +signals: + void layoutChanged(Layout *layout); + void modified(); + void layoutDimensionsChanged(const QSize &size); + void needsRedrawing(); }; +using MapLayout = Layout; + #endif // MAPLAYOUT_H diff --git a/include/core/mapparser.h b/include/core/mapparser.h index 21e3074e4..4032154a5 100644 --- a/include/core/mapparser.h +++ b/include/core/mapparser.h @@ -10,7 +10,7 @@ class MapParser { public: MapParser(); - MapLayout *parse(QString filepath, bool *error, Project *project); + Layout *parse(QString filepath, bool *error, Project *project); }; #endif // MAPPARSER_H diff --git a/include/editor.h b/include/editor.h index 0b0bc5910..8f12d88f8 100644 --- a/include/editor.h +++ b/include/editor.h @@ -20,7 +20,7 @@ #include "connectionpixmapitem.h" #include "currentselectedmetatilespixmapitem.h" #include "collisionpixmapitem.h" -#include "mappixmapitem.h" +#include "layoutpixmapitem.h" #include "settings.h" #include "movablerect.h" #include "cursortilerect.h" @@ -46,7 +46,7 @@ class Editor : public QObject Project *project = nullptr; Map *map = nullptr; - MapLayout *layout = nullptr; /* NEW */ + Layout *layout = nullptr; /* NEW */ QUndoGroup editGroup; // Manages the undo history for each map @@ -60,6 +60,7 @@ class Editor : public QObject void closeProject(); bool setMap(QString map_name); + void unsetMap(); Tileset *getCurrentMapPrimaryTileset(); @@ -123,7 +124,7 @@ class Editor : public QObject QGraphicsScene *scene = nullptr; QGraphicsPixmapItem *current_view = nullptr; - MapPixmapItem *map_item = nullptr; + LayoutPixmapItem *map_item = nullptr; ConnectionPixmapItem* selected_connection_item = nullptr; QList connection_items; QGraphicsPathItem *connection_mask = nullptr; @@ -201,11 +202,11 @@ public slots: qint64 *pid = nullptr); private slots: - void onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); - void onMapEndPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); + void onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item); + void onMapEndPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item); void setSmartPathCursorMode(QGraphicsSceneMouseEvent *event); void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event); - void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); + void mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item); void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item); void onConnectionMoved(MapConnection*); void onConnectionItemSelected(ConnectionPixmapItem* connectionItem); diff --git a/include/mainwindow.h b/include/mainwindow.h index 09d39f3a5..18b947f9f 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -164,8 +164,13 @@ public slots: private slots: void on_action_Open_Project_triggered(); void on_action_Reload_Project_triggered(); + void on_mapList_activated(const QModelIndex &index); + void on_areaList_activated(const QModelIndex &index); + void on_layoutList_activated(const QModelIndex &index); + void on_action_Save_Project_triggered(); + void openWarpMap(QString map_name, int event_id, Event::Group event_group); void duplicate(); @@ -229,6 +234,7 @@ private slots: void on_toolButton_Move_clicked(); void on_toolButton_Shift_clicked(); + void on_mapListContainer_currentChanged(int index); void onOpenMapListContextMenu(const QPoint &point); void onAddNewMapToGroupClick(QAction* triggeredAction); void onAddNewMapToAreaClick(QAction* triggeredAction); @@ -310,6 +316,11 @@ private slots: FilterChildrenProxyModel *groupListProxyModel; MapGroupModel *mapGroupModel; + + FilterChildrenProxyModel *layoutListProxyModel; + LayoutTreeModel *layoutTreeModel; + + // QStandardItemModel *mapListModel; // QList *mapGroupItemsList; // QMap mapListIndexes; @@ -342,10 +353,14 @@ private slots: bool newMapDefaultsSet = false; MapSortOrder mapSortOrder; + enum MapListTab { Groups, Areas, Layouts }; bool tilesetNeedsRedraw = false; + bool setLayout(QString layoutName); + bool setMap(QString, bool scrollTreeView = false); + void unsetMap(); void redrawMapScene(); void refreshMapScene(); bool loadDataStructures(); diff --git a/include/project.h b/include/project.h index 05029df32..dd2e044b6 100644 --- a/include/project.h +++ b/include/project.h @@ -56,8 +56,9 @@ class Project : public QObject QStringList mapLayoutsTable; QStringList mapLayoutsTableMaster; QString layoutsLabel; - QMap mapLayouts; - QMap mapLayoutsMaster; + QMap layoutIdsToNames; + QMap mapLayouts; + QMap mapLayoutsMaster; QMap mapSecToMapHoverName; QMap mapSectionNameToValue; QMap mapSectionValueToName; @@ -115,8 +116,8 @@ class Project : public QObject QStringList tilesetLabelsOrdered; Blockdata readBlockdata(QString); - bool loadBlockdata(MapLayout*); - bool loadLayoutBorder(MapLayout*); + bool loadBlockdata(Layout *); + bool loadLayoutBorder(Layout *); void saveTextFile(QString path, QString text); void appendTextFile(QString path, QString text); @@ -128,6 +129,7 @@ class Project : public QObject QString getProjectTitle(); QString readMapLayoutId(QString map_name); + QString readMapLayoutName(QString mapName); QString readMapLocation(QString map_name); bool readWildMonData(); @@ -143,9 +145,9 @@ class Project : public QObject QSet getTopLevelMapFields(); bool loadMapData(Map*); bool readMapLayouts(); - bool loadLayout(MapLayout *); + bool loadLayout(Layout *); bool loadMapLayout(Map*); - bool loadLayoutTilesets(MapLayout*); + bool loadLayoutTilesets(Layout *); void loadTilesetAssets(Tileset*); void loadTilesetTiles(Tileset*, QImage); void loadTilesetMetatiles(Tileset*); diff --git a/include/ui/bordermetatilespixmapitem.h b/include/ui/bordermetatilespixmapitem.h index f4af8bfe6..cf2ba0d42 100644 --- a/include/ui/bordermetatilespixmapitem.h +++ b/include/ui/bordermetatilespixmapitem.h @@ -1,21 +1,21 @@ #ifndef BORDERMETATILESPIXMAPITEM_H #define BORDERMETATILESPIXMAPITEM_H -#include "map.h" +#include "maplayout.h" #include "metatileselector.h" #include class BorderMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: - BorderMetatilesPixmapItem(Map *map_, MetatileSelector *metatileSelector) { - this->map = map_; - this->map->setBorderItem(this); + BorderMetatilesPixmapItem(Layout *layout, MetatileSelector *metatileSelector) { + this->layout = layout; + this->layout->setBorderItem(this); this->metatileSelector = metatileSelector; setAcceptHoverEvents(true); } MetatileSelector *metatileSelector; - Map *map; + Layout *layout; void draw(); signals: void hoveredBorderMetatileSelectionChanged(uint16_t); diff --git a/include/ui/collisionpixmapitem.h b/include/ui/collisionpixmapitem.h index 2e3e74e30..0e4afd6c3 100644 --- a/include/ui/collisionpixmapitem.h +++ b/include/ui/collisionpixmapitem.h @@ -3,18 +3,18 @@ #include "metatileselector.h" #include "movementpermissionsselector.h" -#include "mappixmapitem.h" +#include "layoutpixmapitem.h" #include "map.h" #include "settings.h" -class CollisionPixmapItem : public MapPixmapItem { +class CollisionPixmapItem : public LayoutPixmapItem { Q_OBJECT public: - CollisionPixmapItem(Map *map, MovementPermissionsSelector *movementPermissionsSelector, MetatileSelector *metatileSelector, Settings *settings, qreal *opacity) - : MapPixmapItem(map, metatileSelector, settings){ + CollisionPixmapItem(Layout *layout, MovementPermissionsSelector *movementPermissionsSelector, MetatileSelector *metatileSelector, Settings *settings, qreal *opacity) + : LayoutPixmapItem(layout, metatileSelector, settings){ this->movementPermissionsSelector = movementPermissionsSelector; this->opacity = opacity; - map->setCollisionItem(this); + layout->setCollisionItem(this); } MovementPermissionsSelector *movementPermissionsSelector; qreal *opacity; diff --git a/include/ui/mappixmapitem.h b/include/ui/layoutpixmapitem.h similarity index 83% rename from include/ui/mappixmapitem.h rename to include/ui/layoutpixmapitem.h index cd2d335cd..ab4d94a51 100644 --- a/include/ui/mappixmapitem.h +++ b/include/ui/layoutpixmapitem.h @@ -1,12 +1,13 @@ #ifndef MAPPIXMAPITEM_H #define MAPPIXMAPITEM_H -#include "map.h" #include "settings.h" #include "metatileselector.h" #include -class MapPixmapItem : public QObject, public QGraphicsPixmapItem { +class Layout; + +class LayoutPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT private: @@ -18,37 +19,49 @@ class MapPixmapItem : public QObject, public QGraphicsPixmapItem { Metatiles, EventObjects }; - MapPixmapItem(Map *map_, MetatileSelector *metatileSelector, Settings *settings) { - this->map = map_; - this->map->setMapItem(this); + + LayoutPixmapItem(Layout *layout, MetatileSelector *metatileSelector, Settings *settings) { + this->layout = layout; + // this->map->setMapItem(this); this->metatileSelector = metatileSelector; this->settings = settings; this->paintingMode = PaintMode::Metatiles; - this->lockedAxis = MapPixmapItem::Axis::None; + this->lockedAxis = LayoutPixmapItem::Axis::None; this->prevStraightPathState = false; setAcceptHoverEvents(true); } - MapPixmapItem::PaintMode paintingMode; - Map *map; + + LayoutPixmapItem::PaintMode paintingMode; + + Layout *layout; + MetatileSelector *metatileSelector; + Settings *settings; + bool active; bool has_mouse = false; bool right_click; + int paint_tile_initial_x; int paint_tile_initial_y; bool prevStraightPathState; int straight_path_initial_x; int straight_path_initial_y; + QPoint metatilePos; + enum Axis { None = 0, X, Y }; - MapPixmapItem::Axis lockedAxis; + + LayoutPixmapItem::Axis lockedAxis; + QPoint selection_origin; QList selection; + virtual void paint(QGraphicsSceneMouseEvent*); virtual void floodFill(QGraphicsSceneMouseEvent*); virtual void magicFill(QGraphicsSceneMouseEvent*); @@ -70,11 +83,13 @@ class MapPixmapItem : public QObject, public QGraphicsPixmapItem { QList selectedCollisions, bool fromScriptCall = false); void floodFillSmartPath(int initialX, int initialY, bool fromScriptCall = false); + virtual void pick(QGraphicsSceneMouseEvent*); virtual void select(QGraphicsSceneMouseEvent*); virtual void shift(QGraphicsSceneMouseEvent*); void shift(int xDelta, int yDelta, bool fromScriptCall = false); virtual void draw(bool ignoreCache = false); + void updateMetatileSelection(QGraphicsSceneMouseEvent *event); void paintNormal(int x, int y, bool fromScriptCall = false); void lockNondominantAxis(QGraphicsSceneMouseEvent *event); @@ -87,9 +102,9 @@ class MapPixmapItem : public QObject, public QGraphicsPixmapItem { unsigned actionId_ = 0; signals: - void startPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *); - void endPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *); - void mouseEvent(QGraphicsSceneMouseEvent *, MapPixmapItem *); + void startPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *); + void endPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *); + void mouseEvent(QGraphicsSceneMouseEvent *, LayoutPixmapItem *); void hoveredMapMetatileChanged(const QPoint &pos); void hoveredMapMetatileCleared(); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 972c86681..d15adcd3d 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -46,10 +46,40 @@ class MapGroupModel : public QStandardItemModel { QString openMap; - // QIcon *mapIcon = nullptr; - // QIcon *mapEditedIcon = nullptr; - // QIcon *mapOpenedIcon = nullptr; - // QIcon *mapFolderIcon = nullptr; +signals: + void edited(); +}; + + + +class LayoutTreeModel : public QStandardItemModel { + Q_OBJECT + +public: + LayoutTreeModel(Project *project, QObject *parent = nullptr); + ~LayoutTreeModel() {} + + QVariant data(const QModelIndex &index, int role) const override; + +public: + void setLayout(QString layoutName) { this->openLayout = layoutName; } + + QStandardItem *createLayoutItem(QString layoutName); + QStandardItem *createMapItem(QString mapName); + + QStandardItem *getItem(const QModelIndex &index) const; + QModelIndex indexOfLayout(QString layoutName); + + void initialize(); + +private: + Project *project; + QStandardItem *root = nullptr; + + QMap layoutItems; + QMap mapItems; + + QString openLayout; signals: void edited(); diff --git a/include/ui/newmappopup.h b/include/ui/newmappopup.h index 826e1609f..e668e8632 100644 --- a/include/ui/newmappopup.h +++ b/include/ui/newmappopup.h @@ -24,7 +24,7 @@ class NewMapPopup : public QMainWindow QString layoutId; void init(); void init(MapSortOrder type, QVariant data); - void init(MapLayout *); + void init(Layout *); static void setDefaultSettings(Project *project); signals: @@ -37,7 +37,7 @@ class NewMapPopup : public QMainWindow bool checkNewMapGroup(); void saveSettings(); void useLayout(QString layoutId); - void useLayoutSettings(MapLayout *mapLayout); + void useLayoutSettings(Layout *mapLayout); struct Settings { QString group; diff --git a/porymap.pro b/porymap.pro index 7e39f0f82..a6df62240 100644 --- a/porymap.pro +++ b/porymap.pro @@ -61,7 +61,7 @@ SOURCES += src/core/block.cpp \ src/ui/maplistmodels.cpp \ src/ui/graphicsview.cpp \ src/ui/imageproviders.cpp \ - src/ui/mappixmapitem.cpp \ + src/ui/layoutpixmapitem.cpp \ src/ui/prefabcreationdialog.cpp \ src/ui/regionmappixmapitem.cpp \ src/ui/citymappixmapitem.cpp \ @@ -151,7 +151,7 @@ HEADERS += include/core/block.h \ include/ui/maplistmodels.h \ include/ui/graphicsview.h \ include/ui/imageproviders.h \ - include/ui/mappixmapitem.h \ + include/ui/layoutpixmapitem.h \ include/ui/mapview.h \ include/ui/prefabcreationdialog.h \ include/ui/regionmappixmapitem.h \ diff --git a/src/config.cpp b/src/config.cpp index 681dc3f90..9dddcd427 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -172,15 +172,15 @@ void KeyValueConfigBase::setSaveDisabled(bool disabled) { } const QMap mapSortOrderMap = { - {MapSortOrder::Group, "group"}, - {MapSortOrder::Layout, "layout"}, - {MapSortOrder::Area, "area"}, + {MapSortOrder::SortByGroup, "group"}, + {MapSortOrder::SortByLayout, "layout"}, + {MapSortOrder::SortByArea, "area"}, }; const QMap mapSortOrderReverseMap = { - {"group", MapSortOrder::Group}, - {"layout", MapSortOrder::Layout}, - {"area", MapSortOrder::Area}, + {"group", MapSortOrder::SortByGroup}, + {"layout", MapSortOrder::SortByLayout}, + {"area", MapSortOrder::SortByArea}, }; PorymapConfig porymapConfig; @@ -209,7 +209,7 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { if (mapSortOrderReverseMap.contains(sortOrder)) { this->mapSortOrder = mapSortOrderReverseMap.value(sortOrder); } else { - this->mapSortOrder = MapSortOrder::Group; + this->mapSortOrder = MapSortOrder::SortByGroup; logWarn(QString("Invalid config value for map_sort_order: '%1'. Must be 'group', 'area', or 'layout'.").arg(value)); } } else if (key == "main_window_geometry") { diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp index 394c51cbc..91ea18b38 100644 --- a/src/core/editcommands.cpp +++ b/src/core/editcommands.cpp @@ -1,5 +1,4 @@ #include "editcommands.h" -#include "mappixmapitem.h" #include "draggablepixmapitem.h" #include "bordermetatilespixmapitem.h" #include "editor.h" @@ -25,17 +24,18 @@ int getEventTypeMask(QList events) { return eventTypeMask; } -void renderMapBlocks(Map *map, bool ignoreCache = false) { - map->mapItem->draw(ignoreCache); - map->collisionItem->draw(ignoreCache); +/// !TODO: +void renderBlocks(Layout *layout, bool ignoreCache = false) { + layout->layoutItem->draw(ignoreCache); + layout->collisionItem->draw(ignoreCache); } -PaintMetatile::PaintMetatile(Map *map, +PaintMetatile::PaintMetatile(Layout *layout, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, unsigned actionId, QUndoCommand *parent) : QUndoCommand(parent) { setText("Paint Metatiles"); - this->map = map; + this->layout = layout; this->oldMetatiles = oldMetatiles; this->newMetatiles = newMetatiles; @@ -45,23 +45,23 @@ PaintMetatile::PaintMetatile(Map *map, void PaintMetatile::redo() { QUndoCommand::redo(); - if (!map) return; + if (!layout) return; - map->setBlockdata(newMetatiles, true); + layout->setBlockdata(newMetatiles, true); - map->layout->lastCommitBlocks.blocks = map->layout->blockdata; + layout->lastCommitBlocks.blocks = layout->blockdata; - renderMapBlocks(map); + renderBlocks(layout); } void PaintMetatile::undo() { - if (!map) return; + if (!layout) return; - map->setBlockdata(oldMetatiles, true); + layout->setBlockdata(oldMetatiles, true); - map->layout->lastCommitBlocks.blocks = map->layout->blockdata; + layout->lastCommitBlocks.blocks = layout->blockdata; - renderMapBlocks(map); + renderBlocks(layout); QUndoCommand::undo(); } @@ -69,7 +69,7 @@ void PaintMetatile::undo() { bool PaintMetatile::mergeWith(const QUndoCommand *command) { const PaintMetatile *other = static_cast(command); - if (map != other->map) + if (layout != other->layout) return false; if (actionId != other->actionId) @@ -84,12 +84,12 @@ bool PaintMetatile::mergeWith(const QUndoCommand *command) { ************************************************************************ ******************************************************************************/ -PaintBorder::PaintBorder(Map *map, +PaintBorder::PaintBorder(Layout *layout, const Blockdata &oldBorder, const Blockdata &newBorder, unsigned actionId, QUndoCommand *parent) : QUndoCommand(parent) { setText("Paint Border"); - this->map = map; + this->layout = layout; this->oldBorder = oldBorder; this->newBorder = newBorder; @@ -99,23 +99,23 @@ PaintBorder::PaintBorder(Map *map, void PaintBorder::redo() { QUndoCommand::redo(); - if (!map) return; + if (!layout) return; - map->setBorderBlockData(newBorder, true); + layout->setBorderBlockData(newBorder, true); - map->layout->lastCommitBlocks.border = map->layout->border; + layout->lastCommitBlocks.border = layout->border; - map->borderItem->draw(); + layout->borderItem->draw(); } void PaintBorder::undo() { - if (!map) return; + if (!layout) return; - map->setBorderBlockData(oldBorder, true); + layout->setBorderBlockData(oldBorder, true); - map->layout->lastCommitBlocks.border = map->layout->border; + layout->lastCommitBlocks.border = layout->border; - map->borderItem->draw(); + layout->borderItem->draw(); QUndoCommand::undo(); } @@ -124,12 +124,12 @@ void PaintBorder::undo() { ************************************************************************ ******************************************************************************/ -ShiftMetatiles::ShiftMetatiles(Map *map, +ShiftMetatiles::ShiftMetatiles(Layout *layout, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, unsigned actionId, QUndoCommand *parent) : QUndoCommand(parent) { setText("Shift Metatiles"); - this->map = map; + this->layout = layout; this->oldMetatiles = oldMetatiles; this->newMetatiles = newMetatiles; @@ -139,23 +139,23 @@ ShiftMetatiles::ShiftMetatiles(Map *map, void ShiftMetatiles::redo() { QUndoCommand::redo(); - if (!map) return; + if (!layout) return; - map->setBlockdata(newMetatiles, true); + layout->setBlockdata(newMetatiles, true); - map->layout->lastCommitBlocks.blocks = map->layout->blockdata; + layout->lastCommitBlocks.blocks = layout->blockdata; - renderMapBlocks(map, true); + renderBlocks(layout, true); } void ShiftMetatiles::undo() { - if (!map) return; + if (!layout) return; - map->setBlockdata(oldMetatiles, true); + layout->setBlockdata(oldMetatiles, true); - map->layout->lastCommitBlocks.blocks = map->layout->blockdata; + layout->lastCommitBlocks.blocks = layout->blockdata; - renderMapBlocks(map, true); + renderBlocks(layout, true); QUndoCommand::undo(); } @@ -163,7 +163,7 @@ void ShiftMetatiles::undo() { bool ShiftMetatiles::mergeWith(const QUndoCommand *command) { const ShiftMetatiles *other = static_cast(command); - if (this->map != other->map) + if (this->layout != other->layout) return false; if (actionId != other->actionId) @@ -178,14 +178,14 @@ bool ShiftMetatiles::mergeWith(const QUndoCommand *command) { ************************************************************************ ******************************************************************************/ -ResizeMap::ResizeMap(Map *map, QSize oldMapDimensions, QSize newMapDimensions, +ResizeMap::ResizeMap(Layout *layout, QSize oldMapDimensions, QSize newMapDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, QSize oldBorderDimensions, QSize newBorderDimensions, const Blockdata &oldBorder, const Blockdata &newBorder, QUndoCommand *parent) : QUndoCommand(parent) { setText("Resize Map"); - this->map = map; + this->layout = layout; this->oldMapWidth = oldMapDimensions.width(); this->oldMapHeight = oldMapDimensions.height(); @@ -209,33 +209,33 @@ ResizeMap::ResizeMap(Map *map, QSize oldMapDimensions, QSize newMapDimensions, void ResizeMap::redo() { QUndoCommand::redo(); - if (!map) return; + if (!layout) return; - map->layout->blockdata = newMetatiles; - map->setDimensions(newMapWidth, newMapHeight, false, true); + layout->blockdata = newMetatiles; + layout->setDimensions(newMapWidth, newMapHeight, false, true); - map->layout->border = newBorder; - map->setBorderDimensions(newBorderWidth, newBorderHeight, false, true); + layout->border = newBorder; + layout->setBorderDimensions(newBorderWidth, newBorderHeight, false, true); - map->layout->lastCommitBlocks.mapDimensions = QSize(map->getWidth(), map->getHeight()); - map->layout->lastCommitBlocks.borderDimensions = QSize(map->getBorderWidth(), map->getBorderHeight()); + layout->lastCommitBlocks.mapDimensions = QSize(layout->getWidth(), layout->getHeight()); + layout->lastCommitBlocks.borderDimensions = QSize(layout->getBorderWidth(), layout->getBorderHeight()); - map->mapNeedsRedrawing(); + layout->needsRedrawing(); } void ResizeMap::undo() { - if (!map) return; + if (!layout) return; - map->layout->blockdata = oldMetatiles; - map->setDimensions(oldMapWidth, oldMapHeight, false, true); + layout->blockdata = oldMetatiles; + layout->setDimensions(oldMapWidth, oldMapHeight, false, true); - map->layout->border = oldBorder; - map->setBorderDimensions(oldBorderWidth, oldBorderHeight, false, true); + layout->border = oldBorder; + layout->setBorderDimensions(oldBorderWidth, oldBorderHeight, false, true); - map->layout->lastCommitBlocks.mapDimensions = QSize(map->getWidth(), map->getHeight()); - map->layout->lastCommitBlocks.borderDimensions = QSize(map->getBorderWidth(), map->getBorderHeight()); + layout->lastCommitBlocks.mapDimensions = QSize(layout->getWidth(), layout->getHeight()); + layout->lastCommitBlocks.borderDimensions = QSize(layout->getBorderWidth(), layout->getBorderHeight()); - map->mapNeedsRedrawing(); + layout->needsRedrawing(); QUndoCommand::undo(); } @@ -538,7 +538,8 @@ void ScriptEditMap::redo() { map->layout->lastCommitBlocks.border = newBorder; map->layout->lastCommitBlocks.borderDimensions = QSize(newBorderWidth, newBorderHeight); - renderMapBlocks(map); + // !TODO + renderBlocks(map->layout); map->borderItem->draw(); } @@ -564,7 +565,8 @@ void ScriptEditMap::undo() { map->layout->lastCommitBlocks.border = oldBorder; map->layout->lastCommitBlocks.borderDimensions = QSize(oldBorderWidth, oldBorderHeight); - renderMapBlocks(map); + // !TODO + renderBlocks(map->layout); map->borderItem->draw(); QUndoCommand::undo(); diff --git a/src/core/map.cpp b/src/core/map.cpp index 176d4d2f5..181cde359 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -133,48 +133,8 @@ QPixmap Map::renderCollision(bool ignoreCache) { return collision_pixmap; } -QPixmap Map::render(bool ignoreCache, MapLayout * fromLayout, QRect bounds) { - bool changed_any = false; - int width_ = getWidth(); - int height_ = getHeight(); - if (image.isNull() || image.width() != width_ * 16 || image.height() != height_ * 16) { - image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); - changed_any = true; - } - if (layout->blockdata.isEmpty() || !width_ || !height_) { - pixmap = pixmap.fromImage(image); - return pixmap; - } - - QPainter painter(&image); - for (int i = 0; i < layout->blockdata.length(); i++) { - if (!ignoreCache && !mapBlockChanged(i, layout->cached_blockdata)) { - continue; - } - changed_any = true; - int map_y = width_ ? i / width_ : 0; - int map_x = width_ ? i % width_ : 0; - if (bounds.isValid() && !bounds.contains(map_x, map_y)) { - continue; - } - QPoint metatile_origin = QPoint(map_x * 16, map_y * 16); - Block block = layout->blockdata.at(i); - QImage metatile_image = getMetatileImage( - block.metatileId, - fromLayout ? fromLayout->tileset_primary : layout->tileset_primary, - fromLayout ? fromLayout->tileset_secondary : layout->tileset_secondary, - metatileLayerOrder, - metatileLayerOpacity - ); - painter.drawImage(metatile_origin, metatile_image); - } - painter.end(); - if (changed_any) { - cacheBlockdata(); - pixmap = pixmap.fromImage(image); - } - - return pixmap; +QPixmap Map::render(bool ignoreCache, Layout *fromLayout, QRect bounds) { + return this->layout->render(ignoreCache, fromLayout, bounds); } QPixmap Map::renderBorder(bool ignoreCache) { @@ -215,7 +175,7 @@ QPixmap Map::renderBorder(bool ignoreCache) { return layout->border_pixmap; } -QPixmap Map::renderConnection(MapConnection connection, MapLayout * fromLayout) { +QPixmap Map::renderConnection(MapConnection connection, Layout *fromLayout) { int x, y, w, h; if (connection.direction == "up") { x = 0; @@ -245,9 +205,10 @@ QPixmap Map::renderConnection(MapConnection connection, MapLayout * fromLayout) h = getHeight(); } - render(true, fromLayout, QRect(x, y, w, h)); - QImage connection_image = image.copy(x * 16, y * 16, w * 16, h * 16); - return QPixmap::fromImage(connection_image); + //render(true, fromLayout, QRect(x, y, w, h)); + //QImage connection_image = image.copy(x * 16, y * 16, w * 16, h * 16); + return render(true, fromLayout, QRect(x, y, w, h)).copy(x * 16, y * 16, w * 16, h * 16); + //return QPixmap::fromImage(connection_image); } void Map::setNewDimensionsBlockdata(int newWidth, int newHeight) { diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 0f5deecd5..70364f69a 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -2,7 +2,10 @@ #include -QString MapLayout::layoutConstantFromName(QString mapName) { +#include "scripting.h" +#include "imageproviders.h" + +QString Layout::layoutConstantFromName(QString mapName) { // Transform map names of the form 'GraniteCave_B1F` into layout constants like 'LAYOUT_GRANITE_CAVE_B1F'. static const QRegularExpression caseChange("([a-z])([A-Z])"); QString nameWithUnderscores = mapName.replace(caseChange, "\\1_\\2"); @@ -17,18 +20,363 @@ QString MapLayout::layoutConstantFromName(QString mapName) { return constantName; } -int MapLayout::getWidth() { +int Layout::getWidth() { return width; } -int MapLayout::getHeight() { +int Layout::getHeight() { return height; } -int MapLayout::getBorderWidth() { +int Layout::getBorderWidth() { return border_width; } -int MapLayout::getBorderHeight() { +int Layout::getBorderHeight() { return border_height; } + +bool Layout::getBlock(int x, int y, Block *out) { + if (isWithinBounds(x, y)) { + int i = y * getWidth() + x; + *out = this->blockdata.value(i); + return true; + } + return false; +} + +void Layout::setBlock(int x, int y, Block block, bool enableScriptCallback) { + if (!isWithinBounds(x, y)) return; + int i = y * getWidth() + x; + if (i < this->blockdata.size()) { + Block prevBlock = this->blockdata.at(i); + this->blockdata.replace(i, block); + if (enableScriptCallback) { + Scripting::cb_MetatileChanged(x, y, prevBlock, block); + } + } +} + +void Layout::setBlockdata(Blockdata newBlockdata, bool enableScriptCallback) { + int width = getWidth(); + int size = qMin(newBlockdata.size(), this->blockdata.size()); + for (int i = 0; i < size; i++) { + Block prevBlock = this->blockdata.at(i); + Block newBlock = newBlockdata.at(i); + if (prevBlock != newBlock) { + this->blockdata.replace(i, newBlock); + if (enableScriptCallback) + Scripting::cb_MetatileChanged(i % width, i / width, prevBlock, newBlock); + } + } +} + +void Layout::clearBorderCache() { + this->cached_border.clear(); +} + +void Layout::cacheBorder() { + this->cached_border.clear(); + for (const auto &block : this->border) + this->cached_border.append(block); +} + +void Layout::cacheBlockdata() { + this->cached_blockdata.clear(); + for (const auto &block : this->blockdata) + this->cached_blockdata.append(block); +} + +void Layout::cacheCollision() { + this->cached_collision.clear(); + for (const auto &block : this->blockdata) + this->cached_collision.append(block); +} + +bool Layout::layoutBlockChanged(int i, const Blockdata &cache) { + if (cache.length() <= i) + return true; + if (this->blockdata.length() <= i) + return true; + + return this->blockdata.at(i) != cache.at(i); +} + +uint16_t Layout::getBorderMetatileId(int x, int y) { + int i = y * getBorderWidth() + x; + return this->border[i].metatileId; +} + +void Layout::setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback) { + int i = y * getBorderWidth() + x; + if (i < this->border.size()) { + uint16_t prevMetatileId = this->border[i].metatileId; + this->border[i].metatileId = metatileId; + if (prevMetatileId != metatileId && enableScriptCallback) { + Scripting::cb_BorderMetatileChanged(x, y, prevMetatileId, metatileId); + } + } +} + +void Layout::setBorderBlockData(Blockdata newBlockdata, bool enableScriptCallback) { + int width = getBorderWidth(); + int size = qMin(newBlockdata.size(), this->border.size()); + for (int i = 0; i < size; i++) { + Block prevBlock = this->border.at(i); + Block newBlock = newBlockdata.at(i); + if (prevBlock != newBlock) { + this->border.replace(i, newBlock); + if (enableScriptCallback) + Scripting::cb_BorderMetatileChanged(i % width, i / width, prevBlock.metatileId, newBlock.metatileId); + } + } +} + +void Layout::setDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) { + if (setNewBlockdata) { + setNewDimensionsBlockdata(newWidth, newHeight); + } + + int oldWidth = this->width; + int oldHeight = this->height; + this->width = newWidth; + this->height = newHeight; + + if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) { + Scripting::cb_MapResized(oldWidth, oldHeight, newWidth, newHeight); + } + + emit layoutChanged(this); + emit layoutDimensionsChanged(QSize(getWidth(), getHeight())); +} + +void Layout::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) { + if (setNewBlockdata) { + setNewBorderDimensionsBlockdata(newWidth, newHeight); + } + + int oldWidth = this->border_width; + int oldHeight = this->border_height; + this->border_width = newWidth; + this->border_height = newHeight; + + if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) { + Scripting::cb_BorderResized(oldWidth, oldHeight, newWidth, newHeight); + } + + emit layoutChanged(this); +} + +void Layout::setNewDimensionsBlockdata(int newWidth, int newHeight) { + int oldWidth = getWidth(); + int oldHeight = getHeight(); + + Blockdata newBlockdata; + + for (int y = 0; y < newHeight; y++) + for (int x = 0; x < newWidth; x++) { + if (x < oldWidth && y < oldHeight) { + int index = y * oldWidth + x; + newBlockdata.append(this->blockdata.value(index)); + } else { + newBlockdata.append(0); + } + } + + this->blockdata = newBlockdata; +} + +void Layout::setNewBorderDimensionsBlockdata(int newWidth, int newHeight) { + int oldWidth = getBorderWidth(); + int oldHeight = getBorderHeight(); + + Blockdata newBlockdata; + + for (int y = 0; y < newHeight; y++) + for (int x = 0; x < newWidth; x++) { + if (x < oldWidth && y < oldHeight) { + int index = y * oldWidth + x; + newBlockdata.append(this->border.value(index)); + } else { + newBlockdata.append(0); + } + } + + this->border = newBlockdata; +} + +void Layout::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) { + QList todo; + todo.append(QPoint(x, y)); + while (todo.length()) { + QPoint point = todo.takeAt(0); + x = point.x(); + y = point.y(); + Block block; + if (!getBlock(x, y, &block)) { + continue; + } + + uint old_coll = block.collision; + uint old_elev = block.elevation; + if (old_coll == collision && old_elev == elevation) { + continue; + } + + block.collision = collision; + block.elevation = elevation; + setBlock(x, y, block, true); + if (getBlock(x + 1, y, &block) && block.collision == old_coll && block.elevation == old_elev) { + todo.append(QPoint(x + 1, y)); + } + if (getBlock(x - 1, y, &block) && block.collision == old_coll && block.elevation == old_elev) { + todo.append(QPoint(x - 1, y)); + } + if (getBlock(x, y + 1, &block) && block.collision == old_coll && block.elevation == old_elev) { + todo.append(QPoint(x, y + 1)); + } + if (getBlock(x, y - 1, &block) && block.collision == old_coll && block.elevation == old_elev) { + todo.append(QPoint(x, y - 1)); + } + } +} + +void Layout::floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) { + Block block; + if (getBlock(x, y, &block) && (block.collision != collision || block.elevation != elevation)) { + _floodFillCollisionElevation(x, y, collision, elevation); + } +} + +void Layout::magicFillCollisionElevation(int initialX, int initialY, uint16_t collision, uint16_t elevation) { + Block block; + if (getBlock(initialX, initialY, &block) && (block.collision != collision || block.elevation != elevation)) { + uint old_coll = block.collision; + uint old_elev = block.elevation; + + for (int y = 0; y < getHeight(); y++) { + for (int x = 0; x < getWidth(); x++) { + if (getBlock(x, y, &block) && block.collision == old_coll && block.elevation == old_elev) { + block.collision = collision; + block.elevation = elevation; + setBlock(x, y, block, true); + } + } + } + } +} + +QPixmap Layout::render(bool ignoreCache, Layout *fromLayout, QRect bounds) { + bool changed_any = false; + int width_ = getWidth(); + int height_ = getHeight(); + if (image.isNull() || image.width() != width_ * 16 || image.height() != height_ * 16) { + image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); + changed_any = true; + } + if (this->blockdata.isEmpty() || !width_ || !height_) { + pixmap = pixmap.fromImage(image); + return pixmap; + } + + QPainter painter(&image); + for (int i = 0; i < this->blockdata.length(); i++) { + if (!ignoreCache && !layoutBlockChanged(i, this->cached_blockdata)) { + continue; + } + changed_any = true; + int map_y = width_ ? i / width_ : 0; + int map_x = width_ ? i % width_ : 0; + if (bounds.isValid() && !bounds.contains(map_x, map_y)) { + continue; + } + QPoint metatile_origin = QPoint(map_x * 16, map_y * 16); + Block block = this->blockdata.at(i); + QImage metatile_image = getMetatileImage( + block.metatileId, + fromLayout ? fromLayout->tileset_primary : this->tileset_primary, + fromLayout ? fromLayout->tileset_secondary : this->tileset_secondary, + metatileLayerOrder, + metatileLayerOpacity + ); + painter.drawImage(metatile_origin, metatile_image); + } + painter.end(); + if (changed_any) { + cacheBlockdata(); + pixmap = pixmap.fromImage(image); + } + + return pixmap; +} + +QPixmap Layout::renderCollision(bool ignoreCache) { + bool changed_any = false; + int width_ = getWidth(); + int height_ = getHeight(); + if (collision_image.isNull() || collision_image.width() != width_ * 16 || collision_image.height() != height_ * 16) { + collision_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); + changed_any = true; + } + if (this->blockdata.isEmpty() || !width_ || !height_) { + collision_pixmap = collision_pixmap.fromImage(collision_image); + return collision_pixmap; + } + QPainter painter(&collision_image); + for (int i = 0; i < this->blockdata.length(); i++) { + if (!ignoreCache && !layoutBlockChanged(i, this->cached_collision)) { + continue; + } + changed_any = true; + Block block = this->blockdata.at(i); + QImage collision_metatile_image = getCollisionMetatileImage(block); + int map_y = width_ ? i / width_ : 0; + int map_x = width_ ? i % width_ : 0; + QPoint metatile_origin = QPoint(map_x * 16, map_y * 16); + painter.drawImage(metatile_origin, collision_metatile_image); + } + painter.end(); + cacheCollision(); + if (changed_any) { + collision_pixmap = collision_pixmap.fromImage(collision_image); + } + return collision_pixmap; +} + +QPixmap Layout::renderBorder(bool ignoreCache) { + bool changed_any = false, border_resized = false; + int width_ = getBorderWidth(); + int height_ = getBorderHeight(); + if (this->border_image.isNull()) { + this->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); + changed_any = true; + } + if (this->border_image.width() != width_ * 16 || this->border_image.height() != height_ * 16) { + this->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); + border_resized = true; + } + if (this->border.isEmpty()) { + this->border_pixmap = this->border_pixmap.fromImage(this->border_image); + return this->border_pixmap; + } + QPainter painter(&this->border_image); + for (int i = 0; i < this->border.length(); i++) { + if (!ignoreCache && (!border_resized && !layoutBlockChanged(i, this->cached_border))) { + continue; + } + + changed_any = true; + Block block = this->border.at(i); + uint16_t metatileId = block.metatileId; + QImage metatile_image = getMetatileImage(metatileId, this->tileset_primary, this->tileset_secondary, metatileLayerOrder, metatileLayerOpacity); + int map_y = width_ ? i / width_ : 0; + int map_x = width_ ? i % width_ : 0; + painter.drawImage(QPoint(map_x * 16, map_y * 16), metatile_image); + } + painter.end(); + if (changed_any) { + cacheBorder(); + this->border_pixmap = this->border_pixmap.fromImage(this->border_image); + } + return this->border_pixmap; +} diff --git a/src/editor.cpp b/src/editor.cpp index 4dc12885a..d83ca28a7 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -83,7 +83,7 @@ void Editor::closeProject() { void Editor::setEditingMap() { current_view = map_item; if (map_item) { - map_item->paintingMode = MapPixmapItem::PaintMode::Metatiles; + map_item->paintingMode = LayoutPixmapItem::PaintMode::Metatiles; displayMapConnections(); map_item->draw(); map_item->setVisible(true); @@ -133,7 +133,8 @@ void Editor::setEditingObjects() { events_group->setVisible(true); } if (map_item) { - map_item->paintingMode = MapPixmapItem::PaintMode::EventObjects; + // !TODO: change this pixmapitem paintmode + map_item->paintingMode = LayoutPixmapItem::PaintMode::EventObjects; displayMapConnections(); map_item->draw(); map_item->setVisible(true); @@ -169,7 +170,7 @@ void Editor::setMapEditingButtonsEnabled(bool enabled) { void Editor::setEditingConnections() { current_view = map_item; if (map_item) { - map_item->paintingMode = MapPixmapItem::PaintMode::Disabled; + map_item->paintingMode = LayoutPixmapItem::PaintMode::Disabled; map_item->draw(); map_item->setVisible(true); populateConnectionMapPickers(); @@ -1020,7 +1021,7 @@ void Editor::onHoveredMapMetatileChanged(const QPoint &pos) { return; this->updateCursorRectPos(x, y); - if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) { + if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { int blockIndex = y * map->getWidth() + x; int metatileId = map->layout->blockdata.at(blockIndex).metatileId; this->ui->statusBar->showMessage(QString("X: %1, Y: %2, %3, Scale = %4x") @@ -1029,7 +1030,7 @@ void Editor::onHoveredMapMetatileChanged(const QPoint &pos) { .arg(getMetatileDisplayMessage(metatileId)) .arg(QString::number(zoomLevels[this->scaleIndex], 'g', 2))); } - else if (map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects) { + else if (map_item->paintingMode == LayoutPixmapItem::PaintMode::EventObjects) { this->ui->statusBar->showMessage(QString("X: %1, Y: %2, Scale = %3x") .arg(x) .arg(y) @@ -1040,8 +1041,8 @@ void Editor::onHoveredMapMetatileChanged(const QPoint &pos) { void Editor::onHoveredMapMetatileCleared() { this->setCursorRectVisible(false); - if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles - || map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects) { + if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles + || map_item->paintingMode == LayoutPixmapItem::PaintMode::EventObjects) { this->ui->statusBar->clearMessage(); } Scripting::cb_BlockHoverCleared(); @@ -1052,7 +1053,7 @@ void Editor::onHoveredMapMovementPermissionChanged(int x, int y) { return; this->updateCursorRectPos(x, y); - if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) { + if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { int blockIndex = y * map->getWidth() + x; uint16_t collision = map->layout->blockdata.at(blockIndex).collision; uint16_t elevation = map->layout->blockdata.at(blockIndex).elevation; @@ -1067,7 +1068,7 @@ void Editor::onHoveredMapMovementPermissionChanged(int x, int y) { void Editor::onHoveredMapMovementPermissionCleared() { this->setCursorRectVisible(false); - if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) { + if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { this->ui->statusBar->clearMessage(); } Scripting::cb_BlockHoverCleared(); @@ -1089,16 +1090,22 @@ QString Editor::getMovementPermissionText(uint16_t collision, uint16_t elevation return message; } +void Editor::unsetMap() { + // disconnect previous map's signals so they are not firing + // multiple times if set again in the future + if (this->map) { + this->map->disconnect(this); + } + + this->map = nullptr; +} + bool Editor::setMap(QString map_name) { if (map_name.isEmpty()) { return false; } - // disconnect previous map's signals so they are not firing - // multiple times if set again in the future - if (map) { - map->disconnect(this); - } + unsetMap(); if (project) { Map *loadedMap = project->loadMap(map_name); @@ -1107,6 +1114,7 @@ bool Editor::setMap(QString map_name) { } map = loadedMap; + this->layout = map->layout; // !TODO: editGroup.addStack(&map->editHistory); editGroup.setActiveStack(&map->editHistory); @@ -1123,8 +1131,8 @@ bool Editor::setMap(QString map_name) { return true; } -void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) { - if (item->paintingMode != MapPixmapItem::PaintMode::Metatiles) { +void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) { + if (item->paintingMode != LayoutPixmapItem::PaintMode::Metatiles) { return; } @@ -1136,8 +1144,8 @@ void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *ite } } -void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *item) { - if (!(item->paintingMode == MapPixmapItem::PaintMode::Metatiles)) { +void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *item) { + if (!(item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles)) { return; } this->cursorMapTileRect->stopRightClickSelectionAnchor(); @@ -1170,15 +1178,15 @@ void Editor::setStraightPathCursorMode(QGraphicsSceneMouseEvent *event) { } } -void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) { +void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) { // TODO: add event tab object painting tool buttons stuff here - if (item->paintingMode == MapPixmapItem::PaintMode::Disabled) { + if (item->paintingMode == LayoutPixmapItem::PaintMode::Disabled) { return; } QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); - if (item->paintingMode == MapPixmapItem::PaintMode::Metatiles) { + if (item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { if (map_edit_mode == "paint") { if (event->buttons() & Qt::RightButton) { item->updateMetatileSelection(event); @@ -1225,7 +1233,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item } item->shift(event); } - } else if (item->paintingMode == MapPixmapItem::PaintMode::EventObjects) { + } else if (item->paintingMode == LayoutPixmapItem::PaintMode::EventObjects) { if (obj_edit_mode == "paint" && event->type() == QEvent::GraphicsSceneMousePress) { // Right-clicking while in paint mode will change mode to select. if (event->buttons() & Qt::RightButton) { @@ -1253,7 +1261,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item } } else if (obj_edit_mode == "select") { // do nothing here, at least for now - } else if (obj_edit_mode == "shift" && item->map) { + } else if (obj_edit_mode == "shift") { static QPoint selection_origin; static unsigned actionId = 0; @@ -1269,8 +1277,8 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item QList selectedEvents; - for (DraggablePixmapItem *item : getObjects()) { - selectedEvents.append(item->event); + for (DraggablePixmapItem *pixmapItem : getObjects()) { + selectedEvents.append(pixmapItem->event); } selection_origin = QPoint(pos.x(), pos.y()); @@ -1283,7 +1291,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item } void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) { - if (item->paintingMode != MapPixmapItem::PaintMode::Metatiles) { + if (item->paintingMode != LayoutPixmapItem::PaintMode::Metatiles) { return; } @@ -1400,12 +1408,12 @@ void Editor::displayMetatileSelector() { } void Editor::displayMapMetatiles() { - map_item = new MapPixmapItem(map, this->metatile_selector_item, this->settings); - connect(map_item, &MapPixmapItem::mouseEvent, this, &Editor::mouseEvent_map); - connect(map_item, &MapPixmapItem::startPaint, this, &Editor::onMapStartPaint); - connect(map_item, &MapPixmapItem::endPaint, this, &Editor::onMapEndPaint); - connect(map_item, &MapPixmapItem::hoveredMapMetatileChanged, this, &Editor::onHoveredMapMetatileChanged); - connect(map_item, &MapPixmapItem::hoveredMapMetatileCleared, this, &Editor::onHoveredMapMetatileCleared); + map_item = new LayoutPixmapItem(this->layout, this->metatile_selector_item, this->settings); + connect(map_item, &LayoutPixmapItem::mouseEvent, this, &Editor::mouseEvent_map); + connect(map_item, &LayoutPixmapItem::startPaint, this, &Editor::onMapStartPaint); + connect(map_item, &LayoutPixmapItem::endPaint, this, &Editor::onMapEndPaint); + connect(map_item, &LayoutPixmapItem::hoveredMapMetatileChanged, this, &Editor::onHoveredMapMetatileChanged); + connect(map_item, &LayoutPixmapItem::hoveredMapMetatileCleared, this, &Editor::onHoveredMapMetatileCleared); map_item->draw(true); scene->addItem(map_item); @@ -1425,7 +1433,7 @@ void Editor::displayMapMovementPermissions() { scene->removeItem(collision_item); delete collision_item; } - collision_item = new CollisionPixmapItem(map, this->movement_permissions_selector_item, + collision_item = new CollisionPixmapItem(this->layout, this->movement_permissions_selector_item, this->metatile_selector_item, this->settings, &this->collisionOpacity); connect(collision_item, &CollisionPixmapItem::mouseEvent, this, &Editor::mouseEvent_collision); connect(collision_item, &CollisionPixmapItem::hoveredMapMovementPermissionChanged, @@ -1444,7 +1452,7 @@ void Editor::displayBorderMetatiles() { } scene_selected_border_metatiles = new QGraphicsScene; - selected_border_metatiles_item = new BorderMetatilesPixmapItem(map, this->metatile_selector_item); + selected_border_metatiles_item = new BorderMetatilesPixmapItem(this->layout, this->metatile_selector_item); selected_border_metatiles_item->draw(); scene_selected_border_metatiles->addItem(selected_border_metatiles_item); @@ -2035,7 +2043,7 @@ void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) { } void Editor::duplicateSelectedEvents() { - if (!selected_events || !selected_events->length() || !map || !current_view || map_item->paintingMode != MapPixmapItem::PaintMode::EventObjects) + if (!selected_events || !selected_events->length() || !map || !current_view || map_item->paintingMode != LayoutPixmapItem::PaintMode::EventObjects) return; QList selectedEvents; @@ -2207,7 +2215,7 @@ bool Editor::startDetachedProcess(const QString &command, const QString &working // is clicking on the background instead of an event. void Editor::objectsView_onMousePress(QMouseEvent *event) { // make sure we are in object editing mode - if (map_item && map_item->paintingMode != MapPixmapItem::PaintMode::EventObjects) { + if (map_item && map_item->paintingMode != LayoutPixmapItem::PaintMode::EventObjects) { return; } if (this->obj_edit_mode == "paint" && event->buttons() & Qt::RightButton) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5c4aaf34c..351c0e3e8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -617,12 +617,32 @@ void MainWindow::on_action_Reload_Project_triggered() { } } +void MainWindow::unsetMap() { + // + logInfo("Disabling map-related edits"); + + // + this->editor->unsetMap(); + + // disable other tabs + this->ui->mainTabBar->setTabEnabled(0, true); + this->ui->mainTabBar->setTabEnabled(1, false); + this->ui->mainTabBar->setTabEnabled(2, false); + this->ui->mainTabBar->setTabEnabled(3, false); + this->ui->mainTabBar->setTabEnabled(4, false); + + // +} + bool MainWindow::setMap(QString map_name, bool scrollTreeView) { - logInfo(QString("Setting map to '%1'").arg(map_name)); + // if map name is empty, clear & disable map ui if (map_name.isEmpty()) { + unsetMap(); return false; } + logInfo(QString("Setting map to '%1'").arg(map_name)); + if (!editor->setMap(map_name)) { logWarn(QString("Failed to set map to '%1'").arg(map_name)); return false; @@ -965,6 +985,13 @@ bool MainWindow::populateMapList() { groupListProxyModel->setSourceModel(this->mapGroupModel); ui->mapList->setModel(groupListProxyModel); + this->layoutTreeModel = new LayoutTreeModel(editor->project); + this->layoutListProxyModel = new FilterChildrenProxyModel(); + this->layoutListProxyModel->setSourceModel(this->layoutTreeModel); + ui->layoutList->setModel(layoutListProxyModel); + + //connect(this->ui->layoutList, &QTreeView::doubleClicked, this, &MainWindow::on_layoutList_activated); + // ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); // ui->mapList->setDragEnabled(true); // ui->mapList->setAcceptDrops(true); @@ -993,7 +1020,7 @@ void MainWindow::sortMapList() { // switch (mapSortOrder) // { - // case MapSortOrder::Group: + // case MapSortOrder::SortByGroup: // for (int i = 0; i < project->groupNames.length(); i++) { // QString group_name = project->groupNames.value(i); // QStandardItem *group = new QStandardItem; @@ -1014,7 +1041,7 @@ void MainWindow::sortMapList() { // } // } // break; - // case MapSortOrder::Area: + // case MapSortOrder::SortByArea: // { // QMap mapsecToGroupNum; // for (int i = 0; i < project->mapSectionNameToValue.size(); i++) { @@ -1044,7 +1071,7 @@ void MainWindow::sortMapList() { // } // break; // } - // case MapSortOrder::Layout: + // case MapSortOrder::SortByLayout: // { // QMap layoutIndices; // for (int i = 0; i < project->mapLayoutsTable.length(); i++) { @@ -1137,19 +1164,19 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) { openNewMapPopupWindow(); - this->newMapPrompt->init(MapSortOrder::Group, triggeredAction->data()); + this->newMapPrompt->init(MapSortOrder::SortByGroup, triggeredAction->data()); } void MainWindow::onAddNewMapToAreaClick(QAction* triggeredAction) { openNewMapPopupWindow(); - this->newMapPrompt->init(MapSortOrder::Area, triggeredAction->data()); + this->newMapPrompt->init(MapSortOrder::SortByArea, triggeredAction->data()); } void MainWindow::onAddNewMapToLayoutClick(QAction* triggeredAction) { openNewMapPopupWindow(); - this->newMapPrompt->init(MapSortOrder::Layout, triggeredAction->data()); + this->newMapPrompt->init(MapSortOrder::SortByLayout, triggeredAction->data()); } void MainWindow::onNewMapCreated() { @@ -1359,9 +1386,23 @@ void MainWindow::currentMetatilesSelectionChanged() } } +// !TODO +void MainWindow::on_mapListContainer_currentChanged(int index) { + // + switch (index) { + case MapListTab::Groups: + break; + case MapListTab::Areas: + break; + case MapListTab::Layouts: + //setMap(nullptr); + //setLayout(nullptr); + break; + } +} + /// !TODO -void MainWindow::on_mapList_activated(const QModelIndex &index) -{ +void MainWindow::on_mapList_activated(const QModelIndex &index) { QVariant data = index.data(Qt::UserRole); if (index.data(MapListRoles::TypeRole) == "map_name" && !data.isNull()) { QString mapName = data.toString(); @@ -1376,6 +1417,24 @@ void MainWindow::on_mapList_activated(const QModelIndex &index) } } +void MainWindow::on_areaList_activated(const QModelIndex &index) { + // +} + +void MainWindow::on_layoutList_activated(const QModelIndex &index) { + if (!index.isValid()) return; + + QVariant data = index.data(Qt::UserRole); + if (index.data(MapListRoles::TypeRole) == "map_layout" && !data.isNull()) { + QString layoutName = data.toString(); + // + logInfo("Switching to a layout-only editing mode"); + setMap(QString()); + // setLayout(layout) + qDebug() << "set layout" << layoutName; + } +} + /// !TODO something with the projectHasUnsavedChanges var void MainWindow::drawMapListIcons(QAbstractItemModel *model) { // projectHasUnsavedChanges = false; @@ -2616,21 +2675,21 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() form.addRow(errorLabel); if (dialog.exec() == QDialog::Accepted) { - Map *map = editor->map; - Blockdata oldMetatiles = map->layout->blockdata; - Blockdata oldBorder = map->layout->border; - QSize oldMapDimensions(map->getWidth(), map->getHeight()); - QSize oldBorderDimensions(map->getBorderWidth(), map->getBorderHeight()); + Layout *layout = editor->layout; + Blockdata oldMetatiles = layout->blockdata; + Blockdata oldBorder = layout->border; + QSize oldMapDimensions(layout->getWidth(), layout->getHeight()); + QSize oldBorderDimensions(layout->getBorderWidth(), layout->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(), true, true); - editor->map->setBorderDimensions(newBorderDimensions.width(), newBorderDimensions.height(), true, true); - editor->map->editHistory.push(new ResizeMap(map, + layout->setDimensions(newMapDimensions.width(), newMapDimensions.height(), true, true); + layout->setBorderDimensions(newBorderDimensions.width(), newBorderDimensions.height(), true, true); + editor->map->editHistory.push(new ResizeMap(layout, oldMapDimensions, newMapDimensions, - oldMetatiles, map->layout->blockdata, + oldMetatiles, layout->blockdata, oldBorderDimensions, newBorderDimensions, - oldBorder, map->layout->border + oldBorder, layout->border )); } } @@ -2670,42 +2729,40 @@ void MainWindow::initTilesetEditor() { connect(this->tilesetEditor, &TilesetEditor::tilesetsSaved, this, &MainWindow::onTilesetsSaved); } -// void MainWindow::on_toolButton_ExpandAll_clicked() -// { -// if (ui->mapList) { -// ui->mapList->expandToDepth(0); -// } -// } - -// void MainWindow::on_toolButton_CollapseAll_clicked() -// { -// if (ui->mapList) { -// ui->mapList->collapseAll(); -// } -// } - void MainWindow::on_toolButton_ExpandAll_Groups_clicked() { - // + if (ui->mapList) { + ui->mapList->expandToDepth(0); + } } void MainWindow::on_toolButton_CollapseAll_Groups_clicked() { - // + if (ui->mapList) { + ui->mapList->collapseAll(); + } } void MainWindow::on_toolButton_ExpandAll_Areas_clicked() { - // + if (ui->areaList) { + ui->areaList->expandToDepth(0); + } } void MainWindow::on_toolButton_CollapseAll_Areas_clicked() { - // + if (ui->areaList) { + ui->areaList->collapseAll(); + } } void MainWindow::on_toolButton_ExpandAll_Layouts_clicked() { - // + if (ui->layoutList) { + ui->layoutList->expandToDepth(0); + } } void MainWindow::on_toolButton_CollapseAll_Layouts_clicked() { - // + if (ui->layoutList) { + ui->layoutList->collapseAll(); + } } void MainWindow::on_actionAbout_Porymap_triggered() diff --git a/src/project.cpp b/src/project.cpp index 588d0ee44..4acaf94df 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -359,6 +359,10 @@ QString Project::readMapLayoutId(QString map_name) { return ParseUtil::jsonToQString(mapObj["layout"]); } +QString Project::readMapLayoutName(QString mapName) { + return this->layoutIdsToNames[readMapLayoutId(mapName)]; +} + QString Project::readMapLocation(QString map_name) { if (mapCache.contains(map_name)) { return mapCache.value(map_name)->location; @@ -408,6 +412,7 @@ bool Project::loadMapLayout(Map* map) { bool Project::readMapLayouts() { mapLayouts.clear(); mapLayoutsTable.clear(); + layoutIdsToNames.clear(); QString layoutsFilepath = projectConfig.getFilePath(ProjectFilePath::json_layouts); QString fullFilepath = QString("%1/%2").arg(root).arg(layoutsFilepath); @@ -529,6 +534,7 @@ bool Project::readMapLayouts() { } mapLayouts.insert(layout->id, layout); mapLayoutsTable.append(layout->id); + layoutIdsToNames.insert(layout->id, layout->name); } // Deep copy @@ -1336,11 +1342,12 @@ void Project::updateMapLayout(Map* map) { mapLayoutsTableMaster.append(map->layoutId); } + // !TODO // Deep copy - MapLayout *layout = mapLayouts.value(map->layoutId); - MapLayout *newLayout = new MapLayout(); - *newLayout = *layout; - mapLayoutsMaster.insert(map->layoutId, newLayout); + // MapLayout *layout = mapLayouts.value(map->layoutId); + // MapLayout *newLayout = new MapLayout(); + // *newLayout = *layout; + // mapLayoutsMaster.insert(map->layoutId, newLayout); } void Project::saveAllDataStructures() { diff --git a/src/ui/bordermetatilespixmapitem.cpp b/src/ui/bordermetatilespixmapitem.cpp index 8f8bc1348..6c5425586 100644 --- a/src/ui/bordermetatilespixmapitem.cpp +++ b/src/ui/bordermetatilespixmapitem.cpp @@ -7,30 +7,30 @@ void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { MetatileSelection selection = this->metatileSelector->getMetatileSelection(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); - int width = map->getBorderWidth(); - int height = map->getBorderHeight(); + int width = layout->getBorderWidth(); + int height = layout->getBorderHeight(); - Blockdata oldBorder = map->layout->border; + Blockdata oldBorder = layout->border; for (int i = 0; i < selection.dimensions.x() && (i + pos.x()) < width; i++) { for (int j = 0; j < selection.dimensions.y() && (j + pos.y()) < height; j++) { MetatileSelectionItem item = selection.metatileItems.at(j * selection.dimensions.x() + i); - map->setBorderMetatileId(pos.x() + i, pos.y() + j, item.metatileId, true); + layout->setBorderMetatileId(pos.x() + i, pos.y() + j, item.metatileId, true); } } - if (map->layout->border != oldBorder) { - map->editHistory.push(new PaintBorder(map, oldBorder, map->layout->border, 0)); + if (layout->border != oldBorder) { + layout->editHistory.push(new PaintBorder(layout, oldBorder, layout->border, 0)); } emit borderMetatilesChanged(); } void BorderMetatilesPixmapItem::draw() { - map->setBorderItem(this); + layout->setBorderItem(this); - int width = map->getBorderWidth(); - int height = map->getBorderHeight(); + int width = layout->getBorderWidth(); + int height = layout->getBorderHeight(); QImage image(16 * width, 16 * height, QImage::Format_RGBA8888); QPainter painter(&image); @@ -39,11 +39,11 @@ void BorderMetatilesPixmapItem::draw() { int x = i * 16; int y = j * 16; QImage metatile_image = getMetatileImage( - map->getBorderMetatileId(i, j), - map->layout->tileset_primary, - map->layout->tileset_secondary, - map->metatileLayerOrder, - map->metatileLayerOpacity); + layout->getBorderMetatileId(i, j), + layout->tileset_primary, + layout->tileset_secondary, + layout->metatileLayerOrder, + layout->metatileLayerOpacity); QPoint metatile_origin = QPoint(x, y); painter.drawImage(metatile_origin, metatile_image); } @@ -57,7 +57,7 @@ void BorderMetatilesPixmapItem::draw() { void BorderMetatilesPixmapItem::hoverUpdate(const QPointF &pixmapPos) { QPoint pos = Metatile::coordFromPixmapCoord(pixmapPos); - uint16_t metatileId = this->map->getBorderMetatileId(pos.x(), pos.y()); + uint16_t metatileId = this->layout->getBorderMetatileId(pos.x(), pos.y()); emit this->hoveredBorderMetatileSelectionChanged(metatileId); } diff --git a/src/ui/collisionpixmapitem.cpp b/src/ui/collisionpixmapitem.cpp index eaa4bca10..266806771 100644 --- a/src/ui/collisionpixmapitem.cpp +++ b/src/ui/collisionpixmapitem.cpp @@ -8,7 +8,7 @@ void CollisionPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { this->previousPos = pos; emit this->hoveredMapMovementPermissionChanged(pos.x(), pos.y()); } - if (this->settings->betterCursors && this->paintingMode == MapPixmapItem::PaintMode::Metatiles) { + if (this->settings->betterCursors && this->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { setCursor(this->settings->mapCursor); } } @@ -21,7 +21,7 @@ void CollisionPixmapItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) { void CollisionPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { emit this->hoveredMapMovementPermissionCleared(); - if (this->settings->betterCursors && this->paintingMode == MapPixmapItem::PaintMode::Metatiles){ + if (this->settings->betterCursors && this->paintingMode == LayoutPixmapItem::PaintMode::Metatiles){ unsetCursor(); } this->has_mouse = false; @@ -49,9 +49,10 @@ void CollisionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { } void CollisionPixmapItem::draw(bool ignoreCache) { - if (map) { - map->setCollisionItem(this); - setPixmap(map->renderCollision(ignoreCache)); + if (this->layout) { + // !TODO + // this->layout->setCollisionItem(this); + setPixmap(this->layout->renderCollision(ignoreCache)); setOpacity(*this->opacity); } } @@ -59,8 +60,8 @@ void CollisionPixmapItem::draw(bool ignoreCache) { void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { actionId_++; - } else if (map) { - Blockdata oldCollision = map->layout->blockdata; + } else if (this->layout) { + Blockdata oldCollision = this->layout->blockdata; QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); @@ -70,18 +71,18 @@ void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) { pos = this->adjustCoords(pos); } else { this->prevStraightPathState = false; - this->lockedAxis = MapPixmapItem::Axis::None; + this->lockedAxis = LayoutPixmapItem::Axis::None; } Block block; - if (map->getBlock(pos.x(), pos.y(), &block)) { + if (this->layout->getBlock(pos.x(), pos.y(), &block)) { block.collision = this->movementPermissionsSelector->getSelectedCollision(); block.elevation = this->movementPermissionsSelector->getSelectedElevation(); - map->setBlock(pos.x(), pos.y(), block, true); + this->layout->setBlock(pos.x(), pos.y(), block, true); } - if (map->layout->blockdata != oldCollision) { - map->editHistory.push(new PaintCollision(map, oldCollision, map->layout->blockdata, actionId_)); + if (this->layout->blockdata != oldCollision) { + this->layout->editHistory.push(new PaintCollision(this->layout, oldCollision, this->layout->blockdata, actionId_)); } } } @@ -89,16 +90,16 @@ void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { this->actionId_++; - } else if (map) { - Blockdata oldCollision = map->layout->blockdata; + } else if (this->layout) { + Blockdata oldCollision = this->layout->blockdata; QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); uint16_t collision = this->movementPermissionsSelector->getSelectedCollision(); uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation(); - map->floodFillCollisionElevation(pos.x(), pos.y(), collision, elevation); + this->layout->floodFillCollisionElevation(pos.x(), pos.y(), collision, elevation); - if (map->layout->blockdata != oldCollision) { - map->editHistory.push(new BucketFillCollision(map, oldCollision, map->layout->blockdata)); + if (this->layout->blockdata != oldCollision) { + this->layout->editHistory.push(new BucketFillCollision(this->layout, oldCollision, this->layout->blockdata)); } } } @@ -106,15 +107,15 @@ void CollisionPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { this->actionId_++; - } else if (map) { - Blockdata oldCollision = map->layout->blockdata; + } else if (this->layout) { + Blockdata oldCollision = this->layout->blockdata; QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); uint16_t collision = this->movementPermissionsSelector->getSelectedCollision(); uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation(); - map->magicFillCollisionElevation(pos.x(), pos.y(), collision, elevation); + this->layout->magicFillCollisionElevation(pos.x(), pos.y(), collision, elevation); - if (map->layout->blockdata != oldCollision) { - map->editHistory.push(new MagicFillCollision(map, oldCollision, map->layout->blockdata)); + if (this->layout->blockdata != oldCollision) { + this->layout->editHistory.push(new MagicFillCollision(this->layout, oldCollision, this->layout->blockdata)); } } } @@ -122,7 +123,7 @@ void CollisionPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::pick(QGraphicsSceneMouseEvent *event) { QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); Block block; - if (map->getBlock(pos.x(), pos.y(), &block)) { + if (this->layout->getBlock(pos.x(), pos.y(), &block)) { this->movementPermissionsSelector->select(block.collision, block.elevation); } } @@ -132,12 +133,12 @@ void CollisionPixmapItem::updateMovementPermissionSelection(QGraphicsSceneMouseE // Snap point to within map bounds. if (pos.x() < 0) pos.setX(0); - if (pos.x() >= map->getWidth()) pos.setX(map->getWidth() - 1); + if (pos.x() >= this->layout->getWidth()) pos.setX(this->layout->getWidth() - 1); if (pos.y() < 0) pos.setY(0); - if (pos.y() >= map->getHeight()) pos.setY(map->getHeight() - 1); + if (pos.y() >= this->layout->getHeight()) pos.setY(this->layout->getHeight() - 1); Block block; - if (map->getBlock(pos.x(), pos.y(), &block)) { + if (this->layout->getBlock(pos.x(), pos.y(), &block)) { this->movementPermissionsSelector->select(block.collision, block.elevation); } } diff --git a/src/ui/mappixmapitem.cpp b/src/ui/layoutpixmapitem.cpp similarity index 65% rename from src/ui/mappixmapitem.cpp rename to src/ui/layoutpixmapitem.cpp index f44922a44..a595695ad 100644 --- a/src/ui/mappixmapitem.cpp +++ b/src/ui/layoutpixmapitem.cpp @@ -1,4 +1,4 @@ -#include "mappixmapitem.h" +#include "layoutpixmapitem.h" #include "metatile.h" #include "log.h" #include "scripting.h" @@ -7,8 +7,8 @@ #define SWAP(a, b) do { if (a != b) { a ^= b; b ^= a; a ^= b; } } while (0) -void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) { - if (map) { +void LayoutPixmapItem::paint(QGraphicsSceneMouseEvent *event) { + if (layout) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { actionId_++; } else { @@ -20,7 +20,7 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) { pos = this->adjustCoords(pos); } else { this->prevStraightPathState = false; - this->lockedAxis = MapPixmapItem::Axis::None; + this->lockedAxis = LayoutPixmapItem::Axis::None; } // Paint onto the map. @@ -43,8 +43,8 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) { } } -void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) { - if (map) { +void LayoutPixmapItem::shift(QGraphicsSceneMouseEvent *event) { + if (layout) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { actionId_++; } else { @@ -56,7 +56,7 @@ void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) { pos = this->adjustCoords(pos); } else { this->prevStraightPathState = false; - this->lockedAxis = MapPixmapItem::Axis::None; + this->lockedAxis = LayoutPixmapItem::Axis::None; } if (event->type() == QEvent::GraphicsSceneMousePress) { @@ -76,32 +76,32 @@ void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) { } } -void MapPixmapItem::shift(int xDelta, int yDelta, bool fromScriptCall) { - Blockdata oldMetatiles = map->layout->blockdata; +void LayoutPixmapItem::shift(int xDelta, int yDelta, bool fromScriptCall) { + Blockdata oldMetatiles = this->layout->blockdata; - for (int i = 0; i < map->getWidth(); i++) - for (int j = 0; j < map->getHeight(); j++) { + for (int i = 0; i < this->layout->getWidth(); i++) + for (int j = 0; j < this->layout->getHeight(); j++) { int destX = i + xDelta; int destY = j + yDelta; if (destX < 0) - do { destX += map->getWidth(); } while (destX < 0); + do { destX += this->layout->getWidth(); } while (destX < 0); if (destY < 0) - do { destY += map->getHeight(); } while (destY < 0); - destX %= map->getWidth(); - destY %= map->getHeight(); + do { destY += this->layout->getHeight(); } while (destY < 0); + destX %= this->layout->getWidth(); + destY %= this->layout->getHeight(); - int blockIndex = j * map->getWidth() + i; + int blockIndex = j * this->layout->getWidth() + i; Block srcBlock = oldMetatiles.at(blockIndex); - map->setBlock(destX, destY, srcBlock); + this->layout->setBlock(destX, destY, srcBlock); } - if (!fromScriptCall && map->layout->blockdata != oldMetatiles) { - map->editHistory.push(new ShiftMetatiles(map, oldMetatiles, map->layout->blockdata, actionId_)); + if (!fromScriptCall && this->layout->blockdata != oldMetatiles) { + this->layout->editHistory.push(new ShiftMetatiles(this->layout, oldMetatiles, this->layout->blockdata, actionId_)); Scripting::cb_MapShifted(xDelta, yDelta); } } -void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) { +void LayoutPixmapItem::paintNormal(int x, int y, bool fromScriptCall) { MetatileSelection selection = this->metatileSelector->getMetatileSelection(); int initialX = fromScriptCall ? x : this->paint_tile_initial_x; int initialY = fromScriptCall ? y : this->paint_tile_initial_y; @@ -117,14 +117,14 @@ void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) { y = initialY + (yDiff / selection.dimensions.y()) * selection.dimensions.y(); // for edit history - Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata(); + Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata(); - for (int i = 0; i < selection.dimensions.x() && i + x < map->getWidth(); i++) - for (int j = 0; j < selection.dimensions.y() && j + y < map->getHeight(); j++) { + for (int i = 0; i < selection.dimensions.x() && i + x < this->layout->getWidth(); i++) + for (int j = 0; j < selection.dimensions.y() && j + y < this->layout->getHeight(); j++) { int actualX = i + x; int actualY = j + y; Block block; - if (map->getBlock(actualX, actualY, &block)) { + if (this->layout->getBlock(actualX, actualY, &block)) { int index = j * selection.dimensions.x() + i; MetatileSelectionItem item = selection.metatileItems.at(index); if (!item.enabled) @@ -135,19 +135,19 @@ void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) { block.collision = collisionItem.collision; block.elevation = collisionItem.elevation; } - map->setBlock(actualX, actualY, block, !fromScriptCall); + this->layout->setBlock(actualX, actualY, block, !fromScriptCall); } } - if (!fromScriptCall && map->layout->blockdata != oldMetatiles) { - map->editHistory.push(new PaintMetatile(map, oldMetatiles, map->layout->blockdata, actionId_)); + if (!fromScriptCall && this->layout->blockdata != oldMetatiles) { + this->layout->editHistory.push(new PaintMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_)); } } // These are tile offsets from the top-left tile in the 3x3 smart path selection. // Each entry is for one possibility from the marching squares value for a tile. // (Marching Squares: https://en.wikipedia.org/wiki/Marching_squares) -QList MapPixmapItem::smartPathTable = QList({ +QList LayoutPixmapItem::smartPathTable = QList({ 4, // 0000 4, // 0001 4, // 0010 @@ -189,7 +189,7 @@ bool isValidSmartPathSelection(MetatileSelection selection) { return true; } -void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) { +void LayoutPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) { MetatileSelection selection = this->metatileSelector->getMetatileSelection(); if (!isValidSmartPathSelection(selection)) return; @@ -206,30 +206,30 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) { } // for edit history - Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata(); + Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata(); // Fill the region with the open tile. for (int i = 0; i <= 1; i++) for (int j = 0; j <= 1; j++) { - if (!map->isWithinBounds(x + i, y + j)) + if (!this->layout->isWithinBounds(x + i, y + j)) continue; int actualX = i + x; int actualY = j + y; Block block; - if (map->getBlock(actualX, actualY, &block)) { + if (this->layout->getBlock(actualX, actualY, &block)) { block.metatileId = openTile; if (setCollisions) { block.collision = openTileCollision; block.elevation = openTileElevation; } - map->setBlock(actualX, actualY, block, !fromScriptCall); + this->layout->setBlock(actualX, actualY, block, !fromScriptCall); } } // Go back and resolve the edge tiles for (int i = -1; i <= 2; i++) for (int j = -1; j <= 2; j++) { - if (!map->isWithinBounds(x + i, y + j)) + if (!this->layout->isWithinBounds(x + i, y + j)) continue; // Ignore the corners, which can't possible be affected by the smart path. if ((i == -1 && j == -1) || (i == 2 && j == -1) || @@ -240,7 +240,7 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) { int actualX = i + x; int actualY = j + y; Block block; - if (!map->getBlock(actualX, actualY, &block) || !isSmartPathTile(selection.metatileItems, block.metatileId)) { + if (!this->layout->getBlock(actualX, actualY, &block) || !isSmartPathTile(selection.metatileItems, block.metatileId)) { continue; } @@ -251,13 +251,13 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) { Block left; // Get marching squares value, to determine which tile to use. - if (map->getBlock(actualX, actualY - 1, &top) && isSmartPathTile(selection.metatileItems, top.metatileId)) + if (this->layout->getBlock(actualX, actualY - 1, &top) && isSmartPathTile(selection.metatileItems, top.metatileId)) id += 1; - if (map->getBlock(actualX + 1, actualY, &right) && isSmartPathTile(selection.metatileItems, right.metatileId)) + if (this->layout->getBlock(actualX + 1, actualY, &right) && isSmartPathTile(selection.metatileItems, right.metatileId)) id += 2; - if (map->getBlock(actualX, actualY + 1, &bottom) && isSmartPathTile(selection.metatileItems, bottom.metatileId)) + if (this->layout->getBlock(actualX, actualY + 1, &bottom) && isSmartPathTile(selection.metatileItems, bottom.metatileId)) id += 4; - if (map->getBlock(actualX - 1, actualY, &left) && isSmartPathTile(selection.metatileItems, left.metatileId)) + if (this->layout->getBlock(actualX - 1, actualY, &left) && isSmartPathTile(selection.metatileItems, left.metatileId)) id += 8; block.metatileId = selection.metatileItems.at(smartPathTable[id]).metatileId; @@ -266,19 +266,19 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) { block.collision = collisionItem.collision; block.elevation = collisionItem.elevation; } - map->setBlock(actualX, actualY, block, !fromScriptCall); + this->layout->setBlock(actualX, actualY, block, !fromScriptCall); } - if (!fromScriptCall && map->layout->blockdata != oldMetatiles) { - map->editHistory.push(new PaintMetatile(map, oldMetatiles, map->layout->blockdata, actionId_)); + if (!fromScriptCall && this->layout->blockdata != oldMetatiles) { + this->layout->editHistory.push(new PaintMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_)); } } -void MapPixmapItem::lockNondominantAxis(QGraphicsSceneMouseEvent *event) { +void LayoutPixmapItem::lockNondominantAxis(QGraphicsSceneMouseEvent *event) { /* Return if an axis is already locked, or if the mouse has been released. The mouse release check is necessary - * because MapPixmapItem::mouseReleaseEvent seems to get called before this function, which would unlock the axis + * because LayoutPixmapItem::mouseReleaseEvent seems to get called before this function, which would unlock the axis * and then get immediately re-locked here until the next ctrl-click. */ - if (this->lockedAxis != MapPixmapItem::Axis::None || event->type() == QEvent::GraphicsSceneMouseRelease) + if (this->lockedAxis != LayoutPixmapItem::Axis::None || event->type() == QEvent::GraphicsSceneMouseRelease) return; QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); @@ -293,31 +293,31 @@ void MapPixmapItem::lockNondominantAxis(QGraphicsSceneMouseEvent *event) { int yDiff = pos.y() - this->straight_path_initial_y; if (xDiff || yDiff) { if (abs(xDiff) < abs(yDiff)) { - this->lockedAxis = MapPixmapItem::Axis::X; + this->lockedAxis = LayoutPixmapItem::Axis::X; } else { - this->lockedAxis = MapPixmapItem::Axis::Y; + this->lockedAxis = LayoutPixmapItem::Axis::Y; } } } // Adjust the cooresponding coordinate when it is locked -QPoint MapPixmapItem::adjustCoords(QPoint pos) { - if (this->lockedAxis == MapPixmapItem::Axis::X) { +QPoint LayoutPixmapItem::adjustCoords(QPoint pos) { + if (this->lockedAxis == LayoutPixmapItem::Axis::X) { pos.setX(this->straight_path_initial_x); - } else if (this->lockedAxis == MapPixmapItem::Axis::Y) { + } else if (this->lockedAxis == LayoutPixmapItem::Axis::Y) { pos.setY(this->straight_path_initial_y); } return pos; } -void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) { +void LayoutPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) { QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); - // Snap point to within map bounds. + // Snap point to within layout bounds. if (pos.x() < 0) pos.setX(0); - if (pos.x() >= map->getWidth()) pos.setX(map->getWidth() - 1); + if (pos.x() >= this->layout->getWidth()) pos.setX(this->layout->getWidth() - 1); if (pos.y() < 0) pos.setY(0); - if (pos.y() >= map->getHeight()) pos.setY(map->getHeight() - 1); + if (pos.y() >= this->layout->getHeight()) pos.setY(this->layout->getHeight() - 1); // Update/apply copied metatiles. if (event->type() == QEvent::GraphicsSceneMousePress) { @@ -325,7 +325,7 @@ void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) { selection.clear(); selection.append(QPoint(pos.x(), pos.y())); Block block; - if (map->getBlock(pos.x(), pos.y(), &block)) { + if (this->layout->getBlock(pos.x(), pos.y(), &block)) { this->metatileSelector->selectFromMap(block.metatileId, block.collision, block.elevation); } } else if (event->type() == QEvent::GraphicsSceneMouseMove) { @@ -348,11 +348,11 @@ void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) { int x = point.x(); int y = point.y(); Block block; - if (map->getBlock(x, y, &block)) { + if (this->layout->getBlock(x, y, &block)) { metatiles.append(block.metatileId); } - int blockIndex = y * map->getWidth() + x; - block = map->layout->blockdata.at(blockIndex); + int blockIndex = y * this->layout->getWidth() + x; + block = this->layout->blockdata.at(blockIndex); auto collision = block.collision; auto elevation = block.elevation; collisions.append(QPair(collision, elevation)); @@ -362,8 +362,8 @@ void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) { } } -void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { - if (map) { +void LayoutPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { + if (this->layout) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { actionId_++; } else { @@ -371,7 +371,7 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { Block block; MetatileSelection selection = this->metatileSelector->getMetatileSelection(); int metatileId = selection.metatileItems.first().metatileId; - if (selection.metatileItems.count() > 1 || (map->getBlock(pos.x(), pos.y(), &block) && block.metatileId != metatileId)) { + if (selection.metatileItems.count() > 1 || (this->layout->getBlock(pos.x(), pos.y(), &block) && block.metatileId != metatileId)) { bool smartPathsEnabled = event->modifiers() & Qt::ShiftModifier; if ((this->settings->smartPathsEnabled || smartPathsEnabled) && selection.dimensions.x() == 3 && selection.dimensions.y() == 3) this->floodFillSmartPath(pos.x(), pos.y()); @@ -382,8 +382,8 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { } } -void MapPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) { - if (map) { +void LayoutPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) { + if (this->layout) { if (event->type() == QEvent::GraphicsSceneMouseRelease) { actionId_++; } else { @@ -393,18 +393,18 @@ void MapPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) { } } -void MapPixmapItem::magicFill(int x, int y, uint16_t metatileId, bool fromScriptCall) { +void LayoutPixmapItem::magicFill(int x, int y, uint16_t metatileId, bool fromScriptCall) { QPoint selectionDimensions(1, 1); QList selectedMetatiles = QList({MetatileSelectionItem{ true, metatileId }}); this->magicFill(x, y, selectionDimensions, selectedMetatiles, QList(), fromScriptCall); } -void MapPixmapItem::magicFill(int x, int y, bool fromScriptCall) { +void LayoutPixmapItem::magicFill(int x, int y, bool fromScriptCall) { MetatileSelection selection = this->metatileSelector->getMetatileSelection(); this->magicFill(x, y, selection.dimensions, selection.metatileItems, selection.collisionItems, fromScriptCall); } -void MapPixmapItem::magicFill( +void LayoutPixmapItem::magicFill( int initialX, int initialY, QPoint selectionDimensions, @@ -412,18 +412,18 @@ void MapPixmapItem::magicFill( QList selectedCollisions, bool fromScriptCall) { Block block; - if (map->getBlock(initialX, initialY, &block)) { + if (this->layout->getBlock(initialX, initialY, &block)) { if (selectedMetatiles.length() == 1 && selectedMetatiles.at(0).metatileId == block.metatileId) { return; } - Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata(); + Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata(); bool setCollisions = selectedCollisions.length() == selectedMetatiles.length(); uint16_t metatileId = block.metatileId; - for (int y = 0; y < map->getHeight(); y++) { - for (int x = 0; x < map->getWidth(); x++) { - if (map->getBlock(x, y, &block) && block.metatileId == metatileId) { + for (int y = 0; y < this->layout->getHeight(); y++) { + for (int x = 0; x < this->layout->getWidth(); x++) { + if (this->layout->getBlock(x, y, &block) && block.metatileId == metatileId) { int xDiff = x - initialX; int yDiff = y - initialY; int i = xDiff % selectionDimensions.x(); @@ -438,30 +438,30 @@ void MapPixmapItem::magicFill( block.collision = item.collision; block.elevation = item.elevation; } - map->setBlock(x, y, block, !fromScriptCall); + this->layout->setBlock(x, y, block, !fromScriptCall); } } } } - if (!fromScriptCall && map->layout->blockdata != oldMetatiles) { - map->editHistory.push(new MagicFillMetatile(map, oldMetatiles, map->layout->blockdata, actionId_)); + if (!fromScriptCall && this->layout->blockdata != oldMetatiles) { + this->layout->editHistory.push(new MagicFillMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_)); } } } -void MapPixmapItem::floodFill(int initialX, int initialY, bool fromScriptCall) { +void LayoutPixmapItem::floodFill(int initialX, int initialY, bool fromScriptCall) { MetatileSelection selection = this->metatileSelector->getMetatileSelection(); this->floodFill(initialX, initialY, selection.dimensions, selection.metatileItems, selection.collisionItems, fromScriptCall); } -void MapPixmapItem::floodFill(int initialX, int initialY, uint16_t metatileId, bool fromScriptCall) { +void LayoutPixmapItem::floodFill(int initialX, int initialY, uint16_t metatileId, bool fromScriptCall) { QPoint selectionDimensions(1, 1); QList selectedMetatiles = QList({MetatileSelectionItem{true, metatileId}}); this->floodFill(initialX, initialY, selectionDimensions, selectedMetatiles, QList(), fromScriptCall); } -void MapPixmapItem::floodFill( +void LayoutPixmapItem::floodFill( int initialX, int initialY, QPoint selectionDimensions, @@ -469,7 +469,7 @@ void MapPixmapItem::floodFill( QList selectedCollisions, bool fromScriptCall) { bool setCollisions = selectedCollisions.length() == selectedMetatiles.length(); - Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata(); + Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata(); QSet visited; QList todo; @@ -479,11 +479,11 @@ void MapPixmapItem::floodFill( int x = point.x(); int y = point.y(); Block block; - if (!map->getBlock(x, y, &block)) { + if (!this->layout->getBlock(x, y, &block)) { continue; } - visited.insert(x + y * map->getWidth()); + visited.insert(x + y * this->layout->getWidth()); int xDiff = x - initialX; int yDiff = y - initialY; int i = xDiff % selectionDimensions.x(); @@ -500,32 +500,32 @@ void MapPixmapItem::floodFill( block.collision = item.collision; block.elevation = item.elevation; } - map->setBlock(x, y, block, !fromScriptCall); + this->layout->setBlock(x, y, block, !fromScriptCall); } - if (!visited.contains(x + 1 + y * map->getWidth()) && map->getBlock(x + 1, y, &block) && block.metatileId == old_metatileId) { + if (!visited.contains(x + 1 + y * this->layout->getWidth()) && this->layout->getBlock(x + 1, y, &block) && block.metatileId == old_metatileId) { todo.append(QPoint(x + 1, y)); - visited.insert(x + 1 + y * map->getWidth()); + visited.insert(x + 1 + y * this->layout->getWidth()); } - if (!visited.contains(x - 1 + y * map->getWidth()) && map->getBlock(x - 1, y, &block) && block.metatileId == old_metatileId) { + if (!visited.contains(x - 1 + y * this->layout->getWidth()) && this->layout->getBlock(x - 1, y, &block) && block.metatileId == old_metatileId) { todo.append(QPoint(x - 1, y)); - visited.insert(x - 1 + y * map->getWidth()); + visited.insert(x - 1 + y * this->layout->getWidth()); } - if (!visited.contains(x + (y + 1) * map->getWidth()) && map->getBlock(x, y + 1, &block) && block.metatileId == old_metatileId) { + if (!visited.contains(x + (y + 1) * this->layout->getWidth()) && this->layout->getBlock(x, y + 1, &block) && block.metatileId == old_metatileId) { todo.append(QPoint(x, y + 1)); - visited.insert(x + (y + 1) * map->getWidth()); + visited.insert(x + (y + 1) * this->layout->getWidth()); } - if (!visited.contains(x + (y - 1) * map->getWidth()) && map->getBlock(x, y - 1, &block) && block.metatileId == old_metatileId) { + if (!visited.contains(x + (y - 1) * this->layout->getWidth()) && this->layout->getBlock(x, y - 1, &block) && block.metatileId == old_metatileId) { todo.append(QPoint(x, y - 1)); - visited.insert(x + (y - 1) * map->getWidth()); + visited.insert(x + (y - 1) * this->layout->getWidth()); } } - if (!fromScriptCall && map->layout->blockdata != oldMetatiles) { - map->editHistory.push(new BucketFillMetatile(map, oldMetatiles, map->layout->blockdata, actionId_)); + if (!fromScriptCall && this->layout->blockdata != oldMetatiles) { + this->layout->editHistory.push(new BucketFillMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_)); } } -void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScriptCall) { +void LayoutPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScriptCall) { MetatileSelection selection = this->metatileSelector->getMetatileSelection(); if (!isValidSmartPathSelection(selection)) return; @@ -542,7 +542,7 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri setCollisions = true; } - Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata(); + Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata(); // Flood fill the region with the open tile. QList todo; @@ -552,7 +552,7 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri int x = point.x(); int y = point.y(); Block block; - if (!map->getBlock(x, y, &block)) { + if (!this->layout->getBlock(x, y, &block)) { continue; } @@ -566,17 +566,17 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri block.collision = openTileCollision; block.elevation = openTileElevation; } - map->setBlock(x, y, block, !fromScriptCall); - if (map->getBlock(x + 1, y, &block) && block.metatileId == old_metatileId) { + this->layout->setBlock(x, y, block, !fromScriptCall); + if (this->layout->getBlock(x + 1, y, &block) && block.metatileId == old_metatileId) { todo.append(QPoint(x + 1, y)); } - if (map->getBlock(x - 1, y, &block) && block.metatileId == old_metatileId) { + if (this->layout->getBlock(x - 1, y, &block) && block.metatileId == old_metatileId) { todo.append(QPoint(x - 1, y)); } - if (map->getBlock(x, y + 1, &block) && block.metatileId == old_metatileId) { + if (this->layout->getBlock(x, y + 1, &block) && block.metatileId == old_metatileId) { todo.append(QPoint(x, y + 1)); } - if (map->getBlock(x, y - 1, &block) && block.metatileId == old_metatileId) { + if (this->layout->getBlock(x, y - 1, &block) && block.metatileId == old_metatileId) { todo.append(QPoint(x, y - 1)); } } @@ -590,11 +590,11 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri int x = point.x(); int y = point.y(); Block block; - if (!map->getBlock(x, y, &block)) { + if (!this->layout->getBlock(x, y, &block)) { continue; } - visited.insert(x + y * map->getWidth()); + visited.insert(x + y * this->layout->getWidth()); int id = 0; Block top; Block right; @@ -602,13 +602,13 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri Block left; // Get marching squares value, to determine which tile to use. - if (map->getBlock(x, y - 1, &top) && isSmartPathTile(selection.metatileItems, top.metatileId)) + if (this->layout->getBlock(x, y - 1, &top) && isSmartPathTile(selection.metatileItems, top.metatileId)) id += 1; - if (map->getBlock(x + 1, y, &right) && isSmartPathTile(selection.metatileItems, right.metatileId)) + if (this->layout->getBlock(x + 1, y, &right) && isSmartPathTile(selection.metatileItems, right.metatileId)) id += 2; - if (map->getBlock(x, y + 1, &bottom) && isSmartPathTile(selection.metatileItems, bottom.metatileId)) + if (this->layout->getBlock(x, y + 1, &bottom) && isSmartPathTile(selection.metatileItems, bottom.metatileId)) id += 4; - if (map->getBlock(x - 1, y, &left) && isSmartPathTile(selection.metatileItems, left.metatileId)) + if (this->layout->getBlock(x - 1, y, &left) && isSmartPathTile(selection.metatileItems, left.metatileId)) id += 8; block.metatileId = selection.metatileItems.at(smartPathTable[id]).metatileId; @@ -617,41 +617,41 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri block.collision = item.collision; block.elevation = item.elevation; } - map->setBlock(x, y, block, !fromScriptCall); + this->layout->setBlock(x, y, block, !fromScriptCall); // Visit neighbors if they are smart-path tiles, and don't revisit any. - if (!visited.contains(x + 1 + y * map->getWidth()) && map->getBlock(x + 1, y, &block) && isSmartPathTile(selection.metatileItems, block.metatileId)) { + if (!visited.contains(x + 1 + y * this->layout->getWidth()) && this->layout->getBlock(x + 1, y, &block) && isSmartPathTile(selection.metatileItems, block.metatileId)) { todo.append(QPoint(x + 1, y)); - visited.insert(x + 1 + y * map->getWidth()); + visited.insert(x + 1 + y * this->layout->getWidth()); } - if (!visited.contains(x - 1 + y * map->getWidth()) && map->getBlock(x - 1, y, &block) && isSmartPathTile(selection.metatileItems, block.metatileId)) { + if (!visited.contains(x - 1 + y * this->layout->getWidth()) && this->layout->getBlock(x - 1, y, &block) && isSmartPathTile(selection.metatileItems, block.metatileId)) { todo.append(QPoint(x - 1, y)); - visited.insert(x - 1 + y * map->getWidth()); + visited.insert(x - 1 + y * this->layout->getWidth()); } - if (!visited.contains(x + (y + 1) * map->getWidth()) && map->getBlock(x, y + 1, &block) && isSmartPathTile(selection.metatileItems, block.metatileId)) { + if (!visited.contains(x + (y + 1) * this->layout->getWidth()) && this->layout->getBlock(x, y + 1, &block) && isSmartPathTile(selection.metatileItems, block.metatileId)) { todo.append(QPoint(x, y + 1)); - visited.insert(x + (y + 1) * map->getWidth()); + visited.insert(x + (y + 1) * this->layout->getWidth()); } - if (!visited.contains(x + (y - 1) * map->getWidth()) && map->getBlock(x, y - 1, &block) && isSmartPathTile(selection.metatileItems, block.metatileId)) { + if (!visited.contains(x + (y - 1) * this->layout->getWidth()) && this->layout->getBlock(x, y - 1, &block) && isSmartPathTile(selection.metatileItems, block.metatileId)) { todo.append(QPoint(x, y - 1)); - visited.insert(x + (y - 1) * map->getWidth()); + visited.insert(x + (y - 1) * this->layout->getWidth()); } } - if (!fromScriptCall && map->layout->blockdata != oldMetatiles) { - map->editHistory.push(new BucketFillMetatile(map, oldMetatiles, map->layout->blockdata, actionId_)); + if (!fromScriptCall && this->layout->blockdata != oldMetatiles) { + this->layout->editHistory.push(new BucketFillMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_)); } } -void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) { +void LayoutPixmapItem::pick(QGraphicsSceneMouseEvent *event) { QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); Block block; - if (map->getBlock(pos.x(), pos.y(), &block)) { + if (this->layout->getBlock(pos.x(), pos.y(), &block)) { this->metatileSelector->selectFromMap(block.metatileId, block.collision, block.elevation); } } -void MapPixmapItem::select(QGraphicsSceneMouseEvent *event) { +void LayoutPixmapItem::select(QGraphicsSceneMouseEvent *event) { QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); if (event->type() == QEvent::GraphicsSceneMousePress) { selection_origin = QPoint(pos.x(), pos.y()); @@ -681,43 +681,47 @@ void MapPixmapItem::select(QGraphicsSceneMouseEvent *event) { } } -void MapPixmapItem::draw(bool ignoreCache) { - if (map) { - map->setMapItem(this); - setPixmap(map->render(ignoreCache)); +void LayoutPixmapItem::draw(bool ignoreCache) { + if (this->layout) { + layout->setLayoutItem(this); + setPixmap(this->layout->render(ignoreCache)); } } -void MapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { +void LayoutPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); if (pos != this->metatilePos) { this->metatilePos = pos; emit this->hoveredMapMetatileChanged(pos); } - if (this->settings->betterCursors && this->paintingMode != MapPixmapItem::PaintMode::Disabled) { + if (this->settings->betterCursors && this->paintingMode != LayoutPixmapItem::PaintMode::Disabled) { setCursor(this->settings->mapCursor); } } -void MapPixmapItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) { + +void LayoutPixmapItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) { this->has_mouse = true; QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); emit this->hoveredMapMetatileChanged(pos); } -void MapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { + +void LayoutPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { emit this->hoveredMapMetatileCleared(); - if (this->settings->betterCursors && this->paintingMode != MapPixmapItem::PaintMode::Disabled) { + if (this->settings->betterCursors && this->paintingMode != LayoutPixmapItem::PaintMode::Disabled) { unsetCursor(); } this->has_mouse = false; } -void MapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { + +void LayoutPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); this->paint_tile_initial_x = this->straight_path_initial_x = pos.x(); this->paint_tile_initial_y = this->straight_path_initial_y = pos.y(); emit startPaint(event, this); emit mouseEvent(event, this); } -void MapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { + +void LayoutPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); if (pos != this->metatilePos) { this->metatilePos = pos; @@ -725,8 +729,9 @@ void MapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { } emit mouseEvent(event, this); } -void MapPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - this->lockedAxis = MapPixmapItem::Axis::None; + +void LayoutPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { + this->lockedAxis = LayoutPixmapItem::Axis::None; emit endPaint(event, this); emit mouseEvent(event, this); } diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 4a8eb262f..53a65154f 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -217,3 +217,146 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { return QStandardItemModel::data(index, role); } + + + + + + + + + + + + + + + // case MapSortOrder::Layout: + // { + // QMap layoutIndices; + // for (int i = 0; i < project->mapLayoutsTable.length(); i++) { + // QString layoutId = project->mapLayoutsTable.value(i); + // MapLayout *layout = project->mapLayouts.value(layoutId); + // QStandardItem *layoutItem = new QStandardItem; + // layoutItem->setText(layout->name); + // layoutItem->setIcon(folderIcon); + // layoutItem->setEditable(false); + // layoutItem->setData(layout->name, Qt::UserRole); + // layoutItem->setData("map_layout", MapListUserRoles::TypeRole); + // layoutItem->setData(layout->id, MapListUserRoles::TypeRole2); + // layoutItem->setData(i, MapListUserRoles::GroupRole); + // root->appendRow(layoutItem); + // mapGroupItemsList->append(layoutItem); + // layoutIndices[layoutId] = i; + // } + // for (int i = 0; i < project->groupNames.length(); i++) { + // QStringList names = project->groupedMapNames.value(i); + // for (int j = 0; j < names.length(); j++) { + // QString map_name = names.value(j); + // QStandardItem *map = createMapItem(map_name, i, j); + // QString layoutId = project->readMapLayoutId(map_name); + // QStandardItem *layoutItem = mapGroupItemsList->at(layoutIndices.value(layoutId)); + // layoutItem->setIcon(mapFolderIcon); + // layoutItem->appendRow(map); + // mapListIndexes.insert(map_name, map->index()); + // } + // } + // break; + // } +LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : QStandardItemModel(parent) { + // + + this->project = project; + this->root = this->invisibleRootItem(); + + initialize(); +} + +QStandardItem *LayoutTreeModel::createLayoutItem(QString layoutName) { + QStandardItem *layout = new QStandardItem; + layout->setText(layoutName); + layout->setEditable(false); + layout->setData(layoutName, Qt::UserRole); + layout->setData("map_layout", MapListRoles::TypeRole); + // // group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + this->layoutItems.insert(layoutName, layout); + return layout; +} + +QStandardItem *LayoutTreeModel::createMapItem(QString mapName) { + QStandardItem *map = new QStandardItem; + map->setText(mapName); + map->setEditable(false); + map->setData(mapName, Qt::UserRole); + map->setData("map_name", MapListRoles::TypeRole); + map->setFlags(Qt::NoItemFlags | Qt::ItemNeverHasChildren); + this->mapItems.insert(mapName, map); + return map; +} + +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); + this->root->appendRow(layoutItem); + } + + for (auto mapList : this->project->groupedMapNames) { + for (auto mapName : mapList) { + // + QString layoutName = project->readMapLayoutName(mapName); + QStandardItem *map = createMapItem(mapName); + this->layoutItems[layoutName]->appendRow(map); + } + } + + // // project->readMapLayoutName +} + +QStandardItem *LayoutTreeModel::getItem(const QModelIndex &index) const { + if (index.isValid()) { + QStandardItem *item = static_cast(index.internalPointer()); + if (item) + return item; + } + return this->root; +} + +QModelIndex LayoutTreeModel::indexOfLayout(QString layoutName) { + if (this->layoutItems.contains(layoutName)) { + return this->layoutItems[layoutName]->index(); + } + return QModelIndex(); +} + +QVariant LayoutTreeModel::data(const QModelIndex &index, int role) const { + int row = index.row(); + int col = index.column(); + + if (role == Qt::DecorationRole) { + static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico")); + static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico")); + static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico")); + + QStandardItem *item = this->getItem(index)->child(row, col); + QString type = item->data(MapListRoles::TypeRole).toString(); + + if (type == "map_layout") { + return mapIcon; + } + else if (type == "map_name") { + return QVariant(); + } + + return QVariant(); + + // check if map or group + // if map, check if edited or open + //return QIcon(":/icons/porymap-icon-2.ico"); + } + + return QStandardItemModel::data(index, role); +} + diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index ba3159751..eb3eae45f 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -96,13 +96,13 @@ void NewMapPopup::init() { void NewMapPopup::init(MapSortOrder type, QVariant data) { switch (type) { - case MapSortOrder::Group: + case MapSortOrder::SortByGroup: settings.group = project->groupNames.at(data.toInt()); break; - case MapSortOrder::Area: + case MapSortOrder::SortByArea: settings.location = data.toString(); break; - case MapSortOrder::Layout: + case MapSortOrder::SortByLayout: useLayout(data.toString()); break; } From 90f8218c32e77c96a48a372f04a154ee86067017 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 1 Feb 2023 15:02:26 -0500 Subject: [PATCH 04/70] fix edit commands and ui things to use layout instead of map --- include/core/editcommands.h | 6 +- include/core/map.h | 66 +--- include/core/maplayout.h | 5 +- .../ui/currentselectedmetatilespixmapitem.h | 13 +- include/ui/metatileselector.h | 12 +- include/ui/prefab.h | 6 +- include/ui/prefabcreationdialog.h | 7 +- include/ui/tileseteditor.h | 11 +- include/ui/tileseteditormetatileselector.h | 7 +- src/core/editcommands.cpp | 64 ++-- src/core/map.cpp | 326 +----------------- src/core/maplayout.cpp | 8 + src/editor.cpp | 32 +- src/mainwindow.cpp | 24 +- src/scriptapi/apimap.cpp | 250 +++++++------- src/scriptapi/apioverlay.cpp | 26 +- src/scriptapi/apiutility.cpp | 16 +- src/ui/currentselectedmetatilespixmapitem.cpp | 12 +- src/ui/mapimageexporter.cpp | 28 +- src/ui/metatileselector.cpp | 6 +- src/ui/prefab.cpp | 28 +- src/ui/prefabcreationdialog.cpp | 10 +- src/ui/tileseteditor.cpp | 18 +- src/ui/tileseteditormetatileselector.cpp | 8 +- 24 files changed, 315 insertions(+), 674 deletions(-) diff --git a/include/core/editcommands.h b/include/core/editcommands.h index 6cfaf3b99..7d89a35a7 100644 --- a/include/core/editcommands.h +++ b/include/core/editcommands.h @@ -342,12 +342,12 @@ class EventPaste : public EventDuplicate { -// !TODO +// !TODO: rename map vars to layout /// Implements a command to commit map edits from the scripting API. /// The scripting api can edit map/border blocks and dimensions. class ScriptEditMap : public QUndoCommand { public: - ScriptEditMap(Map *map, + ScriptEditMap(Layout *layout, QSize oldMapDimensions, QSize newMapDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, QSize oldBorderDimensions, QSize newBorderDimensions, @@ -361,7 +361,7 @@ class ScriptEditMap : public QUndoCommand { int id() const override { return CommandId::ID_ScriptEditMap; } private: - Map *map; + Layout *layout = nullptr; Blockdata newMetatiles; Blockdata oldMetatiles; diff --git a/include/core/map.h b/include/core/map.h index 33105c50c..37ae9b581 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -66,20 +66,11 @@ class Map : public QObject bool needsLayoutDir = true; bool needsHealLocation = false; - QImage collision_image; - QPixmap collision_pixmap; - QImage image; - QPixmap pixmap; - QMap> events; QList ownedEvents; // for memory management QList connections; - // !TODO - QList metatileLayerOrder; - QList metatileLayerOpacity; - void setName(QString mapName); static QString mapConstantFromName(QString mapName); @@ -89,68 +80,21 @@ class Map : public QObject int getBorderWidth(); int getBorderHeight(); - QUndoStack editHistory; - void modify(); - void clean(); - - QPixmap render(bool ignoreCache = false, Layout *fromLayout = nullptr, QRect bounds = QRect(0, 0, -1, -1)); - QPixmap renderCollision(bool ignoreCache); - QPixmap renderConnection(MapConnection, Layout *); - QPixmap renderBorder(bool ignoreCache = false); - - bool mapBlockChanged(int i, const Blockdata &cache); - bool borderBlockChanged(int i, const Blockdata &cache); - - // !TODO: remove - void cacheBlockdata(); - void cacheCollision(); - - /// !TODO: remove this - bool getBlock(int x, int y, Block *out); - void setBlock(int x, int y, Block block, bool enableScriptCallback = false); - void setBlockdata(Blockdata blockdata, bool enableScriptCallback = false); - - uint16_t getBorderMetatileId(int x, int y); - void setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback = false); - void setBorderBlockData(Blockdata blockdata, bool enableScriptCallback = false); - - 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); - QList getAllEvents() const; QStringList eventScriptLabels(Event::Group group = Event::Group::None) const; void removeEvent(Event *); void addEvent(Event *); - void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); - void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); - - void clearBorderCache(); - void cacheBorder(); - - bool hasUnsavedChanges(); - - bool isWithinBounds(int x, int y); - bool isWithinBorderBounds(int x, int y); - void openScript(QString label); -private: - LayoutPixmapItem *mapItem = nullptr; - -public: - void setMapItem(LayoutPixmapItem *item) { mapItem = item; } + QUndoStack editHistory; + void modify(); + void clean(); + bool hasUnsavedChanges(); - CollisionPixmapItem *collisionItem = nullptr; - void setCollisionItem(CollisionPixmapItem *item) { collisionItem = item; } + QPixmap renderConnection(MapConnection, Layout *); - BorderMetatilesPixmapItem *borderItem = nullptr; - void setBorderItem(BorderMetatilesPixmapItem *item) { borderItem = item; } -private: - void setNewDimensionsBlockdata(int newWidth, int newHeight); - void setNewBorderDimensionsBlockdata(int newWidth, int newHeight); signals: void mapChanged(Map *map); diff --git a/include/core/maplayout.h b/include/core/maplayout.h index ffbe61275..5e7c0f7c9 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -77,9 +77,8 @@ class Layout : public QObject { int getBorderWidth(); int getBorderHeight(); - bool isWithinBounds(int x, int y) { - return (x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight()); - } + bool isWithinBounds(int x, int y); + bool isWithinBorderBounds(int x, int y); bool getBlock(int x, int y, Block *out); void setBlock(int x, int y, Block block, bool enableScriptCallback = false); diff --git a/include/ui/currentselectedmetatilespixmapitem.h b/include/ui/currentselectedmetatilespixmapitem.h index 5e4bd2756..109f52c56 100644 --- a/include/ui/currentselectedmetatilespixmapitem.h +++ b/include/ui/currentselectedmetatilespixmapitem.h @@ -1,23 +1,24 @@ #ifndef CURRENTSELECTEDMETATILESPIXMAPITEM_H #define CURRENTSELECTEDMETATILESPIXMAPITEM_H -#include "map.h" #include "metatileselector.h" #include +class Layout; + class CurrentSelectedMetatilesPixmapItem : public QGraphicsPixmapItem { public: - CurrentSelectedMetatilesPixmapItem(Map *map, MetatileSelector *metatileSelector) { - this->map = map; + CurrentSelectedMetatilesPixmapItem(Layout *layout, MetatileSelector *metatileSelector) { + this->layout = layout; this->metatileSelector = metatileSelector; } - Map* map = nullptr; + Layout *layout = nullptr; MetatileSelector *metatileSelector; void draw(); - void setMap(Map *map) { this->map = map; } + void setLayout(Layout *layout) { this->layout = layout; } }; -QPixmap drawMetatileSelection(MetatileSelection selection, Map *map); +QPixmap drawMetatileSelection(MetatileSelection selection, Layout *layout); #endif // CURRENTSELECTEDMETATILESPIXMAPITEM_H diff --git a/include/ui/metatileselector.h b/include/ui/metatileselector.h index 0c0b779f2..6fe25784a 100644 --- a/include/ui/metatileselector.h +++ b/include/ui/metatileselector.h @@ -31,13 +31,13 @@ struct MetatileSelection class MetatileSelector: public SelectablePixmapItem { Q_OBJECT public: - MetatileSelector(int numMetatilesWide, Map *map): SelectablePixmapItem(16, 16) { + MetatileSelector(int numMetatilesWide, Layout *layout): SelectablePixmapItem(16, 16) { this->externalSelection = false; this->prefabSelection = false; this->numMetatilesWide = numMetatilesWide; - this->map = map; - this->primaryTileset = map->layout->tileset_primary; - this->secondaryTileset = map->layout->tileset_secondary; + this->layout = layout; + this->primaryTileset = layout->tileset_primary; + this->secondaryTileset = layout->tileset_secondary; this->selection = MetatileSelection{}; setAcceptHoverEvents(true); } @@ -50,7 +50,7 @@ class MetatileSelector: public SelectablePixmapItem { void setPrefabSelection(MetatileSelection selection); void setExternalSelection(int, int, QList, QList>); QPoint getMetatileIdCoordsOnWidget(uint16_t); - void setMap(Map*); + void setLayout(Layout *layout); Tileset *primaryTileset; Tileset *secondaryTileset; protected: @@ -63,7 +63,7 @@ class MetatileSelector: public SelectablePixmapItem { bool externalSelection; bool prefabSelection; int numMetatilesWide; - Map *map; + Layout *layout; int externalSelectionWidth; int externalSelectionHeight; QList externalSelectedMetatiles; diff --git a/include/ui/prefab.h b/include/ui/prefab.h index 7bd9e0b24..2ac8fa042 100644 --- a/include/ui/prefab.h +++ b/include/ui/prefab.h @@ -20,9 +20,9 @@ struct PrefabItem class Prefab { public: - void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map); - void addPrefab(MetatileSelection selection, Map *map, QString name); - void updatePrefabUi(Map *map); + void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Layout *layout); + void addPrefab(MetatileSelection selection, Layout *layout, QString name); + void updatePrefabUi(Layout *layout); bool tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath = ""); private: diff --git a/include/ui/prefabcreationdialog.h b/include/ui/prefabcreationdialog.h index 5748f35af..0821f7512 100644 --- a/include/ui/prefabcreationdialog.h +++ b/include/ui/prefabcreationdialog.h @@ -2,10 +2,11 @@ #define PREFABCREATIONDIALOG_H #include "metatileselector.h" -#include "map.h" #include +class Layout; + namespace Ui { class PrefabCreationDialog; } @@ -15,12 +16,12 @@ class PrefabCreationDialog : public QDialog Q_OBJECT public: - explicit PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Map *map); + explicit PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Layout *layout); ~PrefabCreationDialog(); void savePrefab(); private: - Map *map; + Layout *layout = nullptr; Ui::PrefabCreationDialog *ui; MetatileSelection selection; }; diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 5a46075cb..5e1b3b644 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -8,7 +8,8 @@ #include "tileseteditormetatileselector.h" #include "tileseteditortileselector.h" #include "metatilelayersitem.h" -#include "map.h" + +class Layout; namespace Ui { class TilesetEditor; @@ -39,10 +40,10 @@ class TilesetEditor : public QMainWindow Q_OBJECT public: - explicit TilesetEditor(Project*, Map*, QWidget *parent = nullptr); + explicit TilesetEditor(Project *project, Layout *layout, QWidget *parent = nullptr); ~TilesetEditor(); - void update(Map *map, QString primaryTilsetLabel, QString secondaryTilesetLabel); - void updateMap(Map *map); + void update(Layout *layout, QString primaryTilsetLabel, QString secondaryTilesetLabel); + void updateLayout(Layout *layout); void updateTilesets(QString primaryTilsetLabel, QString secondaryTilesetLabel); bool selectMetatile(uint16_t metatileId); uint16_t getSelectedMetatileId(); @@ -148,7 +149,7 @@ private slots: MetatileLayersItem *metatileLayersItem = nullptr; PaletteEditor *paletteEditor = nullptr; Project *project = nullptr; - Map *map = nullptr; + Layout *layout = nullptr; Metatile *metatile = nullptr; Metatile *copiedMetatile = nullptr; QString copiedMetatileLabel; diff --git a/include/ui/tileseteditormetatileselector.h b/include/ui/tileseteditormetatileselector.h index ef5255dc6..ee56f013f 100644 --- a/include/ui/tileseteditormetatileselector.h +++ b/include/ui/tileseteditormetatileselector.h @@ -3,13 +3,14 @@ #include "selectablepixmapitem.h" #include "tileset.h" -#include "map.h" + +class Layout; class TilesetEditorMetatileSelector: public SelectablePixmapItem { Q_OBJECT public: - TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Map *map); - Map *map = nullptr; + TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout); + Layout *layout = nullptr; void draw(); bool select(uint16_t metatileId); void setTilesets(Tileset*, Tileset*, bool draw = true); diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp index 91ea18b38..a20969056 100644 --- a/src/core/editcommands.cpp +++ b/src/core/editcommands.cpp @@ -487,7 +487,7 @@ int EventPaste::id() const { ************************************************************************ ******************************************************************************/ -ScriptEditMap::ScriptEditMap(Map *map, +ScriptEditMap::ScriptEditMap(Layout *layout, QSize oldMapDimensions, QSize newMapDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, QSize oldBorderDimensions, QSize newBorderDimensions, @@ -495,7 +495,7 @@ ScriptEditMap::ScriptEditMap(Map *map, QUndoCommand *parent) : QUndoCommand(parent) { setText("Script Edit Map"); - this->map = map; + this->layout = layout; this->newMetatiles = newMetatiles; this->oldMetatiles = oldMetatiles; @@ -517,57 +517,57 @@ ScriptEditMap::ScriptEditMap(Map *map, void ScriptEditMap::redo() { QUndoCommand::redo(); - if (!map) return; + if (!layout) return; - if (newMapWidth != map->getWidth() || newMapHeight != map->getHeight()) { - map->layout->blockdata = newMetatiles; - map->setDimensions(newMapWidth, newMapHeight, false); + if (newMapWidth != layout->getWidth() || newMapHeight != layout->getHeight()) { + layout->blockdata = newMetatiles; + layout->setDimensions(newMapWidth, newMapHeight, false); } else { - map->setBlockdata(newMetatiles); + layout->setBlockdata(newMetatiles); } - if (newBorderWidth != map->getBorderWidth() || newBorderHeight != map->getBorderHeight()) { - map->layout->border = newBorder; - map->setBorderDimensions(newBorderWidth, newBorderHeight, false); + if (newBorderWidth != layout->getBorderWidth() || newBorderHeight != layout->getBorderHeight()) { + layout->border = newBorder; + layout->setBorderDimensions(newBorderWidth, newBorderHeight, false); } else { - map->setBorderBlockData(newBorder); + layout->setBorderBlockData(newBorder); } - map->layout->lastCommitBlocks.blocks = newMetatiles; - map->layout->lastCommitBlocks.mapDimensions = QSize(newMapWidth, newMapHeight); - map->layout->lastCommitBlocks.border = newBorder; - map->layout->lastCommitBlocks.borderDimensions = QSize(newBorderWidth, newBorderHeight); + layout->lastCommitBlocks.blocks = newMetatiles; + layout->lastCommitBlocks.mapDimensions = QSize(newMapWidth, newMapHeight); + layout->lastCommitBlocks.border = newBorder; + layout->lastCommitBlocks.borderDimensions = QSize(newBorderWidth, newBorderHeight); // !TODO - renderBlocks(map->layout); - map->borderItem->draw(); + renderBlocks(layout); + layout->borderItem->draw(); } void ScriptEditMap::undo() { - if (!map) return; + if (!layout) return; - if (oldMapWidth != map->getWidth() || oldMapHeight != map->getHeight()) { - map->layout->blockdata = oldMetatiles; - map->setDimensions(oldMapWidth, oldMapHeight, false); + if (oldMapWidth != layout->getWidth() || oldMapHeight != layout->getHeight()) { + layout->blockdata = oldMetatiles; + layout->setDimensions(oldMapWidth, oldMapHeight, false); } else { - map->setBlockdata(oldMetatiles); + layout->setBlockdata(oldMetatiles); } - if (oldBorderWidth != map->getBorderWidth() || oldBorderHeight != map->getBorderHeight()) { - map->layout->border = oldBorder; - map->setBorderDimensions(oldBorderWidth, oldBorderHeight, false); + if (oldBorderWidth != layout->getBorderWidth() || oldBorderHeight != layout->getBorderHeight()) { + layout->border = oldBorder; + layout->setBorderDimensions(oldBorderWidth, oldBorderHeight, false); } else { - map->setBorderBlockData(oldBorder); + layout->setBorderBlockData(oldBorder); } - map->layout->lastCommitBlocks.blocks = oldMetatiles; - map->layout->lastCommitBlocks.mapDimensions = QSize(oldMapWidth, oldMapHeight); - map->layout->lastCommitBlocks.border = oldBorder; - map->layout->lastCommitBlocks.borderDimensions = QSize(oldBorderWidth, oldBorderHeight); + layout->lastCommitBlocks.blocks = oldMetatiles; + layout->lastCommitBlocks.mapDimensions = QSize(oldMapWidth, oldMapHeight); + layout->lastCommitBlocks.border = oldBorder; + layout->lastCommitBlocks.borderDimensions = QSize(oldBorderWidth, oldBorderHeight); // !TODO - renderBlocks(map->layout); - map->borderItem->draw(); + renderBlocks(layout); + layout->borderItem->draw(); QUndoCommand::undo(); } diff --git a/src/core/map.cpp b/src/core/map.cpp index 181cde359..fdfb030cc 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -60,121 +60,6 @@ int Map::getBorderHeight() { return layout->getBorderHeight(); } -bool Map::mapBlockChanged(int i, const Blockdata &cache) { - if (cache.length() <= i) - return true; - if (layout->blockdata.length() <= i) - return true; - - return layout->blockdata.at(i) != cache.at(i); -} - -bool Map::borderBlockChanged(int i, const Blockdata &cache) { - if (cache.length() <= i) - return true; - if (layout->border.length() <= i) - return true; - - return layout->border.at(i) != cache.at(i); -} - -void Map::clearBorderCache() { - layout->cached_border.clear(); -} - -void Map::cacheBorder() { - layout->cached_border.clear(); - for (const auto &block : layout->border) - layout->cached_border.append(block); -} - -void Map::cacheBlockdata() { - layout->cached_blockdata.clear(); - for (const auto &block : layout->blockdata) - layout->cached_blockdata.append(block); -} - -void Map::cacheCollision() { - layout->cached_collision.clear(); - for (const auto &block : layout->blockdata) - layout->cached_collision.append(block); -} - -QPixmap Map::renderCollision(bool ignoreCache) { - bool changed_any = false; - int width_ = getWidth(); - int height_ = getHeight(); - if (collision_image.isNull() || collision_image.width() != width_ * 16 || collision_image.height() != height_ * 16) { - collision_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); - changed_any = true; - } - if (layout->blockdata.isEmpty() || !width_ || !height_) { - collision_pixmap = collision_pixmap.fromImage(collision_image); - return collision_pixmap; - } - QPainter painter(&collision_image); - for (int i = 0; i < layout->blockdata.length(); i++) { - if (!ignoreCache && !mapBlockChanged(i, layout->cached_collision)) { - continue; - } - changed_any = true; - Block block = layout->blockdata.at(i); - QImage collision_metatile_image = getCollisionMetatileImage(block); - int map_y = width_ ? i / width_ : 0; - int map_x = width_ ? i % width_ : 0; - QPoint metatile_origin = QPoint(map_x * 16, map_y * 16); - painter.drawImage(metatile_origin, collision_metatile_image); - } - painter.end(); - cacheCollision(); - if (changed_any) { - collision_pixmap = collision_pixmap.fromImage(collision_image); - } - return collision_pixmap; -} - -QPixmap Map::render(bool ignoreCache, Layout *fromLayout, QRect bounds) { - return this->layout->render(ignoreCache, fromLayout, bounds); -} - -QPixmap Map::renderBorder(bool ignoreCache) { - bool changed_any = false, border_resized = false; - int width_ = getBorderWidth(); - int height_ = getBorderHeight(); - if (layout->border_image.isNull()) { - layout->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); - changed_any = true; - } - if (layout->border_image.width() != width_ * 16 || layout->border_image.height() != height_ * 16) { - layout->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); - border_resized = true; - } - if (layout->border.isEmpty()) { - layout->border_pixmap = layout->border_pixmap.fromImage(layout->border_image); - return layout->border_pixmap; - } - QPainter painter(&layout->border_image); - for (int i = 0; i < layout->border.length(); i++) { - if (!ignoreCache && (!border_resized && !borderBlockChanged(i, layout->cached_border))) { - continue; - } - - changed_any = true; - Block block = layout->border.at(i); - uint16_t metatileId = block.metatileId; - QImage metatile_image = getMetatileImage(metatileId, layout->tileset_primary, layout->tileset_secondary, metatileLayerOrder, metatileLayerOpacity); - int map_y = width_ ? i / width_ : 0; - int map_x = width_ ? i % width_ : 0; - painter.drawImage(QPoint(map_x * 16, map_y * 16), metatile_image); - } - painter.end(); - if (changed_any) { - cacheBorder(); - layout->border_pixmap = layout->border_pixmap.fromImage(layout->border_image); - } - return layout->border_pixmap; -} - QPixmap Map::renderConnection(MapConnection connection, Layout *fromLayout) { int x, y, w, h; if (connection.direction == "up") { @@ -207,213 +92,14 @@ QPixmap Map::renderConnection(MapConnection connection, Layout *fromLayout) { //render(true, fromLayout, QRect(x, y, w, h)); //QImage connection_image = image.copy(x * 16, y * 16, w * 16, h * 16); - return render(true, fromLayout, QRect(x, y, w, h)).copy(x * 16, y * 16, w * 16, h * 16); + return this->layout->render(true, fromLayout, QRect(x, y, w, h)).copy(x * 16, y * 16, w * 16, h * 16); //return QPixmap::fromImage(connection_image); } -void Map::setNewDimensionsBlockdata(int newWidth, int newHeight) { - int oldWidth = getWidth(); - int oldHeight = getHeight(); - - Blockdata newBlockdata; - - for (int y = 0; y < newHeight; y++) - for (int x = 0; x < newWidth; x++) { - if (x < oldWidth && y < oldHeight) { - int index = y * oldWidth + x; - newBlockdata.append(layout->blockdata.value(index)); - } else { - newBlockdata.append(0); - } - } - - layout->blockdata = newBlockdata; -} - -void Map::setNewBorderDimensionsBlockdata(int newWidth, int newHeight) { - int oldWidth = getBorderWidth(); - int oldHeight = getBorderHeight(); - - Blockdata newBlockdata; - - for (int y = 0; y < newHeight; y++) - for (int x = 0; x < newWidth; x++) { - if (x < oldWidth && y < oldHeight) { - int index = y * oldWidth + x; - newBlockdata.append(layout->border.value(index)); - } else { - newBlockdata.append(0); - } - } - - layout->border = newBlockdata; -} - -void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) { - if (setNewBlockdata) { - setNewDimensionsBlockdata(newWidth, newHeight); - } - - int oldWidth = layout->width; - int oldHeight = layout->height; - layout->width = newWidth; - layout->height = newHeight; - - if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) { - Scripting::cb_MapResized(oldWidth, oldHeight, newWidth, newHeight); - } - - emit mapChanged(this); - emit mapDimensionsChanged(QSize(getWidth(), getHeight())); -} - -void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) { - if (setNewBlockdata) { - setNewBorderDimensionsBlockdata(newWidth, newHeight); - } - - int oldWidth = layout->border_width; - int oldHeight = layout->border_height; - layout->border_width = newWidth; - layout->border_height = newHeight; - - if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) { - Scripting::cb_BorderResized(oldWidth, oldHeight, newWidth, newHeight); - } - - emit mapChanged(this); -} - void Map::openScript(QString label) { emit openScriptRequested(label); } -bool Map::getBlock(int x, int y, Block *out) { - if (isWithinBounds(x, y)) { - int i = y * getWidth() + x; - *out = layout->blockdata.value(i); - return true; - } - return false; -} - -void Map::setBlock(int x, int y, Block block, bool enableScriptCallback) { - if (!isWithinBounds(x, y)) return; - int i = y * getWidth() + x; - if (i < layout->blockdata.size()) { - Block prevBlock = layout->blockdata.at(i); - layout->blockdata.replace(i, block); - if (enableScriptCallback) { - Scripting::cb_MetatileChanged(x, y, prevBlock, block); - } - } -} - -void Map::setBlockdata(Blockdata blockdata, bool enableScriptCallback) { - int width = getWidth(); - int size = qMin(blockdata.size(), layout->blockdata.size()); - for (int i = 0; i < size; i++) { - Block prevBlock = layout->blockdata.at(i); - Block newBlock = blockdata.at(i); - if (prevBlock != newBlock) { - layout->blockdata.replace(i, newBlock); - if (enableScriptCallback) - Scripting::cb_MetatileChanged(i % width, i / width, prevBlock, newBlock); - } - } -} - -uint16_t Map::getBorderMetatileId(int x, int y) { - int i = y * getBorderWidth() + x; - return layout->border[i].metatileId; -} - -void Map::setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback) { - int i = y * getBorderWidth() + x; - if (i < layout->border.size()) { - uint16_t prevMetatileId = layout->border[i].metatileId; - layout->border[i].metatileId = metatileId; - if (prevMetatileId != metatileId && enableScriptCallback) { - Scripting::cb_BorderMetatileChanged(x, y, prevMetatileId, metatileId); - } - } -} - -void Map::setBorderBlockData(Blockdata blockdata, bool enableScriptCallback) { - int width = getBorderWidth(); - int size = qMin(blockdata.size(), layout->border.size()); - for (int i = 0; i < size; i++) { - Block prevBlock = layout->border.at(i); - Block newBlock = blockdata.at(i); - if (prevBlock != newBlock) { - layout->border.replace(i, newBlock); - if (enableScriptCallback) - Scripting::cb_BorderMetatileChanged(i % width, i / width, prevBlock.metatileId, newBlock.metatileId); - } - } -} - -void Map::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) { - QList todo; - todo.append(QPoint(x, y)); - while (todo.length()) { - QPoint point = todo.takeAt(0); - x = point.x(); - y = point.y(); - Block block; - if (!getBlock(x, y, &block)) { - continue; - } - - uint old_coll = block.collision; - uint old_elev = block.elevation; - if (old_coll == collision && old_elev == elevation) { - continue; - } - - block.collision = collision; - block.elevation = elevation; - setBlock(x, y, block, true); - if (getBlock(x + 1, y, &block) && block.collision == old_coll && block.elevation == old_elev) { - todo.append(QPoint(x + 1, y)); - } - if (getBlock(x - 1, y, &block) && block.collision == old_coll && block.elevation == old_elev) { - todo.append(QPoint(x - 1, y)); - } - if (getBlock(x, y + 1, &block) && block.collision == old_coll && block.elevation == old_elev) { - todo.append(QPoint(x, y + 1)); - } - if (getBlock(x, y - 1, &block) && block.collision == old_coll && block.elevation == old_elev) { - todo.append(QPoint(x, y - 1)); - } - } -} - -void Map::floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) { - Block block; - if (getBlock(x, y, &block) && (block.collision != collision || block.elevation != elevation)) { - _floodFillCollisionElevation(x, y, collision, elevation); - } -} - -void Map::magicFillCollisionElevation(int initialX, int initialY, uint16_t collision, uint16_t elevation) { - Block block; - if (getBlock(initialX, initialY, &block) && (block.collision != collision || block.elevation != elevation)) { - uint old_coll = block.collision; - uint old_elev = block.elevation; - - for (int y = 0; y < getHeight(); y++) { - for (int x = 0; x < getWidth(); x++) { - if (getBlock(x, y, &block) && block.collision == old_coll && block.elevation == old_elev) { - block.collision = collision; - block.elevation = elevation; - setBlock(x, y, block, true); - } - } - } - } -} - QList Map::getAllEvents() const { QList all_events; for (const auto &event_list : events) { @@ -468,13 +154,5 @@ void Map::clean() { } bool Map::hasUnsavedChanges() { - return !editHistory.isClean() || hasUnsavedDataChanges || !isPersistedToFile; -} - -bool Map::isWithinBounds(int x, int y) { - return (x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight()); -} - -bool Map::isWithinBorderBounds(int x, int y) { - return (x >= 0 && x < this->getBorderWidth() && y >= 0 && y < this->getBorderHeight()); + return !editHistory.isClean() /* || !this->layout->editHistory.isClean() */ || hasUnsavedDataChanges || !isPersistedToFile; } diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 70364f69a..a56a982e0 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -36,6 +36,14 @@ int Layout::getBorderHeight() { return border_height; } +bool Layout::isWithinBounds(int x, int y) { + return (x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight()); +} + +bool Layout::isWithinBorderBounds(int x, int y) { + return (x >= 0 && x < this->getBorderWidth() && y >= 0 && y < this->getBorderHeight()); +} + bool Layout::getBlock(int x, int y, Block *out) { if (isWithinBounds(x, y)) { int i = y * getWidth() + x; diff --git a/src/editor.cpp b/src/editor.cpp index d83ca28a7..4b1bafc5f 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -111,7 +111,7 @@ void Editor::setEditingCollision() { collision_item->setVisible(true); } if (map_item) { - map_item->paintingMode = MapPixmapItem::PaintMode::Metatiles; + map_item->paintingMode = LayoutPixmapItem::PaintMode::Metatiles; map_item->draw(); map_item->setVisible(true); } @@ -1017,13 +1017,13 @@ void Editor::setCursorRectVisible(bool visible) { void Editor::onHoveredMapMetatileChanged(const QPoint &pos) { int x = pos.x(); int y = pos.y(); - if (!map->isWithinBounds(x, y)) + if (!layout->isWithinBounds(x, y)) return; this->updateCursorRectPos(x, y); if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { - int blockIndex = y * map->getWidth() + x; - int metatileId = map->layout->blockdata.at(blockIndex).metatileId; + int blockIndex = y * layout->getWidth() + x; + int metatileId = layout->blockdata.at(blockIndex).metatileId; this->ui->statusBar->showMessage(QString("X: %1, Y: %2, %3, Scale = %4x") .arg(x) .arg(y) @@ -1049,14 +1049,14 @@ void Editor::onHoveredMapMetatileCleared() { } void Editor::onHoveredMapMovementPermissionChanged(int x, int y) { - if (!map->isWithinBounds(x, y)) + if (!layout->isWithinBounds(x, y)) return; this->updateCursorRectPos(x, y); if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { - int blockIndex = y * map->getWidth() + x; - uint16_t collision = map->layout->blockdata.at(blockIndex).collision; - uint16_t elevation = map->layout->blockdata.at(blockIndex).elevation; + int blockIndex = y * layout->getWidth() + x; + uint16_t collision = layout->blockdata.at(blockIndex).collision; + uint16_t elevation = layout->blockdata.at(blockIndex).elevation; QString message = QString("X: %1, Y: %2, %3") .arg(x) .arg(y) @@ -1385,7 +1385,7 @@ void Editor::displayMetatileSelector() { } scene_metatiles = new QGraphicsScene; if (!metatile_selector_item) { - metatile_selector_item = new MetatileSelector(8, map); + metatile_selector_item = new MetatileSelector(8, this->layout); connect(metatile_selector_item, &MetatileSelector::hoveredMetatileSelectionChanged, this, &Editor::onHoveredMetatileSelectionChanged); connect(metatile_selector_item, &MetatileSelector::hoveredMetatileSelectionCleared, @@ -1394,7 +1394,7 @@ void Editor::displayMetatileSelector() { this, &Editor::onSelectedMetatilesChanged); metatile_selector_item->select(0); } else { - metatile_selector_item->setMap(map); + 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); @@ -1471,14 +1471,14 @@ void Editor::displayCurrentMetatilesSelection() { } scene_current_metatile_selection = new QGraphicsScene; - current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(map, this->metatile_selector_item); + current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(this->layout, this->metatile_selector_item); current_metatile_selection_item->draw(); scene_current_metatile_selection->addItem(current_metatile_selection_item); } void Editor::redrawCurrentMetatilesSelection() { if (current_metatile_selection_item) { - current_metatile_selection_item->setMap(map); + current_metatile_selection_item->setLayout(this->layout); current_metatile_selection_item->draw(); emit currentMetatilesSelectionChanged(); } @@ -1635,7 +1635,7 @@ void Editor::displayMapBorder() { int borderHeight = map->getBorderHeight(); int borderHorzDist = getBorderDrawDistance(borderWidth); int borderVertDist = getBorderDrawDistance(borderHeight); - QPixmap pixmap = map->renderBorder(); + 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) { QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); @@ -1648,7 +1648,7 @@ void Editor::displayMapBorder() { } void Editor::updateMapBorder() { - QPixmap pixmap = this->map->renderBorder(true); + QPixmap pixmap = this->layout->renderBorder(true); for (auto item : this->borderItems) { item->setPixmap(pixmap); } @@ -1925,7 +1925,7 @@ void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) { map->layout->tileset_primary_label = tilesetLabel; map->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad); - map->clearBorderCache(); + layout->clearBorderCache(); } } @@ -1935,7 +1935,7 @@ void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad) { map->layout->tileset_secondary_label = tilesetLabel; map->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad); - map->clearBorderCache(); + layout->clearBorderCache(); } } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 351c0e3e8..3d0bc6b3d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -536,7 +536,7 @@ bool MainWindow::openProject(QString dir) { editor->metatile_selector_item, ui->scrollAreaWidgetContents_Prefabs, ui->label_prefabHelp, - editor->map); + editor->layout); Scripting::cb_ProjectOpened(dir); return true; } @@ -674,7 +674,7 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { updateMapList(); Scripting::cb_MapOpened(map_name); - prefab.updatePrefabUi(editor->map); + prefab.updatePrefabUi(editor->layout); updateTilesetEditor(); return true; } @@ -1352,7 +1352,7 @@ void MainWindow::on_actionNew_Tileset_triggered() { void MainWindow::updateTilesetEditor() { if (this->tilesetEditor) { this->tilesetEditor->update( - this->editor->map, + this->editor->layout, editor->ui->comboBox_PrimaryTileset->currentText(), editor->ui->comboBox_SecondaryTileset->currentText() ); @@ -1532,7 +1532,7 @@ void MainWindow::copy() { case 0: { // copy the map image - QPixmap pixmap = editor->map ? editor->map->render(true) : QPixmap(); + QPixmap pixmap = editor->layout ? editor->layout->render(true) : QPixmap(); setClipboardData(pixmap.toImage()); logInfo("Copied current map image to clipboard"); break; @@ -1755,8 +1755,8 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index) // User hasn't set up prefabs and hasn't been prompted before. // Ask if they'd like to import the default prefabs file. if (prefab.tryImportDefaultPrefabs(this, projectConfig.getBaseGameVersion())) - prefab.updatePrefabUi(this->editor->map); - } + prefab.updatePrefabUi(this->editor->layout); + } } editor->setCursorRectVisible(false); } @@ -2442,8 +2442,10 @@ void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryT } else { this->editor->project->getTileset(secondaryTilesetLabel, true); } - if (updated) + if (updated) { + this->editor->layout->clearBorderCache(); redrawMapScene(); + } } void MainWindow::onWildMonDataChanged() { @@ -2592,7 +2594,7 @@ void MainWindow::on_comboBox_PrimaryTileset_currentTextChanged(const QString &ti redrawMapScene(); on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value()); updateTilesetEditor(); - prefab.updatePrefabUi(editor->map); + prefab.updatePrefabUi(editor->layout); markMapEdited(); } } @@ -2604,7 +2606,7 @@ void MainWindow::on_comboBox_SecondaryTileset_currentTextChanged(const QString & redrawMapScene(); on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value()); updateTilesetEditor(); - prefab.updatePrefabUi(editor->map); + prefab.updatePrefabUi(editor->layout); markMapEdited(); } } @@ -2725,7 +2727,7 @@ void MainWindow::on_actionTileset_Editor_triggered() } void MainWindow::initTilesetEditor() { - this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map, this); + this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->layout, this); connect(this->tilesetEditor, &TilesetEditor::tilesetsSaved, this, &MainWindow::onTilesetsSaved); } @@ -2889,7 +2891,7 @@ void MainWindow::on_actionRegion_Map_Editor_triggered() { } void MainWindow::on_pushButton_CreatePrefab_clicked() { - PrefabCreationDialog dialog(this, this->editor->metatile_selector_item, this->editor->map); + PrefabCreationDialog dialog(this, this->editor->metatile_selector_item, this->editor->layout); dialog.setWindowTitle("Create Prefab"); dialog.setWindowModality(Qt::NonModal); if (dialog.exec() == QDialog::Accepted) { diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index 21f38a51f..155d34926 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -42,13 +42,13 @@ void MainWindow::tryRedrawMapArea(bool forceRedraw) { void MainWindow::tryCommitMapChanges(bool commitChanges) { if (commitChanges) { - Map *map = this->editor->map; - if (map) { - map->editHistory.push(new ScriptEditMap(map, - map->layout->lastCommitBlocks.mapDimensions, QSize(map->getWidth(), map->getHeight()), - map->layout->lastCommitBlocks.blocks, map->layout->blockdata, - map->layout->lastCommitBlocks.borderDimensions, QSize(map->getBorderWidth(), map->getBorderHeight()), - map->layout->lastCommitBlocks.border, map->layout->border + Layout *layout = this->editor->layout; + if (layout) { + layout->editHistory.push(new ScriptEditMap(layout, + layout->lastCommitBlocks.mapDimensions, QSize(layout->getWidth(), layout->getHeight()), + layout->lastCommitBlocks.blocks, layout->blockdata, + layout->lastCommitBlocks.borderDimensions, QSize(layout->getBorderWidth(), layout->getBorderHeight()), + layout->lastCommitBlocks.border, layout->border )); } } @@ -59,27 +59,27 @@ void MainWindow::tryCommitMapChanges(bool commitChanges) { //===================== QJSValue MainWindow::getBlock(int x, int y) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return QJSValue(); Block block; - if (!this->editor->map->getBlock(x, y, &block)) { + if (!this->editor->layout->getBlock(x, y, &block)) { return Scripting::fromBlock(Block()); } return Scripting::fromBlock(block); } void MainWindow::setBlock(int x, int y, int metatileId, int collision, int elevation, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; - this->editor->map->setBlock(x, y, Block(metatileId, collision, elevation)); + this->editor->layout->setBlock(x, y, Block(metatileId, collision, elevation)); this->tryCommitMapChanges(commitChanges); this->tryRedrawMapArea(forceRedraw); } void MainWindow::setBlock(int x, int y, int rawValue, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; - this->editor->map->setBlock(x, y, Block(static_cast(rawValue))); + this->editor->layout->setBlock(x, y, Block(static_cast(rawValue))); this->tryCommitMapChanges(commitChanges); this->tryRedrawMapArea(forceRedraw); } @@ -93,73 +93,73 @@ void MainWindow::setBlocksFromSelection(int x, int y, bool forceRedraw, bool com } int MainWindow::getMetatileId(int x, int y) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return 0; Block block; - if (!this->editor->map->getBlock(x, y, &block)) { + if (!this->editor->layout->getBlock(x, y, &block)) { return 0; } return block.metatileId; } void MainWindow::setMetatileId(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; Block block; - if (!this->editor->map->getBlock(x, y, &block)) { + if (!this->editor->layout->getBlock(x, y, &block)) { return; } - this->editor->map->setBlock(x, y, Block(metatileId, block.collision, block.elevation)); + this->editor->layout->setBlock(x, y, Block(metatileId, block.collision, block.elevation)); this->tryCommitMapChanges(commitChanges); this->tryRedrawMapArea(forceRedraw); } int MainWindow::getCollision(int x, int y) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return 0; Block block; - if (!this->editor->map->getBlock(x, y, &block)) { + if (!this->editor->layout->getBlock(x, y, &block)) { return 0; } return block.collision; } void MainWindow::setCollision(int x, int y, int collision, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; Block block; - if (!this->editor->map->getBlock(x, y, &block)) { + if (!this->editor->layout->getBlock(x, y, &block)) { return; } - this->editor->map->setBlock(x, y, Block(block.metatileId, collision, block.elevation)); + this->editor->layout->setBlock(x, y, Block(block.metatileId, collision, block.elevation)); this->tryCommitMapChanges(commitChanges); this->tryRedrawMapArea(forceRedraw); } int MainWindow::getElevation(int x, int y) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return 0; Block block; - if (!this->editor->map->getBlock(x, y, &block)) { + if (!this->editor->layout->getBlock(x, y, &block)) { return 0; } return block.elevation; } void MainWindow::setElevation(int x, int y, int elevation, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; Block block; - if (!this->editor->map->getBlock(x, y, &block)) { + if (!this->editor->layout->getBlock(x, y, &block)) { return; } - this->editor->map->setBlock(x, y, Block(block.metatileId, block.collision, elevation)); + this->editor->layout->setBlock(x, y, Block(block.metatileId, block.collision, elevation)); this->tryCommitMapChanges(commitChanges); this->tryRedrawMapArea(forceRedraw); } void MainWindow::bucketFill(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; this->editor->map_item->floodFill(x, y, metatileId, true); this->tryCommitMapChanges(commitChanges); @@ -167,7 +167,7 @@ void MainWindow::bucketFill(int x, int y, int metatileId, bool forceRedraw, bool } void MainWindow::bucketFillFromSelection(int x, int y, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; this->editor->map_item->floodFill(x, y, true); this->tryCommitMapChanges(commitChanges); @@ -175,7 +175,7 @@ void MainWindow::bucketFillFromSelection(int x, int y, bool forceRedraw, bool co } void MainWindow::magicFill(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; this->editor->map_item->magicFill(x, y, metatileId, true); this->tryCommitMapChanges(commitChanges); @@ -183,7 +183,7 @@ void MainWindow::magicFill(int x, int y, int metatileId, bool forceRedraw, bool } void MainWindow::magicFillFromSelection(int x, int y, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; this->editor->map_item->magicFill(x, y, true); this->tryCommitMapChanges(commitChanges); @@ -191,7 +191,7 @@ void MainWindow::magicFillFromSelection(int x, int y, bool forceRedraw, bool com } void MainWindow::shift(int xDelta, int yDelta, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; this->editor->map_item->shift(xDelta, yDelta, true); this->tryCommitMapChanges(commitChanges); @@ -207,49 +207,49 @@ void MainWindow::commit() { } QJSValue MainWindow::getDimensions() { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return QJSValue(); - return Scripting::dimensions(this->editor->map->getWidth(), this->editor->map->getHeight()); + return Scripting::dimensions(this->editor->layout->getWidth(), this->editor->layout->getHeight()); } int MainWindow::getWidth() { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return 0; - return this->editor->map->getWidth(); + return this->editor->layout->getWidth(); } int MainWindow::getHeight() { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return 0; - return this->editor->map->getHeight(); + return this->editor->layout->getHeight(); } void MainWindow::setDimensions(int width, int height) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; if (!Project::mapDimensionsValid(width, height)) return; - this->editor->map->setDimensions(width, height); + this->editor->layout->setDimensions(width, height); this->tryCommitMapChanges(true); this->onMapNeedsRedrawing(); } void MainWindow::setWidth(int width) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; - if (!Project::mapDimensionsValid(width, this->editor->map->getHeight())) + if (!Project::mapDimensionsValid(width, this->editor->layout->getHeight())) return; - this->editor->map->setDimensions(width, this->editor->map->getHeight()); + this->editor->layout->setDimensions(width, this->editor->layout->getHeight()); this->tryCommitMapChanges(true); this->onMapNeedsRedrawing(); } void MainWindow::setHeight(int height) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; - if (!Project::mapDimensionsValid(this->editor->map->getWidth(), height)) + if (!Project::mapDimensionsValid(this->editor->layout->getWidth(), height)) return; - this->editor->map->setDimensions(this->editor->map->getWidth(), height); + this->editor->layout->setDimensions(this->editor->layout->getWidth(), height); this->tryCommitMapChanges(true); this->onMapNeedsRedrawing(); } @@ -259,67 +259,67 @@ void MainWindow::setHeight(int height) { //===================== int MainWindow::getBorderMetatileId(int x, int y) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return 0; - if (!this->editor->map->isWithinBorderBounds(x, y)) + if (!this->editor->layout->isWithinBorderBounds(x, y)) return 0; - return this->editor->map->getBorderMetatileId(x, y); + return this->editor->layout->getBorderMetatileId(x, y); } void MainWindow::setBorderMetatileId(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return; - if (!this->editor->map->isWithinBorderBounds(x, y)) + if (!this->editor->layout->isWithinBorderBounds(x, y)) return; - this->editor->map->setBorderMetatileId(x, y, metatileId); + this->editor->layout->setBorderMetatileId(x, y, metatileId); this->tryCommitMapChanges(commitChanges); this->tryRedrawMapArea(forceRedraw); } QJSValue MainWindow::getBorderDimensions() { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return QJSValue(); - return Scripting::dimensions(this->editor->map->getBorderWidth(), this->editor->map->getBorderHeight()); + return Scripting::dimensions(this->editor->layout->getBorderWidth(), this->editor->layout->getBorderHeight()); } int MainWindow::getBorderWidth() { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return 0; - return this->editor->map->getBorderWidth(); + return this->editor->layout->getBorderWidth(); } int MainWindow::getBorderHeight() { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->layout) return 0; - return this->editor->map->getBorderHeight(); + return this->editor->layout->getBorderHeight(); } void MainWindow::setBorderDimensions(int width, int height) { - if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize()) + if (!this->editor || !this->editor->layout || !projectConfig.getUseCustomBorderSize()) return; if (width < 1 || height < 1 || width > MAX_BORDER_WIDTH || height > MAX_BORDER_HEIGHT) return; - this->editor->map->setBorderDimensions(width, height); + this->editor->layout->setBorderDimensions(width, height); this->tryCommitMapChanges(true); this->onMapNeedsRedrawing(); } void MainWindow::setBorderWidth(int width) { - if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize()) + if (!this->editor || !this->editor->layout || !projectConfig.getUseCustomBorderSize()) return; if (width < 1 || width > MAX_BORDER_WIDTH) return; - this->editor->map->setBorderDimensions(width, this->editor->map->getBorderHeight()); + this->editor->layout->setBorderDimensions(width, this->editor->layout->getBorderHeight()); this->tryCommitMapChanges(true); this->onMapNeedsRedrawing(); } void MainWindow::setBorderHeight(int height) { - if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize()) + if (!this->editor || !this->editor->layout || !projectConfig.getUseCustomBorderSize()) return; if (height < 1 || height > MAX_BORDER_HEIGHT) return; - this->editor->map->setBorderDimensions(this->editor->map->getBorderWidth(), height); + this->editor->layout->setBorderDimensions(this->editor->layout->getBorderWidth(), height); this->tryCommitMapChanges(true); this->onMapNeedsRedrawing(); } @@ -330,7 +330,7 @@ void MainWindow::setBorderHeight(int height) { void MainWindow::refreshAfterPaletteChange(Tileset *tileset) { if (this->tilesetEditor) { - this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label); + this->tilesetEditor->updateTilesets(this->editor->layout->tileset_primary_label, this->editor->layout->tileset_secondary_label); } this->editor->metatile_selector_item->draw(); this->editor->selected_border_metatiles_item->draw(); @@ -341,7 +341,7 @@ void MainWindow::refreshAfterPaletteChange(Tileset *tileset) { } void MainWindow::setTilesetPalette(Tileset *tileset, int paletteIndex, QList> colors) { - if (!this->editor || !this->editor->map || !this->editor->map->layout) + if (!this->editor || !this->editor->map || !this->editor->layout) return; if (paletteIndex >= tileset->palettes.size()) return; @@ -357,42 +357,42 @@ void MainWindow::setTilesetPalette(Tileset *tileset, int paletteIndex, QList> colors, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return; - this->setTilesetPalette(this->editor->map->layout->tileset_primary, paletteIndex, colors); + this->setTilesetPalette(this->editor->layout->tileset_primary, paletteIndex, colors); if (forceRedraw) { - this->refreshAfterPaletteChange(this->editor->map->layout->tileset_primary); + this->refreshAfterPaletteChange(this->editor->layout->tileset_primary); } } void MainWindow::setPrimaryTilesetPalettes(QList>> palettes, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return; for (int i = 0; i < palettes.size(); i++) { - this->setTilesetPalette(this->editor->map->layout->tileset_primary, i, palettes[i]); + this->setTilesetPalette(this->editor->layout->tileset_primary, i, palettes[i]); } if (forceRedraw) { - this->refreshAfterPaletteChange(this->editor->map->layout->tileset_primary); + this->refreshAfterPaletteChange(this->editor->layout->tileset_primary); } } void MainWindow::setSecondaryTilesetPalette(int paletteIndex, QList> colors, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return; - this->setTilesetPalette(this->editor->map->layout->tileset_secondary, paletteIndex, colors); + this->setTilesetPalette(this->editor->layout->tileset_secondary, paletteIndex, colors); if (forceRedraw) { - this->refreshAfterPaletteChange(this->editor->map->layout->tileset_secondary); + this->refreshAfterPaletteChange(this->editor->layout->tileset_secondary); } } void MainWindow::setSecondaryTilesetPalettes(QList>> palettes, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return; for (int i = 0; i < palettes.size(); i++) { - this->setTilesetPalette(this->editor->map->layout->tileset_secondary, i, palettes[i]); + this->setTilesetPalette(this->editor->layout->tileset_secondary, i, palettes[i]); } if (forceRedraw) { - this->refreshAfterPaletteChange(this->editor->map->layout->tileset_secondary); + this->refreshAfterPaletteChange(this->editor->layout->tileset_secondary); } } @@ -420,27 +420,27 @@ QJSValue MainWindow::getTilesetPalettes(const QList> &palettes) { } QJSValue MainWindow::getPrimaryTilesetPalette(int paletteIndex) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return QJSValue(); - return this->getTilesetPalette(this->editor->map->layout->tileset_primary->palettes, paletteIndex); + return this->getTilesetPalette(this->editor->layout->tileset_primary->palettes, paletteIndex); } QJSValue MainWindow::getPrimaryTilesetPalettes() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return QJSValue(); - return this->getTilesetPalettes(this->editor->map->layout->tileset_primary->palettes); + return this->getTilesetPalettes(this->editor->layout->tileset_primary->palettes); } QJSValue MainWindow::getSecondaryTilesetPalette(int paletteIndex) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return QJSValue(); - return this->getTilesetPalette(this->editor->map->layout->tileset_secondary->palettes, paletteIndex); + return this->getTilesetPalette(this->editor->layout->tileset_secondary->palettes, paletteIndex); } QJSValue MainWindow::getSecondaryTilesetPalettes() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return QJSValue(); - return this->getTilesetPalettes(this->editor->map->layout->tileset_secondary->palettes); + return this->getTilesetPalettes(this->editor->layout->tileset_secondary->palettes); } void MainWindow::refreshAfterPalettePreviewChange() { @@ -452,7 +452,7 @@ void MainWindow::refreshAfterPalettePreviewChange() { } void MainWindow::setTilesetPalettePreview(Tileset *tileset, int paletteIndex, QList> colors) { - if (!this->editor || !this->editor->map || !this->editor->map->layout) + if (!this->editor || !this->editor->map || !this->editor->layout) return; if (paletteIndex >= tileset->palettePreviews.size()) return; @@ -467,19 +467,19 @@ void MainWindow::setTilesetPalettePreview(Tileset *tileset, int paletteIndex, QL } void MainWindow::setPrimaryTilesetPalettePreview(int paletteIndex, QList> colors, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return; - this->setTilesetPalettePreview(this->editor->map->layout->tileset_primary, paletteIndex, colors); + this->setTilesetPalettePreview(this->editor->layout->tileset_primary, paletteIndex, colors); if (forceRedraw) { this->refreshAfterPalettePreviewChange(); } } void MainWindow::setPrimaryTilesetPalettesPreview(QList>> palettes, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return; for (int i = 0; i < palettes.size(); i++) { - this->setTilesetPalettePreview(this->editor->map->layout->tileset_primary, i, palettes[i]); + this->setTilesetPalettePreview(this->editor->layout->tileset_primary, i, palettes[i]); } if (forceRedraw) { this->refreshAfterPalettePreviewChange(); @@ -487,19 +487,19 @@ void MainWindow::setPrimaryTilesetPalettesPreview(QList>> palet } void MainWindow::setSecondaryTilesetPalettePreview(int paletteIndex, QList> colors, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return; - this->setTilesetPalettePreview(this->editor->map->layout->tileset_secondary, paletteIndex, colors); + this->setTilesetPalettePreview(this->editor->layout->tileset_secondary, paletteIndex, colors); if (forceRedraw) { this->refreshAfterPalettePreviewChange(); } } void MainWindow::setSecondaryTilesetPalettesPreview(QList>> palettes, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return; for (int i = 0; i < palettes.size(); i++) { - this->setTilesetPalettePreview(this->editor->map->layout->tileset_secondary, i, palettes[i]); + this->setTilesetPalettePreview(this->editor->layout->tileset_secondary, i, palettes[i]); } if (forceRedraw) { this->refreshAfterPalettePreviewChange(); @@ -507,63 +507,63 @@ void MainWindow::setSecondaryTilesetPalettesPreview(QList>> pal } QJSValue MainWindow::getPrimaryTilesetPalettePreview(int paletteIndex) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return QJSValue(); - return this->getTilesetPalette(this->editor->map->layout->tileset_primary->palettePreviews, paletteIndex); + return this->getTilesetPalette(this->editor->layout->tileset_primary->palettePreviews, paletteIndex); } QJSValue MainWindow::getPrimaryTilesetPalettesPreview() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return QJSValue(); - return this->getTilesetPalettes(this->editor->map->layout->tileset_primary->palettePreviews); + return this->getTilesetPalettes(this->editor->layout->tileset_primary->palettePreviews); } QJSValue MainWindow::getSecondaryTilesetPalettePreview(int paletteIndex) { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return QJSValue(); - return this->getTilesetPalette(this->editor->map->layout->tileset_secondary->palettePreviews, paletteIndex); + return this->getTilesetPalette(this->editor->layout->tileset_secondary->palettePreviews, paletteIndex); } QJSValue MainWindow::getSecondaryTilesetPalettesPreview() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return QJSValue(); - return this->getTilesetPalettes(this->editor->map->layout->tileset_secondary->palettePreviews); + return this->getTilesetPalettes(this->editor->layout->tileset_secondary->palettePreviews); } int MainWindow::getNumPrimaryTilesetMetatiles() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return 0; - return this->editor->map->layout->tileset_primary->metatiles.length(); + return this->editor->layout->tileset_primary->metatiles.length(); } int MainWindow::getNumSecondaryTilesetMetatiles() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return 0; - return this->editor->map->layout->tileset_secondary->metatiles.length(); + return this->editor->layout->tileset_secondary->metatiles.length(); } int MainWindow::getNumPrimaryTilesetTiles() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return 0; - return this->editor->map->layout->tileset_primary->tiles.length(); + return this->editor->layout->tileset_primary->tiles.length(); } int MainWindow::getNumSecondaryTilesetTiles() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return 0; - return this->editor->map->layout->tileset_secondary->tiles.length(); + return this->editor->layout->tileset_secondary->tiles.length(); } QString MainWindow::getPrimaryTileset() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) return QString(); - return this->editor->map->layout->tileset_primary->name; + return this->editor->layout->tileset_primary->name; } QString MainWindow::getSecondaryTileset() { - if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) return QString(); - return this->editor->map->layout->tileset_secondary->name; + return this->editor->layout->tileset_secondary->name; } void MainWindow::setPrimaryTileset(QString tileset) { @@ -575,13 +575,13 @@ void MainWindow::setSecondaryTileset(QString tileset) { } void MainWindow::saveMetatilesByMetatileId(int metatileId) { - Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); if (this->editor->project && tileset) this->editor->project->saveTilesetMetatiles(tileset); } void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) { - Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); if (this->editor->project && tileset) this->editor->project->saveTilesetMetatileAttributes(tileset); @@ -591,9 +591,9 @@ void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) { } Metatile * MainWindow::getMetatile(int metatileId) { - if (!this->editor || !this->editor->map || !this->editor->map->layout) + if (!this->editor || !this->editor->map || !this->editor->layout) return nullptr; - return Tileset::getMetatile(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + return Tileset::getMetatile(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); } QString MainWindow::getMetatileLabel(int metatileId) { @@ -603,7 +603,7 @@ QString MainWindow::getMetatileLabel(int metatileId) { } void MainWindow::setMetatileLabel(int metatileId, QString label) { - if (!this->editor || !this->editor->map || !this->editor->map->layout) + if (!this->editor || !this->editor->map || !this->editor->layout) return; // If the Tileset Editor is opened on this metatile we need to update the text box @@ -612,13 +612,13 @@ void MainWindow::setMetatileLabel(int metatileId, QString label) { return; } - if (!Tileset::setMetatileLabel(metatileId, label, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary)) { + if (!Tileset::setMetatileLabel(metatileId, label, this->editor->layout->tileset_primary, this->editor->map->layout->tileset_secondary)) { logError("Failed to set metatile label. Must be a valid metatile id and a label containing only letters, numbers, and underscores."); return; } if (this->editor->project) - this->editor->project->saveTilesetMetatileLabels(this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + this->editor->project->saveTilesetMetatileLabels(this->editor->layout->tileset_primary, this->editor->map->layout->tileset_secondary); } int MainWindow::getMetatileLayerType(int metatileId) { @@ -769,9 +769,9 @@ void MainWindow::setMetatileTile(int metatileId, int tileIndex, QJSValue tileObj } QJSValue MainWindow::getTilePixels(int tileId) { - if (tileId < 0 || !this->editor || !this->editor->project || !this->editor->map || !this->editor->map->layout) + if (tileId < 0 || !this->editor || !this->editor->project || !this->editor->map || !this->editor->layout) return QJSValue(); - QImage tileImage = getTileImage(tileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + QImage tileImage = getTileImage(tileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); if (tileImage.isNull() || tileImage.sizeInBytes() < 64) return QJSValue(); const uchar * pixels = tileImage.constBits(); diff --git a/src/scriptapi/apioverlay.cpp b/src/scriptapi/apioverlay.cpp index bee473ff4..7e634fab5 100644 --- a/src/scriptapi/apioverlay.cpp +++ b/src/scriptapi/apioverlay.cpp @@ -254,23 +254,23 @@ void MapView::addImage(int x, int y, QString filepath, int layer, bool useCache) } void MapView::createImage(int x, int y, QString filepath, int width, int height, int xOffset, int yOffset, qreal hScale, qreal vScale, int paletteId, bool setTransparency, int layer, bool useCache) { - if (!this->editor || !this->editor->map || !this->editor->map->layout - || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout + || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) return; QList palette; if (paletteId != -1) - palette = Tileset::getPalette(paletteId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + palette = Tileset::getPalette(paletteId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); if (this->getOverlay(layer)->addImage(x, y, filepath, useCache, width, height, xOffset, yOffset, hScale, vScale, palette, setTransparency)) this->scene()->update(); } void MapView::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency, int layer) { - if (!this->editor || !this->editor->map || !this->editor->map->layout - || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout + || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) return; QImage image = getPalettedTileImage(tileId, - this->editor->map->layout->tileset_primary, - this->editor->map->layout->tileset_secondary, + this->editor->layout->tileset_primary, + this->editor->layout->tileset_secondary, paletteId) .mirrored(xflip, yflip); if (setTransparency) @@ -285,14 +285,14 @@ void MapView::addTileImage(int x, int y, QJSValue tileObj, bool setTransparency, } void MapView::addMetatileImage(int x, int y, int metatileId, bool setTransparency, int layer) { - if (!this->editor || !this->editor->map || !this->editor->map->layout - || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) + if (!this->editor || !this->editor->map || !this->editor->layout + || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) return; QImage image = getMetatileImage(static_cast(metatileId), - this->editor->map->layout->tileset_primary, - this->editor->map->layout->tileset_secondary, - this->editor->map->metatileLayerOrder, - this->editor->map->metatileLayerOpacity); + this->editor->layout->tileset_primary, + this->editor->layout->tileset_secondary, + this->editor->layout->metatileLayerOrder, + this->editor->layout->metatileLayerOpacity); if (setTransparency) image.setColor(0, qRgba(0, 0, 0, 0)); if (this->getOverlay(layer)->addImage(x, y, image)) diff --git a/src/scriptapi/apiutility.cpp b/src/scriptapi/apiutility.cpp index 559e46afe..712a81716 100644 --- a/src/scriptapi/apiutility.cpp +++ b/src/scriptapi/apiutility.cpp @@ -188,13 +188,13 @@ QList ScriptUtility::getCustomScripts() { } QList ScriptUtility::getMetatileLayerOrder() { - if (!window || !window->editor || !window->editor->map) + if (!window || !window->editor || !window->editor->layout) return QList(); - return window->editor->map->metatileLayerOrder; + return window->editor->layout->metatileLayerOrder; } void ScriptUtility::setMetatileLayerOrder(QList order) { - if (!window || !window->editor || !window->editor->map) + if (!window || !window->editor || !window->editor->layout) return; const int numLayers = 3; @@ -213,20 +213,20 @@ void ScriptUtility::setMetatileLayerOrder(QList order) { } if (invalid) return; - window->editor->map->metatileLayerOrder = order; + window->editor->layout->metatileLayerOrder = order; window->refreshAfterPalettePreviewChange(); } QList ScriptUtility::getMetatileLayerOpacity() { - if (!window || !window->editor || !window->editor->map) + if (!window || !window->editor || !window->editor->layout) return QList(); - return window->editor->map->metatileLayerOpacity; + return window->editor->layout->metatileLayerOpacity; } void ScriptUtility::setMetatileLayerOpacity(QList order) { - if (!window || !window->editor || !window->editor->map) + if (!window || !window->editor || !window->editor->layout) return; - window->editor->map->metatileLayerOpacity = order; + window->editor->layout->metatileLayerOpacity = order; window->refreshAfterPalettePreviewChange(); } diff --git a/src/ui/currentselectedmetatilespixmapitem.cpp b/src/ui/currentselectedmetatilespixmapitem.cpp index 0967e5588..e8b16f49a 100644 --- a/src/ui/currentselectedmetatilespixmapitem.cpp +++ b/src/ui/currentselectedmetatilespixmapitem.cpp @@ -2,7 +2,7 @@ #include "imageproviders.h" #include -QPixmap drawMetatileSelection(MetatileSelection selection, Map *map) { +QPixmap drawMetatileSelection(MetatileSelection selection, Layout *layout) { int width = selection.dimensions.x() * 16; int height = selection.dimensions.y() * 16; QImage image(width, height, QImage::Format_RGBA8888); @@ -19,10 +19,10 @@ QPixmap drawMetatileSelection(MetatileSelection selection, Map *map) { if (item.enabled) { QImage metatile_image = getMetatileImage( item.metatileId, - map->layout->tileset_primary, - map->layout->tileset_secondary, - map->metatileLayerOrder, - map->metatileLayerOpacity); + layout->tileset_primary, + layout->tileset_secondary, + layout->metatileLayerOrder, + layout->metatileLayerOpacity); painter.drawImage(metatile_origin, metatile_image); } } @@ -34,5 +34,5 @@ QPixmap drawMetatileSelection(MetatileSelection selection, Map *map) { void CurrentSelectedMetatilesPixmapItem::draw() { MetatileSelection selection = metatileSelector->getMetatileSelection(); - setPixmap(drawMetatileSelection(selection, this->map)); + setPixmap(drawMetatileSelection(selection, this->layout)); } diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index 099f2288a..e81208b89 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -90,6 +90,7 @@ void MapImageExporter::saveImage() { break; } case ImageExporterMode::Timelapse: + // !TODO: also need layout editHistory! QProgressDialog progress("Building map timelapse...", "Cancel", 0, 1, this); progress.setAutoClose(true); progress.setWindowModality(Qt::WindowModal); @@ -358,14 +359,19 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { QPixmap pixmap; // draw background layer / base image - map->render(true); - pixmap = map->pixmap; + Layout *layout = map->layout; + if (!layout) { + return QPixmap(); + } + + layout->render(true); + pixmap = layout->pixmap; if (showCollision) { QPainter collisionPainter(&pixmap); - map->renderCollision(true); + layout->renderCollision(true); collisionPainter.setOpacity(editor->collisionOpacity); - collisionPainter.drawPixmap(0, 0, map->collision_pixmap); + collisionPainter.drawPixmap(0, 0, layout->collision_pixmap); collisionPainter.end(); } @@ -375,16 +381,16 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { bool forceDrawBorder = showUpConnections || showDownConnections || showLeftConnections || showRightConnections; if (!ignoreBorder && (showBorder || forceDrawBorder)) { int borderDistance = this->mode ? STITCH_MODE_BORDER_DISTANCE : BORDER_DISTANCE; - map->renderBorder(); - int borderHorzDist = editor->getBorderDrawDistance(map->getBorderWidth()); - int borderVertDist = editor->getBorderDrawDistance(map->getBorderHeight()); + layout->renderBorder(); + int borderHorzDist = editor->getBorderDrawDistance(layout->getBorderWidth()); + int borderVertDist = editor->getBorderDrawDistance(layout->getBorderHeight()); borderWidth = borderDistance * 16; borderHeight = borderDistance * 16; - QPixmap newPixmap = QPixmap(map->pixmap.width() + borderWidth * 2, map->pixmap.height() + borderHeight * 2); + QPixmap newPixmap = QPixmap(layout->pixmap.width() + borderWidth * 2, layout->pixmap.height() + borderHeight * 2); QPainter borderPainter(&newPixmap); - for (int y = borderDistance - borderVertDist; y < map->getHeight() + borderVertDist * 2; y += map->getBorderHeight()) { - for (int x = borderDistance - borderHorzDist; x < map->getWidth() + borderHorzDist * 2; x += map->getBorderWidth()) { - borderPainter.drawPixmap(x * 16, y * 16, map->layout->border_pixmap); + for (int y = borderDistance - borderVertDist; y < layout->getHeight() + borderVertDist * 2; y += layout->getBorderHeight()) { + for (int x = borderDistance - borderHorzDist; x < layout->getWidth() + borderHorzDist * 2; x += layout->getBorderWidth()) { + borderPainter.drawPixmap(x * 16, y * 16, layout->border_pixmap); } } borderPainter.drawImage(borderWidth, borderHeight, pixmap.toImage()); diff --git a/src/ui/metatileselector.cpp b/src/ui/metatileselector.cpp index 3ce9cf552..7fb9c34b3 100644 --- a/src/ui/metatileselector.cpp +++ b/src/ui/metatileselector.cpp @@ -26,7 +26,7 @@ void MetatileSelector::draw() { if (i >= primaryLength) { tile += Project::getNumMetatilesPrimary() - primaryLength; } - QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset, map->metatileLayerOrder, map->metatileLayerOpacity); + QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset, layout->metatileLayerOrder, layout->metatileLayerOpacity); int map_y = i / this->numMetatilesWide; int map_x = i % this->numMetatilesWide; QPoint metatile_origin = QPoint(map_x * 16, map_y * 16); @@ -209,6 +209,6 @@ QPoint MetatileSelector::getMetatileIdCoordsOnWidget(uint16_t metatileId) { return pos; } -void MetatileSelector::setMap(Map *map) { - this->map = map; +void MetatileSelector::setLayout(Layout *layout) { + this->layout = layout; } diff --git a/src/ui/prefab.cpp b/src/ui/prefab.cpp index 9ad154f25..67fa45acd 100644 --- a/src/ui/prefab.cpp +++ b/src/ui/prefab.cpp @@ -160,32 +160,32 @@ QList Prefab::getPrefabsForTilesets(QString primaryTileset, QString return filteredPrefabs; } -void Prefab::initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map) { +void Prefab::initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Layout *layout) { this->selector = selector; this->prefabWidget = prefabWidget; this->emptyPrefabLabel = emptyPrefabLabel; this->loadPrefabs(); - this->updatePrefabUi(map); + this->updatePrefabUi(layout); } // This function recreates the UI state for the prefab tab. // We completely delete all the prefab widgets, and recreate new widgets // from the relevant list of prefab items. // This is not very efficient, but it gets the job done. -void Prefab::updatePrefabUi(Map *map) { +void Prefab::updatePrefabUi(Layout *layout) { if (!this->selector) return; // Cleanup the PrefabFrame to have a clean slate. - auto layout = this->prefabWidget->layout(); - while (layout && layout->count() > 1) { - auto child = layout->takeAt(1); + auto uiLayout = this->prefabWidget->layout(); + while (uiLayout && uiLayout->count() > 1) { + auto child = uiLayout->takeAt(1); if (child->widget()) { delete child->widget(); } delete child; } - QList prefabs = this->getPrefabsForTilesets(map->layout->tileset_primary_label, map->layout->tileset_secondary_label); + QList prefabs = this->getPrefabsForTilesets(layout->tileset_primary_label, layout->tileset_secondary_label); if (prefabs.isEmpty()) { emptyPrefabLabel->setVisible(true); return; @@ -204,7 +204,7 @@ void Prefab::updatePrefabUi(Map *map) { frame->ui->label_Name->setText(item.name); auto scene = new QGraphicsScene; - scene->addPixmap(drawMetatileSelection(item.selection, map)); + scene->addPixmap(drawMetatileSelection(item.selection, layout)); scene->setSceneRect(scene->itemsBoundingRect()); frame->ui->graphicsView_Prefab->setScene(scene); frame->ui->graphicsView_Prefab->setFixedSize(scene->itemsBoundingRect().width() + 2, @@ -218,7 +218,7 @@ void Prefab::updatePrefabUi(Map *map) { }); // Clicking the delete button removes it from the list of known prefabs and updates the UI. - QObject::connect(frame->ui->pushButton_DeleteItem, &QPushButton::clicked, [this, item, map](){ + QObject::connect(frame->ui->pushButton_DeleteItem, &QPushButton::clicked, [this, item, layout](){ for (int i = 0; i < this->items.size(); i++) { if (this->items[i].id == item.id) { QMessageBox msgBox; @@ -236,7 +236,7 @@ void Prefab::updatePrefabUi(Map *map) { if (msgBox.clickedButton() == deleteButton) { this->items.removeAt(i); this->savePrefabs(); - this->updatePrefabUi(map); + this->updatePrefabUi(layout); } break; } @@ -248,7 +248,7 @@ void Prefab::updatePrefabUi(Map *map) { prefabWidget->layout()->addItem(verticalSpacer); } -void Prefab::addPrefab(MetatileSelection selection, Map *map, QString name) { +void Prefab::addPrefab(MetatileSelection selection, Layout *layout, QString name) { // First, determine which tilesets are actually used in this new prefab, // based on the metatile ids. bool usesPrimaryTileset = false; @@ -266,12 +266,12 @@ void Prefab::addPrefab(MetatileSelection selection, Map *map, QString name) { this->items.append(PrefabItem{ QUuid::createUuid(), name, - usesPrimaryTileset ? map->layout->tileset_primary_label : "", - usesSecondaryTileset ? map->layout->tileset_secondary_label: "", + usesPrimaryTileset ? layout->tileset_primary_label : "", + usesSecondaryTileset ? layout->tileset_secondary_label: "", selection }); this->savePrefabs(); - this->updatePrefabUi(map); + this->updatePrefabUi(layout); } bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath) { diff --git a/src/ui/prefabcreationdialog.cpp b/src/ui/prefabcreationdialog.cpp index 976a53a15..a7b3029c2 100644 --- a/src/ui/prefabcreationdialog.cpp +++ b/src/ui/prefabcreationdialog.cpp @@ -6,16 +6,16 @@ #include -PrefabCreationDialog::PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Map *map) : +PrefabCreationDialog::PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Layout *layout) : QDialog(parent), ui(new Ui::PrefabCreationDialog) { ui->setupUi(this); - this->map = map; + this->layout = layout; this->selection = metatileSelector->getMetatileSelection(); QGraphicsScene *scene = new QGraphicsScene; - QGraphicsPixmapItem *pixmapItem = scene->addPixmap(drawMetatileSelection(this->selection, map)); + QGraphicsPixmapItem *pixmapItem = scene->addPixmap(drawMetatileSelection(this->selection, layout)); scene->setSceneRect(scene->itemsBoundingRect()); this->ui->graphicsView_Prefab->setScene(scene); this->ui->graphicsView_Prefab->setFixedSize(scene->itemsBoundingRect().width() + 2, @@ -35,7 +35,7 @@ PrefabCreationDialog::PrefabCreationDialog(QWidget *parent, MetatileSelector *me if (this->selection.hasCollision) { this->selection.collisionItems[index].enabled = toggledState; } - pixmapItem->setPixmap(drawMetatileSelection(this->selection, map)); + pixmapItem->setPixmap(drawMetatileSelection(this->selection, layout)); }); } @@ -45,5 +45,5 @@ PrefabCreationDialog::~PrefabCreationDialog() } void PrefabCreationDialog::savePrefab() { - prefab.addPrefab(this->selection, this->map, this->ui->lineEdit_PrefabName->text()); + prefab.addPrefab(this->selection, this->layout, this->ui->lineEdit_PrefabName->text()); } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index fe6b6736e..cf9604bc4 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -13,14 +13,14 @@ #include #include -TilesetEditor::TilesetEditor(Project *project, Map *map, QWidget *parent) : +TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent) : QMainWindow(parent), ui(new Ui::TilesetEditor), project(project), - map(map), + layout(layout), hasUnsavedChanges(false) { - this->setTilesets(this->map->layout->tileset_primary_label, this->map->layout->tileset_secondary_label); + this->setTilesets(this->layout->tileset_primary_label, this->layout->tileset_secondary_label); this->initUi(); } @@ -42,14 +42,14 @@ TilesetEditor::~TilesetEditor() delete copiedMetatile; } -void TilesetEditor::update(Map *map, QString primaryTilesetLabel, QString secondaryTilesetLabel) { - this->updateMap(map); +void TilesetEditor::update(Layout *layout, QString primaryTilesetLabel, QString secondaryTilesetLabel) { + this->updateLayout(layout); this->updateTilesets(primaryTilesetLabel, secondaryTilesetLabel); } -void TilesetEditor::updateMap(Map *map) { - this->map = map; - this->metatileSelector->map = map; +void TilesetEditor::updateLayout(Layout *layout) { + this->layout = layout; + this->metatileSelector->layout = layout; } void TilesetEditor::updateTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) { @@ -178,7 +178,7 @@ void TilesetEditor::setMetatileLabelValidator() { void TilesetEditor::initMetatileSelector() { - this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->map); + this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->layout); connect(this->metatileSelector, &TilesetEditorMetatileSelector::hoveredMetatileChanged, this, &TilesetEditor::onHoveredMetatileChanged); connect(this->metatileSelector, &TilesetEditorMetatileSelector::hoveredMetatileCleared, diff --git a/src/ui/tileseteditormetatileselector.cpp b/src/ui/tileseteditormetatileselector.cpp index e89e94da8..78bd5a39b 100644 --- a/src/ui/tileseteditormetatileselector.cpp +++ b/src/ui/tileseteditormetatileselector.cpp @@ -3,11 +3,11 @@ #include "project.h" #include -TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Map *map) +TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout) : SelectablePixmapItem(32, 32, 1, 1) { this->setTilesets(primaryTileset, secondaryTileset, false); this->numMetatilesWide = 8; - this->map = map; + this->layout = layout; setAcceptHoverEvents(true); this->usedMetatiles.resize(Project::getNumMetatilesTotal()); } @@ -45,8 +45,8 @@ QImage TilesetEditorMetatileSelector::buildImage(int metatileIdStart, int numMet metatileId, this->primaryTileset, this->secondaryTileset, - map->metatileLayerOrder, - map->metatileLayerOpacity, + this->layout->metatileLayerOrder, + this->layout->metatileLayerOpacity, true) .scaled(32, 32); int map_y = i / this->numMetatilesWide; From 18eb3ceb1e7e8ea02dd73b46edb455df49782054 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 1 Feb 2023 20:28:54 -0500 Subject: [PATCH 05/70] 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 5e7c0f7c9..7d4eb500e 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -92,6 +92,8 @@ class Layout : public QObject { 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 8f12d88f8..023451f48 100644 --- a/include/editor.h +++ b/include/editor.h @@ -60,11 +60,14 @@ class Editor : public QObject 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 18b947f9f..7a8b133f9 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -357,7 +357,7 @@ private slots: 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 dd2e044b6..ddffe49b8 100644 --- a/include/project.h +++ b/include/project.h @@ -145,6 +145,7 @@ class Project : public QObject 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 d15adcd3d..166fe79d9 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -62,9 +62,9 @@ class LayoutTreeModel : public QStandardItemModel { 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 fdfb030cc..ee7a1884c 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 a56a982e0..7002f908f 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 4b1bafc5f..ba422eda3 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 3d0bc6b3d..0892a1301 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 4acaf94df..c5cbe2e50 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 266806771..0c809c3f1 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 53a65154f..1add584f1 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") { From e2253939fc84628ed51082927cf06e77da2250c3 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 3 Feb 2023 13:09:25 -0500 Subject: [PATCH 06/70] use enum class for edit modes --- include/editor.h | 8 +++- include/mainwindow.h | 9 +--- src/editor.cpp | 38 ++++++++-------- src/mainwindow.cpp | 102 +++++++++++++++---------------------------- 4 files changed, 62 insertions(+), 95 deletions(-) diff --git a/include/editor.h b/include/editor.h index 023451f48..b207b9d3a 100644 --- a/include/editor.h +++ b/include/editor.h @@ -155,9 +155,13 @@ class Editor : public QObject QList *selected_events = nullptr; + enum class EditAction { None, Paint, Select, Fill, Shift, Pick, Move }; + EditAction mapEditAction = EditAction::Paint; + EditAction objectEditAction = EditAction::Select; + /// !TODO this - QString map_edit_mode = "paint"; - QString obj_edit_mode = "select"; + enum class EditMode { None, Map, Layout }; + EditMode editMode = EditMode::Map; int scaleIndex = 2; qreal collisionOpacity = 0.5; diff --git a/include/mainwindow.h b/include/mainwindow.h index 7a8b133f9..c5643b668 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -321,12 +321,6 @@ private slots: LayoutTreeModel *layoutTreeModel; - // QStandardItemModel *mapListModel; - // QList *mapGroupItemsList; - // QMap mapListIndexes; - // QIcon* mapIcon; - // QIcon* mapEditedIcon; - // QIcon* mapOpenedIcon; QAction *undoAction = nullptr; QAction *redoAction = nullptr; @@ -374,12 +368,11 @@ private slots: void setRecentMap(QString map_name); QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum); - void drawMapListIcons(QAbstractItemModel *model); void updateMapList(); void displayMapProperties(); void checkToolButtons(); - void clickToolButtonFromEditMode(QString editMode); + void clickToolButtonFromEditAction(Editor::EditAction editAction); void markMapEdited(); void showWindowTitle(); diff --git a/src/editor.cpp b/src/editor.cpp index ba422eda3..ca6d3857c 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -158,7 +158,7 @@ void Editor::setMapEditingButtonsEnabled(bool enabled) { this->ui->pushButton_ChangeDimensions->setEnabled(enabled); // If the fill button is pressed, unpress it and select the pointer. if (!enabled && (this->ui->toolButton_Fill->isChecked() || this->ui->toolButton_Dropper->isChecked())) { - this->map_edit_mode = "select"; + this->mapEditAction = EditAction::Select; this->settings->mapCursor = QCursor(); this->cursorMapTileRect->setSingleTileMode(); this->ui->toolButton_Fill->setChecked(false); @@ -1145,7 +1145,7 @@ bool Editor::setLayout(QString layoutId) { } map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight())); - connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); + connect(this->layout, &Layout::layoutDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); return true; } @@ -1156,7 +1156,7 @@ void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem * } QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); - if (event->buttons() & Qt::RightButton && (map_edit_mode == "paint" || map_edit_mode == "fill")) { + if (event->buttons() & Qt::RightButton && (mapEditAction == EditAction::Paint || mapEditAction == EditAction::Fill)) { this->cursorMapTileRect->initRightClickSelectionAnchor(pos.x(), pos.y()); } else { this->cursorMapTileRect->initAnchor(pos.x(), pos.y()); @@ -1206,7 +1206,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); if (item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { - if (map_edit_mode == "paint") { + if (mapEditAction == EditAction::Paint) { if (event->buttons() & Qt::RightButton) { item->updateMetatileSelection(event); } else if (event->buttons() & Qt::MiddleButton) { @@ -1228,9 +1228,9 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i } item->paint(event); } - } else if (map_edit_mode == "select") { + } else if (mapEditAction == EditAction::Select) { item->select(event); - } else if (map_edit_mode == "fill") { + } else if (mapEditAction == EditAction::Fill) { if (event->buttons() & Qt::RightButton) { item->updateMetatileSelection(event); } else if (event->modifiers() & Qt::ControlModifier) { @@ -1238,13 +1238,13 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i } else { item->floodFill(event); } - } else if (map_edit_mode == "pick") { + } else if (mapEditAction == EditAction::Pick) { if (event->buttons() & Qt::RightButton) { item->updateMetatileSelection(event); } else { item->pick(event); } - } else if (map_edit_mode == "shift") { + } else if (mapEditAction == EditAction::Shift) { this->setStraightPathCursorMode(event); if (this->cursorMapTileRect->getStraightPathMode()) { item->lockNondominantAxis(event); @@ -1253,10 +1253,10 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i item->shift(event); } } else if (item->paintingMode == LayoutPixmapItem::PaintMode::EventObjects) { - if (obj_edit_mode == "paint" && event->type() == QEvent::GraphicsSceneMousePress) { + if (objectEditAction == EditAction::Paint && event->type() == QEvent::GraphicsSceneMousePress) { // Right-clicking while in paint mode will change mode to select. if (event->buttons() & Qt::RightButton) { - this->obj_edit_mode = "select"; + this->objectEditAction = EditAction::Select; this->settings->mapCursor = QCursor(); this->cursorMapTileRect->setSingleTileMode(); this->ui->toolButton_Paint->setChecked(false); @@ -1278,9 +1278,9 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i } } } - } else if (obj_edit_mode == "select") { + } else if (objectEditAction == EditAction::Select) { // do nothing here, at least for now - } else if (obj_edit_mode == "shift") { + } else if (objectEditAction == EditAction::Shift) { static QPoint selection_origin; static unsigned actionId = 0; @@ -1316,7 +1316,7 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); - if (map_edit_mode == "paint") { + if (mapEditAction == EditAction::Paint) { if (event->buttons() & Qt::RightButton) { item->updateMovementPermissionSelection(event); } else if (event->buttons() & Qt::MiddleButton) { @@ -1333,9 +1333,9 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm } item->paint(event); } - } else if (map_edit_mode == "select") { + } else if (mapEditAction == EditAction::Select) { item->select(event); - } else if (map_edit_mode == "fill") { + } else if (mapEditAction == EditAction::Fill) { if (event->buttons() & Qt::RightButton) { item->pick(event); } else if (event->modifiers() & Qt::ControlModifier) { @@ -1343,9 +1343,9 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm } else { item->floodFill(event); } - } else if (map_edit_mode == "pick") { + } else if (mapEditAction == EditAction::Pick) { item->pick(event); - } else if (map_edit_mode == "shift") { + } else if (mapEditAction == EditAction::Shift) { this->setStraightPathCursorMode(event); if (this->cursorMapTileRect->getStraightPathMode()) { item->lockNondominantAxis(event); @@ -2247,8 +2247,8 @@ void Editor::objectsView_onMousePress(QMouseEvent *event) { if (map_item && map_item->paintingMode != LayoutPixmapItem::PaintMode::EventObjects) { return; } - if (this->obj_edit_mode == "paint" && event->buttons() & Qt::RightButton) { - this->obj_edit_mode = "select"; + if (this->objectEditAction == EditAction::Paint && event->buttons() & Qt::RightButton) { + this->objectEditAction = EditAction::Select; this->settings->mapCursor = QCursor(); this->cursorMapTileRect->setSingleTileMode(); this->ui->toolButton_Paint->setChecked(false); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0892a1301..3c39fbc70 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -625,7 +625,6 @@ void MainWindow::unsetMap() { this->editor->unsetMap(); // disable other tabs - this->ui->mainTabBar->setTabEnabled(0, true); this->ui->mainTabBar->setTabEnabled(1, false); this->ui->mainTabBar->setTabEnabled(2, false); this->ui->mainTabBar->setTabEnabled(3, false); @@ -653,6 +652,11 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(map_name)), false); } + this->ui->mainTabBar->setTabEnabled(1, true); + this->ui->mainTabBar->setTabEnabled(2, true); + this->ui->mainTabBar->setTabEnabled(3, true); + this->ui->mainTabBar->setTabEnabled(4, true); + refreshMapScene(); displayMapProperties(); @@ -1492,39 +1496,7 @@ void MainWindow::on_layoutList_activated(const QModelIndex &index) { } } -/// !TODO something with the projectHasUnsavedChanges var -void MainWindow::drawMapListIcons(QAbstractItemModel *model) { - // projectHasUnsavedChanges = false; - // QList list; - // list.append(QModelIndex()); - // while (list.length()) { - // QModelIndex parent = list.takeFirst(); - // for (int i = 0; i < model->rowCount(parent); i++) { - // QModelIndex index = model->index(i, 0, parent); - // if (model->hasChildren(index)) { - // list.append(index); - // } - // QVariant data = index.data(Qt::UserRole); - // if (!data.isNull()) { - // QString map_name = data.toString(); - // if (editor->project && editor->project->mapCache.contains(map_name)) { - // QStandardItem *map = mapListModel->itemFromIndex(mapListIndexes.value(map_name)); - // map->setIcon(*mapIcon); - // if (editor->project->mapCache.value(map_name)->hasUnsavedChanges()) { - // map->setIcon(*mapEditedIcon); - // projectHasUnsavedChanges = true; - // } - // if (editor->map->name == map_name) { - // map->setIcon(*mapOpenedIcon); - // } - // } - // } - // } - // } -} - void MainWindow::updateMapList() { - //MapGroupModel *model = static_cast(this->ui->mapList->model()); if (this->editor->map) { mapGroupModel->setMap(this->editor->map->name); groupListProxyModel->layoutChanged(); @@ -1534,8 +1506,6 @@ void MainWindow::updateMapList() { layoutTreeModel->setLayout(this->editor->layout->id); layoutListProxyModel->layoutChanged(); } - //mapGroupModel->layoutChanged(); - // drawMapListIcons(mapListModel); } void MainWindow::on_action_Save_Project_triggered() { @@ -1846,11 +1816,11 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index) if (index == 0) { ui->stackedWidget_MapEvents->setCurrentIndex(0); on_mapViewTab_tabBarClicked(ui->mapViewTab->currentIndex()); - clickToolButtonFromEditMode(editor->map_edit_mode); + clickToolButtonFromEditAction(editor->mapEditAction); } else if (index == 1) { ui->stackedWidget_MapEvents->setCurrentIndex(1); editor->setEditingObjects(); - clickToolButtonFromEditMode(editor->obj_edit_mode); + clickToolButtonFromEditAction(editor->objectEditAction); } else if (index == 3) { editor->setEditingConnections(); } @@ -2324,9 +2294,9 @@ void MainWindow::on_toolButton_deleteObject_clicked() { void MainWindow::on_toolButton_Paint_clicked() { if (ui->mainTabBar->currentIndex() == 0) - editor->map_edit_mode = "paint"; + editor->mapEditAction = Editor::EditAction::Paint; else - editor->obj_edit_mode = "paint"; + editor->objectEditAction = Editor::EditAction::Paint; editor->settings->mapCursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10); @@ -2345,9 +2315,9 @@ void MainWindow::on_toolButton_Paint_clicked() void MainWindow::on_toolButton_Select_clicked() { if (ui->mainTabBar->currentIndex() == 0) - editor->map_edit_mode = "select"; + editor->mapEditAction = Editor::EditAction::Select; else - editor->obj_edit_mode = "select"; + editor->objectEditAction = Editor::EditAction::Select; editor->settings->mapCursor = QCursor(); editor->cursorMapTileRect->setSingleTileMode(); @@ -2363,9 +2333,9 @@ void MainWindow::on_toolButton_Select_clicked() void MainWindow::on_toolButton_Fill_clicked() { if (ui->mainTabBar->currentIndex() == 0) - editor->map_edit_mode = "fill"; + editor->mapEditAction = Editor::EditAction::Fill; else - editor->obj_edit_mode = "fill"; + editor->objectEditAction = Editor::EditAction::Fill; editor->settings->mapCursor = QCursor(QPixmap(":/icons/fill_color_cursor.ico"), 10, 10); editor->cursorMapTileRect->setSingleTileMode(); @@ -2381,9 +2351,9 @@ void MainWindow::on_toolButton_Fill_clicked() void MainWindow::on_toolButton_Dropper_clicked() { if (ui->mainTabBar->currentIndex() == 0) - editor->map_edit_mode = "pick"; + editor->mapEditAction = Editor::EditAction::Pick; else - editor->obj_edit_mode = "pick"; + editor->objectEditAction = Editor::EditAction::Pick; editor->settings->mapCursor = QCursor(QPixmap(":/icons/pipette_cursor.ico"), 10, 10); editor->cursorMapTileRect->setSingleTileMode(); @@ -2399,9 +2369,9 @@ void MainWindow::on_toolButton_Dropper_clicked() void MainWindow::on_toolButton_Move_clicked() { if (ui->mainTabBar->currentIndex() == 0) - editor->map_edit_mode = "move"; + editor->mapEditAction = Editor::EditAction::Move; else - editor->obj_edit_mode = "move"; + editor->objectEditAction = Editor::EditAction::Move; editor->settings->mapCursor = QCursor(QPixmap(":/icons/move.ico"), 7, 7); editor->cursorMapTileRect->setSingleTileMode(); @@ -2417,9 +2387,9 @@ void MainWindow::on_toolButton_Move_clicked() void MainWindow::on_toolButton_Shift_clicked() { if (ui->mainTabBar->currentIndex() == 0) - editor->map_edit_mode = "shift"; + editor->mapEditAction = Editor::EditAction::Shift; else - editor->obj_edit_mode = "shift"; + editor->objectEditAction = Editor::EditAction::Shift; editor->settings->mapCursor = QCursor(QPixmap(":/icons/shift_cursor.ico"), 10, 10); editor->cursorMapTileRect->setSingleTileMode(); @@ -2433,37 +2403,37 @@ void MainWindow::on_toolButton_Shift_clicked() } void MainWindow::checkToolButtons() { - QString edit_mode; + Editor::EditAction editAction; if (ui->mainTabBar->currentIndex() == 0) { - edit_mode = editor->map_edit_mode; + editAction = editor->mapEditAction; } else { - edit_mode = editor->obj_edit_mode; - if (edit_mode == "select" && editor->map_ruler) + editAction = editor->objectEditAction; + if (editAction == Editor::EditAction::Select && editor->map_ruler) editor->map_ruler->setEnabled(true); else if (editor->map_ruler) editor->map_ruler->setEnabled(false); } - ui->toolButton_Paint->setChecked(edit_mode == "paint"); - ui->toolButton_Select->setChecked(edit_mode == "select"); - ui->toolButton_Fill->setChecked(edit_mode == "fill"); - ui->toolButton_Dropper->setChecked(edit_mode == "pick"); - ui->toolButton_Move->setChecked(edit_mode == "move"); - ui->toolButton_Shift->setChecked(edit_mode == "shift"); + ui->toolButton_Paint->setChecked(editAction == Editor::EditAction::Paint); + ui->toolButton_Select->setChecked(editAction == Editor::EditAction::Select); + ui->toolButton_Fill->setChecked(editAction == Editor::EditAction::Fill); + ui->toolButton_Dropper->setChecked(editAction == Editor::EditAction::Pick); + ui->toolButton_Move->setChecked(editAction == Editor::EditAction::Move); + ui->toolButton_Shift->setChecked(editAction == Editor::EditAction::Shift); } -void MainWindow::clickToolButtonFromEditMode(QString editMode) { - if (editMode == "paint") { +void MainWindow::clickToolButtonFromEditAction(Editor::EditAction editAction) { + if (editAction == Editor::EditAction::Paint) { on_toolButton_Paint_clicked(); - } else if (editMode == "select") { + } else if (editAction == Editor::EditAction::Select) { on_toolButton_Select_clicked(); - } else if (editMode == "fill") { + } else if (editAction == Editor::EditAction::Fill) { on_toolButton_Fill_clicked(); - } else if (editMode == "pick") { + } else if (editAction == Editor::EditAction::Pick) { on_toolButton_Dropper_clicked(); - } else if (editMode == "move") { + } else if (editAction == Editor::EditAction::Move) { on_toolButton_Move_clicked(); - } else if (editMode == "shift") { + } else if (editAction == Editor::EditAction::Shift) { on_toolButton_Shift_clicked(); } } From 1497f42ab0cbecf7b236440c5ee377cd9267834e Mon Sep 17 00:00:00 2001 From: garak Date: Sun, 5 Feb 2023 14:52:40 -0500 Subject: [PATCH 07/70] save progress --- include/editor.h | 19 ++++++++++++------- src/editor.cpp | 41 +++++++++++++++++++++++----------------- src/mainwindow.cpp | 10 +++++++++- src/ui/maplistmodels.cpp | 3 ++- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/include/editor.h b/include/editor.h index b207b9d3a..29709df8e 100644 --- a/include/editor.h +++ b/include/editor.h @@ -84,12 +84,6 @@ class Editor : public QObject void updateMapBorder(); void updateMapConnections(); - void setEditingMap(); - void setEditingCollision(); - void setEditingObjects(); - void setEditingConnections(); - void setMapEditingButtonsEnabled(bool enabled); - void setCurrentConnectionDirection(QString curDirection); void updateCurrentConnectionDirection(QString curDirection); void setConnectionsVisibility(bool visible); @@ -160,8 +154,19 @@ class Editor : public QObject EditAction objectEditAction = EditAction::Select; /// !TODO this - enum class EditMode { None, Map, Layout }; + enum class EditMode { None, Disabled, Map, Layout, Objects, Connections, Encounters }; EditMode editMode = EditMode::Map; + void setEditMode(EditMode mode) { this->editMode = mode; } + EditMode getEditMode() { return this->editMode; } + + void setEditingMap(); + void setEditingCollision(); + void setEditingLayout(); + void setEditingObjects(); + void setEditingConnections(); + void setEditingEncounters(); + + void setMapEditingButtonsEnabled(bool enabled); int scaleIndex = 2; qreal collisionOpacity = 0.5; diff --git a/src/editor.cpp b/src/editor.cpp index ca6d3857c..8a508bbf6 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -81,7 +81,6 @@ void Editor::closeProject() { } void Editor::setEditingMap() { - qDebug() << "Editor::setEditingMap()"; current_view = map_item; if (map_item) { map_item->paintingMode = LayoutPixmapItem::PaintMode::Metatiles; @@ -104,6 +103,10 @@ void Editor::setEditingMap() { setMapEditingButtonsEnabled(true); } +void Editor::setEditingLayout() { + // +} + void Editor::setEditingCollision() { current_view = collision_item; if (collision_item) { @@ -152,22 +155,6 @@ void Editor::setEditingObjects() { setMapEditingButtonsEnabled(false); } -void Editor::setMapEditingButtonsEnabled(bool enabled) { - this->ui->toolButton_Fill->setEnabled(enabled); - this->ui->toolButton_Dropper->setEnabled(enabled); - this->ui->pushButton_ChangeDimensions->setEnabled(enabled); - // If the fill button is pressed, unpress it and select the pointer. - if (!enabled && (this->ui->toolButton_Fill->isChecked() || this->ui->toolButton_Dropper->isChecked())) { - this->mapEditAction = EditAction::Select; - this->settings->mapCursor = QCursor(); - this->cursorMapTileRect->setSingleTileMode(); - this->ui->toolButton_Fill->setChecked(false); - this->ui->toolButton_Dropper->setChecked(false); - this->ui->toolButton_Select->setChecked(true); - } - this->ui->checkBox_smartPaths->setEnabled(enabled); -} - void Editor::setEditingConnections() { current_view = map_item; if (map_item) { @@ -199,6 +186,26 @@ void Editor::setEditingConnections() { this->cursorMapTileRect->setActive(false); } +void Editor::setEditingEncounters() { + // +} + +void Editor::setMapEditingButtonsEnabled(bool enabled) { + this->ui->toolButton_Fill->setEnabled(enabled); + this->ui->toolButton_Dropper->setEnabled(enabled); + this->ui->pushButton_ChangeDimensions->setEnabled(enabled); + // If the fill button is pressed, unpress it and select the pointer. + if (!enabled && (this->ui->toolButton_Fill->isChecked() || this->ui->toolButton_Dropper->isChecked())) { + this->mapEditAction = EditAction::Select; + this->settings->mapCursor = QCursor(); + this->cursorMapTileRect->setSingleTileMode(); + this->ui->toolButton_Fill->setChecked(false); + this->ui->toolButton_Dropper->setChecked(false); + this->ui->toolButton_Select->setChecked(true); + } + this->ui->checkBox_smartPaths->setEnabled(enabled); +} + void Editor::displayWildMonTables() { QStackedWidget *stack = ui->stackedWidget_WildMons; QComboBox *labelCombo = ui->comboBox_EncounterGroupLabel; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3c39fbc70..9edf62627 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -335,6 +335,7 @@ void MainWindow::initMiscHeapObjects() { ui->tabWidget_EventType->clear(); } +// TODO void MainWindow::initMapSortOrder() { // QMenu *mapSortOrderMenu = new QMenu(this); // QActionGroup *mapSortOrderActionGroup = new QActionGroup(ui->toolButton_MapSortOrder); @@ -356,6 +357,7 @@ void MainWindow::initMapSortOrder() { } void MainWindow::showWindowTitle() { + // !TODO, check editor editmode if (editor->map) { setWindowTitle(QString("%1%2 - %3") .arg(editor->map->hasUnsavedChanges() ? "* " : "") @@ -363,6 +365,13 @@ void MainWindow::showWindowTitle() { .arg(editor->project->getProjectTitle()) ); } + else if (editor->layout) { + setWindowTitle(QString("%1%2 - %3") + .arg(editor->layout->hasUnsavedChanges() ? "* " : "") + .arg(editor->layout->id) + .arg(editor->project->getProjectTitle()) + ); + } } void MainWindow::markMapEdited() { @@ -1780,7 +1789,6 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index) Scripting::cb_MapViewTabChanged(oldIndex, index); if (index == 0) { - //if () editor->setEditingMap(); } else if (index == 1) { editor->setEditingCollision(); diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 1add584f1..dcf232070 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -274,7 +274,8 @@ LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : QStandardI QStandardItem *LayoutTreeModel::createLayoutItem(QString layoutId) { QStandardItem *layout = new QStandardItem; - layout->setText(layoutId); + layout->setText(this->project->layoutIdsToNames[layoutId]); + //layout->setText(layoutId); layout->setEditable(false); layout->setData(layoutId, Qt::UserRole); layout->setData("map_layout", MapListRoles::TypeRole); From de8b005d77edda406d234e2d516fab1136c7088d Mon Sep 17 00:00:00 2001 From: garak Date: Mon, 6 Feb 2023 13:42:21 -0500 Subject: [PATCH 08/70] gray out map icons until map is open ... because the color of the icon does not mean anything until map has been loaded into memory for example, if the map's layout has changed then it should be marked as modified but that wouldn't happen if the map is unloaded --- resources/icons/map_grayed.ico | Bin 0 -> 1150 bytes resources/images.qrc | 1 + src/mainwindow.cpp | 4 ++-- src/ui/maplistmodels.cpp | 6 +++++- 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 resources/icons/map_grayed.ico diff --git a/resources/icons/map_grayed.ico b/resources/icons/map_grayed.ico new file mode 100644 index 0000000000000000000000000000000000000000..86c3f5fb72543d3d652ece433cf88cbcf15d3722 GIT binary patch literal 1150 zcmbtUxo*Nh6nv5L0aU3dQl`&Oa8pro6cjEH_kBn}35XT}6_Bq3S|skt&W1$>BjtM5 zc-}Gd)|MrUJgLj&5_NwS>sjPQMBWrsOLe~bibT}xLAX`#{SR;h5Rb?65eNj}^?IT5 zZ$TaPN;{`N7z`@85fZcAVvE6QQ4>O~Vaq(UKmSrIpiy9hlxOh)&}sZ}6pT@uN2@_n7uK)l5 literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index 2399cbe9d..e90d58494 100644 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -17,6 +17,7 @@ icons/map_edited.ico icons/map_opened.ico icons/map.ico + icons/map_grayed.ico icons/move.ico icons/pencil_cursor.ico icons/pencil.ico diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9edf62627..c503d23d4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -368,7 +368,7 @@ void MainWindow::showWindowTitle() { else if (editor->layout) { setWindowTitle(QString("%1%2 - %3") .arg(editor->layout->hasUnsavedChanges() ? "* " : "") - .arg(editor->layout->id) + .arg(editor->layout->name) .arg(editor->project->getProjectTitle()) ); } @@ -1646,7 +1646,7 @@ void MainWindow::setClipboardData(QImage image) { } void MainWindow::paste() { - if (!editor || !editor->project || !editor->map) return; + if (!editor || !editor->project || !(editor->map || editor->layout)) return; QClipboard *clipboard = QGuiApplication::clipboard(); QString clipboardText(clipboard->text()); diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index dcf232070..e243541e7 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -180,6 +180,7 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { int col = index.column(); if (role == Qt::DecorationRole) { + static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico")); static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico")); static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico")); static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico")); @@ -206,8 +207,11 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { if (this->project->mapCache.value(mapName)->hasUnsavedChanges()) { return mapEditedIcon; } + else { + return mapIcon; + } } - return mapIcon; + return mapGrayIcon; } // check if map or group From 9918159caab306cb46d4391fe50e4e9b8af4a737 Mon Sep 17 00:00:00 2001 From: garak Date: Mon, 6 Feb 2023 15:05:22 -0500 Subject: [PATCH 09/70] ui to change map's assigned layout id --- forms/mainwindow.ui | 398 +++++++++++++++++++++++-------------------- include/core/map.h | 1 + include/mainwindow.h | 1 + src/core/map.cpp | 7 + src/editor.cpp | 12 ++ src/mainwindow.cpp | 23 ++- 6 files changed, 251 insertions(+), 191 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index a59c0ad06..9ecc927f2 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -509,7 +509,7 @@ - 3 + 0 false @@ -922,65 +922,148 @@ 3 - - + + + + 10 + + + 90 + + + 30 + + + Qt::Horizontal + + + + + - + 0 0 - - QFrame::StyledPanel + + Qt::ScrollBarAlwaysOn - - QFrame::Raised + + Qt::ScrollBarAsNeeded - - - - - Primary Tileset - - - - - - - Qt::StrongFocus - - - <html><head/><body><p>Primary Tileset</p><p>Defines the first 0x200 metatiles available for the map.</p></body></html> - - - true - - - - - - - Secondary Tileset - - - - - - - Qt::StrongFocus - - - <html><head/><body><p>Secondary Tileset</p><p>Defines the second 0x200 metatiles available for the map.</p></body></html> - - - true - - - - + + QAbstractScrollArea::AdjustIgnored + + + true + + + Qt::AlignHCenter|Qt::AlignTop + + + + true + + + + 8 + 0 + 408 + 380 + + + + + 0 + 0 + + + + + QLayout::SetDefaultConstraint + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + true + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustIgnored + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + - + @@ -1062,7 +1145,7 @@ 0 0 - 256 + 420 74 @@ -1143,7 +1226,7 @@ - + Border @@ -1221,145 +1304,90 @@ - - + + - + 0 0 - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAsNeeded - - - QAbstractScrollArea::AdjustIgnored - - - true + + QFrame::StyledPanel - - Qt::AlignHCenter|Qt::AlignTop + + QFrame::Raised - - - true - - - - 0 - 0 - 91 - 74 - - - - - 0 - 0 - - - - - QLayout::SetDefaultConstraint - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - true - - - - 0 - 0 - - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustIgnored - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - + + + + + Primary Tileset + + + + + + + Qt::StrongFocus + + + <html><head/><body><p>Primary Tileset</p><p>Defines the first 0x200 metatiles available for the map.</p></body></html> + + + true + + + + + + + Secondary Tileset + + + + + + + Qt::StrongFocus + + + <html><head/><body><p>Secondary Tileset</p><p>Defines the second 0x200 metatiles available for the map.</p></body></html> + + + true + + + + - - - - 10 - - - 90 - - - 30 + + + + QFrame::NoFrame - - Qt::Horizontal + + QFrame::Raised + + + 2 + + + 2 + + + + + Layout + + + + + + + @@ -1403,8 +1431,8 @@ 0 0 - 92 - 550 + 425 + 696 @@ -1563,8 +1591,8 @@ 0 0 - 91 - 460 + 379 + 611 diff --git a/include/core/map.h b/include/core/map.h index 37ae9b581..87bfd0d97 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -59,6 +59,7 @@ class Map : public QObject QMap customHeaders; Layout *layout = nullptr; + void setLayout(Layout *layout); bool isPersistedToFile = true; bool hasUnsavedDataChanges = false; diff --git a/include/mainwindow.h b/include/mainwindow.h index c5643b668..d4390bbb8 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -200,6 +200,7 @@ private slots: void on_comboBox_Weather_currentTextChanged(const QString &arg1); void on_comboBox_Type_currentTextChanged(const QString &arg1); void on_comboBox_BattleScene_currentTextChanged(const QString &arg1); + void on_comboBox_LayoutSelector_currentTextChanged(const QString &arg1); void on_checkBox_ShowLocation_stateChanged(int selected); void on_checkBox_AllowRunning_stateChanged(int selected); void on_checkBox_AllowBiking_stateChanged(int selected); diff --git a/src/core/map.cpp b/src/core/map.cpp index ee7a1884c..fc167ea13 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -29,6 +29,13 @@ void Map::setName(QString mapName) { constantName = mapConstantFromName(mapName); } +void Map::setLayout(Layout *layout) { + this->layout = layout; + if (layout) { + this->layoutId = layout->id; + } +} + QString Map::mapConstantFromName(QString mapName) { // Transform map names of the form 'GraniteCave_B1F` into map constants like 'MAP_GRANITE_CAVE_B1F'. static const QRegularExpression caseChange("([a-z])([A-Z])"); diff --git a/src/editor.cpp b/src/editor.cpp index 8a508bbf6..18915bdc7 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1154,6 +1154,18 @@ bool Editor::setLayout(QString layoutId) { map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight())); connect(this->layout, &Layout::layoutDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); + ui->comboBox_PrimaryTileset->blockSignals(true); + ui->comboBox_SecondaryTileset->blockSignals(true); + ui->comboBox_PrimaryTileset->setCurrentText(this->layout->tileset_primary_label); + ui->comboBox_SecondaryTileset->setCurrentText(this->layout->tileset_secondary_label); + ui->comboBox_PrimaryTileset->blockSignals(false); + ui->comboBox_SecondaryTileset->blockSignals(false); + + const QSignalBlocker b0(this->ui->comboBox_LayoutSelector); + int index = this->ui->comboBox_LayoutSelector->findText(layoutId); + if (index < 0) index = 0; + this->ui->comboBox_LayoutSelector->setCurrentIndex(index); + return true; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c503d23d4..3904ca0c9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -640,6 +640,7 @@ void MainWindow::unsetMap() { this->ui->mainTabBar->setTabEnabled(4, false); // + this->ui->comboBox_LayoutSelector->setEnabled(false); } bool MainWindow::setMap(QString map_name, bool scrollTreeView) { @@ -721,12 +722,7 @@ bool MainWindow::setLayout(QString layoutId) { // 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); @@ -876,6 +872,18 @@ void MainWindow::displayMapProperties() { ui->tableWidget_CustomHeaderFields->blockSignals(false); } +void MainWindow::on_comboBox_LayoutSelector_currentTextChanged(const QString &text) { + // + if (editor && editor->project && editor->map) { + if (editor->project->mapLayouts.contains(text)) { + editor->map->setLayout(editor->project->loadLayout(text)); + // !TODO: method to setMapLayout instead of having to do whole setMap thing, + // also edit history and bug fixes + setMap(editor->map->name); + } + } +} + void MainWindow::on_comboBox_Song_currentTextChanged(const QString &song) { if (editor && editor->map) { @@ -1012,6 +1020,7 @@ bool MainWindow::loadProjectCombos() { const QSignalBlocker blocker5(ui->comboBox_Weather); const QSignalBlocker blocker6(ui->comboBox_BattleScene); const QSignalBlocker blocker7(ui->comboBox_Type); + const QSignalBlocker blocker8(ui->comboBox_LayoutSelector); ui->comboBox_Song->clear(); ui->comboBox_Song->addItems(project->songNames); @@ -1027,6 +1036,8 @@ bool MainWindow::loadProjectCombos() { ui->comboBox_BattleScene->addItems(project->mapBattleScenes); ui->comboBox_Type->clear(); ui->comboBox_Type->addItems(project->mapTypes); + ui->comboBox_LayoutSelector->clear(); + ui->comboBox_LayoutSelector->addItems(project->mapLayoutsTable); return true; } From e2ff93e5e70bb2f3367ec7858a3945969a5b0c14 Mon Sep 17 00:00:00 2001 From: garak Date: Mon, 6 Feb 2023 23:48:37 -0500 Subject: [PATCH 10/70] add areaList model and filtering, scrolling for all trees --- include/mainwindow.h | 11 +- include/ui/maplistmodels.h | 39 +++- resources/icons/application_form_edit.ico | Bin 1150 -> 1150 bytes resources/icons/connections.ico | Bin 0 -> 1150 bytes resources/images.qrc | 2 + src/mainwindow.cpp | 113 ++++++--- src/ui/maplistmodels.cpp | 264 +++++++++------------- 7 files changed, 231 insertions(+), 198 deletions(-) create mode 100644 resources/icons/connections.ico diff --git a/include/mainwindow.h b/include/mainwindow.h index d4390bbb8..7bc47ff23 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -266,6 +266,8 @@ private slots: void on_actionTileset_Editor_triggered(); void on_lineEdit_filterBox_textChanged(const QString &arg1); + void on_lineEdit_filterBox_Areas_textChanged(const QString &arg1); + void on_lineEdit_filterBox_Layouts_textChanged(const QString &arg1); void moveEvent(QMoveEvent *event); void closeEvent(QCloseEvent *); @@ -318,6 +320,9 @@ private slots: FilterChildrenProxyModel *groupListProxyModel; MapGroupModel *mapGroupModel; + FilterChildrenProxyModel *areaListProxyModel; + MapAreaModel *mapAreaModel; + FilterChildrenProxyModel *layoutListProxyModel; LayoutTreeModel *layoutTreeModel; @@ -348,13 +353,13 @@ private slots: bool newMapDefaultsSet = false; MapSortOrder mapSortOrder; - enum MapListTab { Groups, Areas, Layouts }; + enum MapListTab { Groups = 0, Areas, Layouts }; bool tilesetNeedsRedraw = false; bool setLayout(QString layoutId); - bool setMap(QString, bool scrollTreeView = false); + bool setMap(QString, bool scroll = false); void unsetMap(); void redrawMapScene(); void refreshMapScene(); @@ -363,11 +368,11 @@ private slots: bool populateMapList(); void sortMapList(); void openSubWindow(QWidget * window); + void scrollTreeView(QString itemName); QString getExistingDirectory(QString); bool openProject(QString dir); QString getDefaultMap(); void setRecentMap(QString map_name); - QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum); void updateMapList(); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 166fe79d9..d730c05e0 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -15,7 +15,8 @@ enum MapListRoles { TypeRole2, // Used for various extra data needed. }; -// or QStandardItemModel?? + + class MapGroupModel : public QStandardItemModel { Q_OBJECT @@ -52,6 +53,42 @@ class MapGroupModel : public QStandardItemModel { +class MapAreaModel : public QStandardItemModel { + Q_OBJECT + +public: + MapAreaModel(Project *project, QObject *parent = nullptr); + ~MapAreaModel() {} + + QVariant data(const QModelIndex &index, int role) const override; + +public: + void setMap(QString mapName) { this->openMap = mapName; } + + QStandardItem *createAreaItem(QString areaName, int areaIndex); + QStandardItem *createMapItem(QString mapName, int areaIndex, int mapIndex); + + QStandardItem *getItem(const QModelIndex &index) const; + QModelIndex indexOfMap(QString mapName); + + void initialize(); + +private: + Project *project; + QStandardItem *root = nullptr; + + QMap areaItems; + QMap mapItems; + // TODO: if reordering, will the item be the same? + + QString openMap; + +signals: + void edited(); +}; + + + class LayoutTreeModel : public QStandardItemModel { Q_OBJECT diff --git a/resources/icons/application_form_edit.ico b/resources/icons/application_form_edit.ico index 7bb403eab9c641b0f756a6de02c6cb30a22a8b65..5d9cc7dafdf245cfecb63a9002530a2ae3990568 100644 GIT binary patch literal 1150 zcmb7@T}YEr7{`wgNTZKMr4+3!B%A3~(ir&J26 zGsN{xLZk^Hju4ch%u1fZ|CW0pUH%;;wYc!ecuUBt%+ceu@eWZXje>3d) zsc_{9oPHI@<7q%U2<)r`PTZRoPP@(vjEBp z;NTTn3>9bL7V_^Eyk_>#%!FYw8c}63;q#|3JRNPaj;q7!H#pY?WV`@0FF)X3t{QG# zD%wl7CHvepj5m$rU3nLp@(1K|WB<_LAj(Qh@zh{|cW4mq4p+jKj2=%rydy(s z)q2sYABW{(P~Ly`_xAK+ps$bUm!o8^LA7K?Rkb9;ZO-+P<{OP@(+D{A3i5Bk!Y?{^ zK6{2b7l_60#E;du+Fqc@{fl$~tOW`Tw; literal 1150 zcmb7D%W7gl5beNxKvuJ!MHbo52h8ux!bl*#B0eIh5JAmO5rZ*7#O-L7MqLRa5>XHz zQ4&K8_*l5nsPRmn9wo3DBxv|2*Wqx8ZJeE*38T>{j*pLVbaaI4>uWHM%jFWZZToUB<$(5G`2BvQQYkz< zJiuf!sTeyx2juH?x&rM6gW)ga^LY#g1GHK#WHK3?o}NPb!(y?(Y&L^DyWK9xrM$hp zDa_|{%w{tMx7&?MrGmS=JKWyhs`$!TE{s7w^R8Aaj7B4c@pz2kaEQrdqFg;55AN^p zRg82x4ZU8k^sHl>|MK#JXf%q;%S*hzz9N^)DL*df=jW(atH@@vs*aPB6WDAvIGxT- z{>R5hJUu<3-|s72U0op_kK^X%2FYX+KA#VrP6uAESH-bft*WP5{q1&J+1YOm^rxQR zy)`x$rBEnS#e$j&(0piVlf4+AGA?8cdh^L@9&%WYxiKW zSYWwag757;?d$a#@{V%`>i%@Q-AxYW(Q>hdZD{q-pZUq>y)2bVC>D#K2K~un{W8Wc f?s=a+3;L7C|7YbCV)aA*S$iKqsy6bGUFv=V+U%?a diff --git a/resources/icons/connections.ico b/resources/icons/connections.ico new file mode 100644 index 0000000000000000000000000000000000000000..effb20c982f6c95a93a7a32e20bac1c026a291bf GIT binary patch literal 1150 zcmbVLO-~b16n!NA09LL|+$iw_LZZQ#km?U`p>F&G5OyZe$^s~`(}in|E`)}tIPFYl zh7Lu64Z#>dT zU|KT+7qOD;l-d?8-Iq79@VHk|`%RI1`CxTuf9MUQzq!dlgcDtY4mi;>SQzWY-gn^Z zw*v)pa@0b-<}~FP@G4Szodg%*j>e-vVptseM2C9aQ(inRKNu l*?5}?hT7$h+NIBJ%2BKBx#s;jU`)K>Z*VYcahOhy-d`6swTA!z literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index e90d58494..676853bb8 100644 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -34,6 +34,8 @@ icons/sort_number.ico icons/tall_grass.ico icons/viewsprites.ico + icons/application_form_edit.ico + icons/connections.ico icons/ui/dark_checkbox_checked_disabled.png icons/ui/dark_checkbox_checked_disabled@2x.png icons/ui/dark_checkbox_checked.png diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3904ca0c9..06387fa10 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -205,8 +205,11 @@ void MainWindow::initCustomUI() { ui->mainTabBar->addTab("Map"); ui->mainTabBar->setTabIcon(0, QIcon(QStringLiteral(":/icons/map.ico"))); ui->mainTabBar->addTab("Events"); + ui->mainTabBar->setTabIcon(1, QIcon(QStringLiteral(":/icons/viewsprites.ico"))); ui->mainTabBar->addTab("Header"); + ui->mainTabBar->setTabIcon(2, QIcon(QStringLiteral(":/icons/application_form_edit.ico"))); ui->mainTabBar->addTab("Connections"); + ui->mainTabBar->setTabIcon(3, QIcon(QStringLiteral(":/icons/connections.ico"))); ui->mainTabBar->addTab("Wild Pokemon"); ui->mainTabBar->setTabIcon(4, QIcon(QStringLiteral(":/icons/tall_grass.ico"))); } @@ -340,6 +343,8 @@ void MainWindow::initMapSortOrder() { // QMenu *mapSortOrderMenu = new QMenu(this); // QActionGroup *mapSortOrderActionGroup = new QActionGroup(ui->toolButton_MapSortOrder); + // porymapConfig.setMapSortOrder(mapSortOrder); + // mapSortOrderMenu->addAction(ui->actionSort_by_Group); // mapSortOrderMenu->addAction(ui->actionSort_by_Area); // mapSortOrderMenu->addAction(ui->actionSort_by_Layout); @@ -410,14 +415,40 @@ void MainWindow::on_lineEdit_filterBox_textChanged(const QString &text) { this->applyMapListFilter(text); } +void MainWindow::on_lineEdit_filterBox_Areas_textChanged(const QString &text) { + this->applyMapListFilter(text); +} + +void MainWindow::on_lineEdit_filterBox_Layouts_textChanged(const QString &text) { + this->applyMapListFilter(text); +} + void MainWindow::applyMapListFilter(QString filterText) { - /// !TODO - groupListProxyModel->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption)); + FilterChildrenProxyModel *proxy; + QTreeView *list; + switch (this->mapSortOrder) { + case MapSortOrder::SortByGroup: + proxy = this->groupListProxyModel; + list = this->ui->mapList; + break; + case MapSortOrder::SortByArea: + proxy = this->areaListProxyModel; + list = this->ui->areaList; + break; + case MapSortOrder::SortByLayout: + proxy = this->layoutListProxyModel; + list = this->ui->layoutList; + break; + } + + proxy->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption)); if (filterText.isEmpty()) { - ui->mapList->collapseAll(); + list->collapseAll(); } else { - ui->mapList->expandToDepth(0); + list->expandToDepth(0); } + + /// !TODO // ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), true); // ui->mapList->scrollTo(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), QAbstractItemView::PositionAtCenter); } @@ -432,6 +463,9 @@ void MainWindow::loadUserSettings() { ui->checkBox_ToggleBorder->setChecked(porymapConfig.getShowBorder()); ui->checkBox_ToggleGrid->setChecked(porymapConfig.getShowGrid()); mapSortOrder = porymapConfig.getMapSortOrder(); + this->ui->mapListContainer->blockSignals(true); + this->ui->mapListContainer->setCurrentIndex(static_cast(this->mapSortOrder)); + this->ui->mapListContainer->blockSignals(false); ui->horizontalSlider_CollisionTransparency->blockSignals(true); this->editor->collisionOpacity = static_cast(porymapConfig.getCollisionOpacity()) / 100; ui->horizontalSlider_CollisionTransparency->setValue(porymapConfig.getCollisionOpacity()); @@ -643,7 +677,7 @@ void MainWindow::unsetMap() { this->ui->comboBox_LayoutSelector->setEnabled(false); } -bool MainWindow::setMap(QString map_name, bool scrollTreeView) { +bool MainWindow::setMap(QString map_name, bool scroll) { // if map name is empty, clear & disable map ui if (map_name.isEmpty()) { unsetMap(); @@ -670,12 +704,8 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { refreshMapScene(); displayMapProperties(); - 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); + if (scroll) { + scrollTreeView(map_name); } showWindowTitle(); @@ -1042,13 +1072,7 @@ bool MainWindow::loadProjectCombos() { return true; } -/// !TODO bool MainWindow::populateMapList() { - // bool success = editor->project->readMapGroups(); - // if (success) { - // sortMapList(); - // } - // return success; bool success = editor->project->readMapGroups(); this->mapGroupModel = new MapGroupModel(editor->project); @@ -1056,21 +1080,43 @@ bool MainWindow::populateMapList() { groupListProxyModel->setSourceModel(this->mapGroupModel); ui->mapList->setModel(groupListProxyModel); + this->mapAreaModel = new MapAreaModel(editor->project); + this->areaListProxyModel = new FilterChildrenProxyModel(); + areaListProxyModel->setSourceModel(this->mapAreaModel); + ui->areaList->setModel(areaListProxyModel); + this->layoutTreeModel = new LayoutTreeModel(editor->project); this->layoutListProxyModel = new FilterChildrenProxyModel(); this->layoutListProxyModel->setSourceModel(this->layoutTreeModel); ui->layoutList->setModel(layoutListProxyModel); - //connect(this->ui->layoutList, &QTreeView::doubleClicked, this, &MainWindow::on_layoutList_activated); - + /// !TODO // ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); // ui->mapList->setDragEnabled(true); // ui->mapList->setAcceptDrops(true); // ui->mapList->setDropIndicatorShown(true); return success; +} - //MapGroupModel +void MainWindow::scrollTreeView(QString itemName) { + switch (ui->mapListContainer->currentIndex()) { + case MapListTab::Groups: + groupListProxyModel->setFilterRegularExpression(QString()); + ui->mapList->setCurrentIndex(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(itemName))); + ui->mapList->scrollTo(ui->mapList->currentIndex(), QAbstractItemView::PositionAtCenter); + break; + case MapListTab::Areas: + areaListProxyModel->setFilterRegularExpression(QString()); + ui->areaList->setCurrentIndex(areaListProxyModel->mapFromSource(mapAreaModel->indexOfMap(itemName))); + ui->areaList->scrollTo(ui->areaList->currentIndex(), QAbstractItemView::PositionAtCenter); + break; + case MapListTab::Layouts: + layoutListProxyModel->setFilterRegularExpression(QString()); + ui->layoutList->setCurrentIndex(layoutListProxyModel->mapFromSource(layoutTreeModel->indexOfLayout(itemName))); + ui->layoutList->scrollTo(ui->layoutList->currentIndex(), QAbstractItemView::PositionAtCenter); + break; + } } void MainWindow::sortMapList() { @@ -1181,19 +1227,7 @@ void MainWindow::sortMapList() { // updateMapList(); } -/// !TODO -QStandardItem* MainWindow::createMapItem(QString mapName, int groupNum, int inGroupNum) { - // QStandardItem *map = new QStandardItem; - // map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName); - // map->setIcon(*mapIcon); - // map->setEditable(false); - // map->setData(mapName, Qt::UserRole); - // map->setData("map_name", MapListUserRoles::TypeRole); - // return map; -} - -void MainWindow::onOpenMapListContextMenu(const QPoint &point) -{ +void MainWindow::onOpenMapListContextMenu(const QPoint &point) { /// !TODO // QModelIndex index = mapListProxyModel->mapToSource(ui->mapList->indexAt(point)); // if (!index.isValid()) { @@ -1462,14 +1496,19 @@ void MainWindow::on_mapListContainer_currentChanged(int index) { // switch (index) { case MapListTab::Groups: + this->mapSortOrder = MapSortOrder::SortByGroup; + if (this->editor && this->editor->map) scrollTreeView(this->editor->map->name); break; case MapListTab::Areas: + this->mapSortOrder = MapSortOrder::SortByArea; + if (this->editor && this->editor->map) scrollTreeView(this->editor->map->name); break; case MapListTab::Layouts: - //setMap(nullptr); - //setLayout(nullptr); + this->mapSortOrder = MapSortOrder::SortByLayout; + if (this->editor && this->editor->layout) scrollTreeView(this->editor->layout->id); break; } + porymapConfig.setMapSortOrder(this->mapSortOrder); } /// !TODO @@ -1489,7 +1528,7 @@ void MainWindow::on_mapList_activated(const QModelIndex &index) { } void MainWindow::on_areaList_activated(const QModelIndex &index) { - // + on_mapList_activated(index); } void MainWindow::on_layoutList_activated(const QModelIndex &index) { @@ -1520,6 +1559,8 @@ void MainWindow::updateMapList() { if (this->editor->map) { mapGroupModel->setMap(this->editor->map->name); groupListProxyModel->layoutChanged(); + mapAreaModel->setMap(this->editor->map->name); + areaListProxyModel->layoutChanged(); } if (this->editor->layout) { diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index e243541e7..b904522c1 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -4,89 +4,10 @@ -/* - - // QIcon mapFolderIcon; - // mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); - // mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); - - // QIcon folderIcon; - // folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off); - // //folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On); - - // ui->mapList->setUpdatesEnabled(false); - // mapListModel->clear(); - // mapGroupItemsList->clear(); - // QStandardItem *root = mapListModel->invisibleRootItem(); - - // switch (mapSortOrder) - // { - // case MapSortOrder::Group: - // for (int i = 0; i < project->groupNames.length(); i++) { - // QString group_name = project->groupNames.value(i); - // QStandardItem *group = new QStandardItem; - // group->setText(group_name); - // group->setIcon(mapFolderIcon); - // group->setEditable(false); - // group->setData(group_name, Qt::UserRole); - // group->setData("map_group", MapListUserRoles::TypeRole); - // group->setData(i, MapListUserRoles::GroupRole); - // root->appendRow(group); - // mapGroupItemsList->append(group); - // QStringList names = project->groupedMapNames.value(i); - // for (int j = 0; j < names.length(); j++) { - // QString map_name = names.value(j); - // QStandardItem *map = createMapItem(map_name, i, j); - // group->appendRow(map); - // mapListIndexes.insert(map_name, map->index()); - // } - // } - // break; - - // mapListModel = new QStandardItemModel; - // mapGroupItemsList = new QList; - // mapListProxyModel = new FilterChildrenProxyModel; - - // mapListProxyModel->setSourceModel(mapListModel); - // ui->mapList->setModel(mapListProxyModel); - - // createMapItem: - // QStandardItem *map = new QStandardItem; - // map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName); - // map->setIcon(*mapIcon); - // map->setEditable(false); - // map->setData(mapName, Qt::UserRole); - // map->setData("map_name", MapListUserRoles::TypeRole); - // return map; - - // scrolling: - if (scrollTreeView) { - // Make sure we clear the filter first so we actually have a scroll target - /// !TODO - // mapListProxyModel->setFilterRegularExpression(QString()); - // ui->mapList->setCurrentIndex(mapListProxyModel->mapFromSource(mapListIndexes.value(map_name))); - // ui->mapList->scrollTo(ui->mapList->currentIndex(), QAbstractItemView::PositionAtCenter); - } - - // ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(map_name)), true); - -*/ MapGroupModel::MapGroupModel(Project *project, QObject *parent) : QStandardItemModel(parent) { - // - this->project = project; this->root = this->invisibleRootItem(); - // mapIcon = new QIcon(QStringLiteral(":/icons/map.ico")); - // mapEditedIcon = new QIcon(QStringLiteral(":/icons/map_edited.ico")); - // mapOpenedIcon = new QIcon(QStringLiteral(":/icons/map_opened.ico")); - - // mapFolderIcon = new QIcon(QStringLiteral(":/icons/folder_closed_map.ico")); - - //mapFolderIcon = new QIcon; - //mapFolderIcon->addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); - //mapFolderIcon->addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); - initialize(); } @@ -118,9 +39,6 @@ void MapGroupModel::initialize() { QString group_name = this->project->groupNames.value(i); QStandardItem *group = createGroupItem(group_name, i); root->appendRow(group); - QList groupItems; - QMap inGroupItems; - //mapGroupItemsList->append(group); QStringList names = this->project->groupedMapNames.value(i); for (int j = 0; j < names.length(); j++) { QString map_name = names.value(j); @@ -146,35 +64,6 @@ QModelIndex MapGroupModel::indexOfMap(QString mapName) { return QModelIndex(); } - // projectHasUnsavedChanges = false; - // QList list; - // list.append(QModelIndex()); - // while (list.length()) { - // QModelIndex parent = list.takeFirst(); - // for (int i = 0; i < model->rowCount(parent); i++) { - // QModelIndex index = model->index(i, 0, parent); - // if (model->hasChildren(index)) { - // list.append(index); - // } - // QVariant data = index.data(Qt::UserRole); - // if (!data.isNull()) { - // QString map_name = data.toString(); - // if (editor->project && editor->project->mapCache.contains(map_name)) { - // QStandardItem *map = mapListModel->itemFromIndex(mapListIndexes.value(map_name)); - // map->setIcon(*mapIcon); - // if (editor->project->mapCache.value(map_name)->hasUnsavedChanges()) { - // map->setIcon(*mapEditedIcon); - // projectHasUnsavedChanges = true; - // } - // if (editor->map->name == map_name) { - // map->setIcon(*mapOpenedIcon); - // } - // } - // } - // } - // } - -#include QVariant MapGroupModel::data(const QModelIndex &index, int role) const { int row = index.row(); int col = index.column(); @@ -213,10 +102,6 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { } return mapGrayIcon; } - - // check if map or group - // if map, check if edited or open - //return QIcon(":/icons/porymap-icon-2.ico"); } return QStandardItemModel::data(index, role); @@ -224,52 +109,124 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { +MapAreaModel::MapAreaModel(Project *project, QObject *parent) : QStandardItemModel(parent) { + this->project = project; + this->root = this->invisibleRootItem(); + initialize(); +} +QStandardItem *MapAreaModel::createAreaItem(QString mapsecName, int areaIndex) { + QStandardItem *area = new QStandardItem; + area->setText(mapsecName); + area->setEditable(false); + area->setData(mapsecName, Qt::UserRole); + area->setData("map_section", MapListRoles::TypeRole); + area->setData(areaIndex, MapListRoles::GroupRole); + // group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + this->areaItems.insert(mapsecName, area); + return area; +} +QStandardItem *MapAreaModel::createMapItem(QString mapName, int groupIndex, int mapIndex) { + QStandardItem *map = new QStandardItem; + map->setText(QString("[%1.%2] ").arg(groupIndex).arg(mapIndex, 2, 10, QLatin1Char('0')) + mapName); + map->setEditable(false); + map->setData(mapName, Qt::UserRole); + map->setData("map_name", MapListRoles::TypeRole); + // map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + this->mapItems.insert(mapName, map); + return map; +} +void MapAreaModel::initialize() { + for (int i = 0; i < this->project->mapSectionNameToValue.size(); i++) { + QString mapsecName = project->mapSectionValueToName.value(i); + QStandardItem *areaItem = createAreaItem(mapsecName, i); + this->root->appendRow(areaItem); + } + for (int i = 0; i < this->project->groupNames.length(); i++) { + QStringList names = this->project->groupedMapNames.value(i); + for (int j = 0; j < names.length(); j++) { + QString mapName = names.value(j); + QStandardItem *map = createMapItem(mapName, i, j); + QString mapsecName = this->project->readMapLocation(mapName); + if (this->areaItems.contains(mapsecName)) { + this->areaItems[mapsecName]->appendRow(map); + } + } + } +} +QStandardItem *MapAreaModel::getItem(const QModelIndex &index) const { + if (index.isValid()) { + QStandardItem *item = static_cast(index.internalPointer()); + if (item) + return item; + } + return this->root; +} +QModelIndex MapAreaModel::indexOfMap(QString mapName) { + if (this->mapItems.contains(mapName)) { + return this->mapItems[mapName]->index(); + } + return QModelIndex(); +} +QVariant MapAreaModel::data(const QModelIndex &index, int role) const { + int row = index.row(); + int col = index.column(); + if (role == Qt::DecorationRole) { + static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico")); + static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico")); + static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico")); + static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico")); + static QIcon mapFolderIcon; + static QIcon folderIcon; + static bool loaded = false; + if (!loaded) { + mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); + mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); + folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off); + folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On); + loaded = true; + } - // case MapSortOrder::Layout: - // { - // QMap layoutIndices; - // for (int i = 0; i < project->mapLayoutsTable.length(); i++) { - // QString layoutId = project->mapLayoutsTable.value(i); - // MapLayout *layout = project->mapLayouts.value(layoutId); - // QStandardItem *layoutItem = new QStandardItem; - // layoutItem->setText(layout->name); - // layoutItem->setIcon(folderIcon); - // layoutItem->setEditable(false); - // layoutItem->setData(layout->name, Qt::UserRole); - // layoutItem->setData("map_layout", MapListUserRoles::TypeRole); - // layoutItem->setData(layout->id, MapListUserRoles::TypeRole2); - // layoutItem->setData(i, MapListUserRoles::GroupRole); - // root->appendRow(layoutItem); - // mapGroupItemsList->append(layoutItem); - // layoutIndices[layoutId] = i; - // } - // for (int i = 0; i < project->groupNames.length(); i++) { - // QStringList names = project->groupedMapNames.value(i); - // for (int j = 0; j < names.length(); j++) { - // QString map_name = names.value(j); - // QStandardItem *map = createMapItem(map_name, i, j); - // QString layoutId = project->readMapLayoutId(map_name); - // QStandardItem *layoutItem = mapGroupItemsList->at(layoutIndices.value(layoutId)); - // layoutItem->setIcon(mapFolderIcon); - // layoutItem->appendRow(map); - // mapListIndexes.insert(map_name, map->index()); - // } - // } - // break; - // } -LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : QStandardItemModel(parent) { - // + QStandardItem *item = this->getItem(index)->child(row, col); + QString type = item->data(MapListRoles::TypeRole).toString(); + if (type == "map_section") { + if (item->hasChildren()) { + return mapFolderIcon; + } + return folderIcon; + } else if (type == "map_name") { + QString mapName = item->data(Qt::UserRole).toString(); + if (mapName == this->openMap) { + return mapOpenedIcon; + } + else if (this->project->mapCache.contains(mapName)) { + if (this->project->mapCache.value(mapName)->hasUnsavedChanges()) { + return mapEditedIcon; + } + else { + return mapIcon; + } + } + return mapGrayIcon; + } + } + + return QStandardItemModel::data(index, role); +} + + + +LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : QStandardItemModel(parent) { this->project = project; this->root = this->invisibleRootItem(); @@ -279,7 +236,6 @@ LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : QStandardI QStandardItem *LayoutTreeModel::createLayoutItem(QString layoutId) { QStandardItem *layout = new QStandardItem; layout->setText(this->project->layoutIdsToNames[layoutId]); - //layout->setText(layoutId); layout->setEditable(false); layout->setData(layoutId, Qt::UserRole); layout->setData("map_layout", MapListRoles::TypeRole); @@ -301,7 +257,6 @@ QStandardItem *LayoutTreeModel::createMapItem(QString mapName) { void LayoutTreeModel::initialize() { for (int i = 0; i < this->project->mapLayoutsTable.length(); i++) { - // QString layoutId = project->mapLayoutsTable.value(i); QStandardItem *layoutItem = createLayoutItem(layoutId); this->root->appendRow(layoutItem); @@ -315,8 +270,6 @@ void LayoutTreeModel::initialize() { this->layoutItems[layoutId]->appendRow(map); } } - - // // project->readMapLayoutName } QStandardItem *LayoutTreeModel::getItem(const QModelIndex &index) const { @@ -364,12 +317,7 @@ QVariant LayoutTreeModel::data(const QModelIndex &index, int role) const { } return QVariant(); - - // check if map or group - // if map, check if edited or open - //return QIcon(":/icons/porymap-icon-2.ico"); } return QStandardItemModel::data(index, role); } - From f7f06dab290ca08b38143f6d4a837d8c066e0fe1 Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 7 Feb 2023 13:04:52 -0500 Subject: [PATCH 11/70] fix change dimensions for layouts --- include/core/maplayout.h | 4 ++- include/mainwindow.h | 2 ++ resources/icons/minimap.ico | Bin 0 -> 1150 bytes resources/images.qrc | 1 + src/editor.cpp | 2 ++ src/mainwindow.cpp | 47 ++++++++++++++++++++++++------------ src/project.cpp | 26 ++++++++++++-------- 7 files changed, 55 insertions(+), 27 deletions(-) create mode 100644 resources/icons/minimap.ico diff --git a/include/core/maplayout.h b/include/core/maplayout.h index 7d4eb500e..eabe2c8ef 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -21,6 +21,8 @@ class Layout : public QObject { static QString layoutConstantFromName(QString mapName); + bool loaded = false; + /// !TODO /* NEW */ QList maps; @@ -119,7 +121,7 @@ class Layout : public QObject { signals: void layoutChanged(Layout *layout); - void modified(); + //void modified(); void layoutDimensionsChanged(const QSize &size); void needsRedrawing(); }; diff --git a/include/mainwindow.h b/include/mainwindow.h index 7bc47ff23..52773f5ef 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -182,6 +182,7 @@ private slots: void onLoadMapRequested(QString, QString); void onMapChanged(Map *map); void onMapNeedsRedrawing(); + void onLayoutNeedsRedrawing(); void onTilesetsSaved(QString, QString); void onWildMonDataChanged(); void openNewMapPopupWindow(); @@ -362,6 +363,7 @@ private slots: bool setMap(QString, bool scroll = false); void unsetMap(); void redrawMapScene(); + void redrawLayoutScene(); void refreshMapScene(); bool loadDataStructures(); bool loadProjectCombos(); diff --git a/resources/icons/minimap.ico b/resources/icons/minimap.ico new file mode 100644 index 0000000000000000000000000000000000000000..b9315712a636badcda8c8912a4fcc55123109276 GIT binary patch literal 1150 zcmbu9Ee^s!5QT??15}}r903W3AZQ$dTCfNVf*?5q1Vt(kwe=uzBv>?dnYZ+jrEGsF zZC-cscD|XmlUAgmXAp>9+cIv7v_zz%QcIneuZ#B>_WDPasVU1o?l)6M?3u@2E|H1j z-Iw5lDdWTa%s|LJj0Uz2;xI~T@u&eF_f)0-_B^-!lhxGVp0P5n!h=B#a$Mn6;gM6M zviDcSX8Zf*L=U-)-Ie_@BhHjPIV1RB=;Ix*9{KKa_>qJCaI$&lF}A+W9yQ^)e7Lw8 ruQcDzF|&^vicons/sort_map.ico icons/sort_number.ico icons/tall_grass.ico + icons/minimap.ico icons/viewsprites.ico icons/application_form_edit.ico icons/connections.ico diff --git a/src/editor.cpp b/src/editor.cpp index 18915bdc7..8703aa240 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1151,6 +1151,8 @@ bool Editor::setLayout(QString layoutId) { return false; } + // !TODO: editGroup addStack + map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight())); connect(this->layout, &Layout::layoutDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 06387fa10..b182782fb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -203,7 +203,7 @@ void MainWindow::initCustomUI() { // Set up the tab bar while (ui->mainTabBar->count()) ui->mainTabBar->removeTab(0); ui->mainTabBar->addTab("Map"); - ui->mainTabBar->setTabIcon(0, QIcon(QStringLiteral(":/icons/map.ico"))); + ui->mainTabBar->setTabIcon(0, QIcon(QStringLiteral(":/icons/minimap.ico"))); ui->mainTabBar->addTab("Events"); ui->mainTabBar->setTabIcon(1, QIcon(QStringLiteral(":/icons/viewsprites.ico"))); ui->mainTabBar->addTab("Header"); @@ -714,6 +714,9 @@ bool MainWindow::setMap(QString map_name, bool scroll) { connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); + connect(editor->layout, &Layout::layoutChanged, [this]() { onMapChanged(nullptr); }); + connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing); + setRecentMap(map_name); updateMapList(); @@ -747,8 +750,9 @@ bool MainWindow::setLayout(QString layoutId) { updateMapList(); - // connect(editor->map, &Map::mapChanged, this, &MainWindow::onMapChanged); - // connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); + // !TODO: make sure these connections are not duplicated / cleared later + connect(editor->layout, &Layout::layoutChanged, [this]() { onMapChanged(nullptr); }); + connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing); // connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); // displayMapProperties @@ -765,16 +769,21 @@ bool MainWindow::setLayout(QString layoutId) { return true; } -void MainWindow::redrawMapScene() -{ +void MainWindow::redrawMapScene() { if (!editor->displayMap()) return; this->refreshMapScene(); } -void MainWindow::refreshMapScene() -{ +void MainWindow::redrawLayoutScene() { + if (!editor->displayLayout()) + return; + + this->refreshMapScene(); +} + +void MainWindow::refreshMapScene() { on_mainTabBar_tabBarClicked(ui->mainTabBar->currentIndex()); ui->graphicsView_Map->setScene(editor->scene); @@ -2519,6 +2528,11 @@ void MainWindow::onMapNeedsRedrawing() { redrawMapScene(); } +void MainWindow::onLayoutNeedsRedrawing() { + qDebug() << "MainWindow::onLayoutNeedsRedrawing"; + redrawLayoutScene(); +} + void MainWindow::onMapCacheCleared() { editor->map = nullptr; } @@ -2710,8 +2724,9 @@ void MainWindow::on_comboBox_SecondaryTileset_currentTextChanged(const QString & } } -void MainWindow::on_pushButton_ChangeDimensions_clicked() -{ +void MainWindow::on_pushButton_ChangeDimensions_clicked() { + if (!editor || !editor->layout) return; + QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint); dialog.setWindowTitle("Change Map Dimensions"); dialog.setWindowModality(Qt::NonModal); @@ -2730,10 +2745,10 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() heightSpinBox->setMaximum(editor->project->getMaxMapHeight()); bwidthSpinBox->setMaximum(MAX_BORDER_WIDTH); bheightSpinBox->setMaximum(MAX_BORDER_HEIGHT); - widthSpinBox->setValue(editor->map->getWidth()); - heightSpinBox->setValue(editor->map->getHeight()); - bwidthSpinBox->setValue(editor->map->getBorderWidth()); - bheightSpinBox->setValue(editor->map->getBorderHeight()); + widthSpinBox->setValue(editor->layout->getWidth()); + heightSpinBox->setValue(editor->layout->getHeight()); + bwidthSpinBox->setValue(editor->layout->getBorderWidth()); + bheightSpinBox->setValue(editor->layout->getBorderHeight()); if (projectConfig.getUseCustomBorderSize()) { form.addRow(new QLabel("Map Width"), widthSpinBox); form.addRow(new QLabel("Map Height"), heightSpinBox); @@ -2761,8 +2776,8 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() dialog.accept(); } else { QString errorText = QString("Error: The specified width and height are too large.\n" - "The maximum map width and height is the following: (width + 15) * (height + 14) <= %1\n" - "The specified map width and height was: (%2 + 15) * (%3 + 14) = %4") + "The maximum layout width and height is the following: (width + 15) * (height + 14) <= %1\n" + "The specified layout width and height was: (%2 + 15) * (%3 + 14) = %4") .arg(maxMetatiles) .arg(widthSpinBox->value()) .arg(heightSpinBox->value()) @@ -2786,7 +2801,7 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() if (oldMapDimensions != newMapDimensions || oldBorderDimensions != newBorderDimensions) { layout->setDimensions(newMapDimensions.width(), newMapDimensions.height(), true, true); layout->setBorderDimensions(newBorderDimensions.width(), newBorderDimensions.height(), true, true); - editor->map->editHistory.push(new ResizeMap(layout, + editor->layout->editHistory.push(new ResizeMap(layout, oldMapDimensions, newMapDimensions, oldMetatiles, layout->blockdata, oldBorderDimensions, newBorderDimensions, diff --git a/src/project.cpp b/src/project.cpp index c5cbe2e50..c203944ca 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -380,18 +380,24 @@ QString Project::readMapLocation(QString map_name) { } bool Project::loadLayout(MapLayout *layout) { - // Force these to run even if one fails - bool loadedTilesets = loadLayoutTilesets(layout); - bool loadedBlockdata = loadBlockdata(layout); - bool loadedBorder = loadLayoutBorder(layout); - - return loadedTilesets - && loadedBlockdata - && loadedBorder; + // !TODO: make sure this doesn't break anything, maybe do something better. new layouts work too? + if (!layout->loaded) { + // Force these to run even if one fails + bool loadedTilesets = loadLayoutTilesets(layout); + bool loadedBlockdata = loadBlockdata(layout); + bool loadedBorder = loadLayoutBorder(layout); + + if (loadedTilesets && loadedBlockdata && loadedBorder) { + layout->loaded = true; + return true; + } else { + return false; + } + } + return true; } Layout *Project::loadLayout(QString layoutId) { - // if (mapLayouts.contains(layoutId)) { Layout *layout = mapLayouts[layoutId]; if (loadLayout(layout)) { @@ -415,7 +421,7 @@ bool Project::loadMapLayout(Map* map) { return false; } - if (map->hasUnsavedChanges()) { + if (map->hasUnsavedChanges() /* || map->layout->hasUnsavedChanges() */) { return true; } else { return loadLayout(map->layout); From 72eb8f873f0cce7af72b74a8fc6ddb436f313d99 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 8 Feb 2023 09:31:39 -0500 Subject: [PATCH 12/70] create dynamic map tab icon --- include/core/maplayout.h | 8 +-- include/editor.h | 5 +- include/mainwindow.h | 1 - include/project.h | 4 +- resources/icons/minimap.ico | Bin 1150 -> 1406 bytes src/core/maplayout.cpp | 49 ++++++++++++++ src/core/mapparser.cpp | 4 +- src/mainwindow.cpp | 125 ++++-------------------------------- src/project.cpp | 33 ++++++---- src/ui/newmappopup.cpp | 12 ++-- 10 files changed, 99 insertions(+), 142 deletions(-) diff --git a/include/core/maplayout.h b/include/core/maplayout.h index eabe2c8ef..1e809c134 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -19,14 +19,12 @@ class Layout : public QObject { public: Layout() {} + void copyAttributesFrom(Layout *other); + static QString layoutConstantFromName(QString mapName); bool loaded = false; - /// !TODO - /* NEW */ - QList maps; - QString id; QString name; @@ -126,6 +124,4 @@ class Layout : public QObject { void needsRedrawing(); }; -using MapLayout = Layout; - #endif // MAPLAYOUT_H diff --git a/include/editor.h b/include/editor.h index 29709df8e..d6d973b5c 100644 --- a/include/editor.h +++ b/include/editor.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "mapconnection.h" #include "metatileselector.h" @@ -45,8 +46,8 @@ class Editor : public QObject QObject *parent = nullptr; Project *project = nullptr; - Map *map = nullptr; - Layout *layout = nullptr; /* NEW */ + QPointer map = nullptr; // !TODO: since removed onMapCacheCleared, make sure this works as intended + QPointer layout = nullptr; /* NEW */ QUndoGroup editGroup; // Manages the undo history for each map diff --git a/include/mainwindow.h b/include/mainwindow.h index 52773f5ef..522bf0f27 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -187,7 +187,6 @@ private slots: void onWildMonDataChanged(); void openNewMapPopupWindow(); void onNewMapCreated(); - void onMapCacheCleared(); void importMapFromAdvanceMap1_92(); void onMapRulerStatusChanged(const QString &); void applyUserShortcuts(); diff --git a/include/project.h b/include/project.h index ddffe49b8..9a58905f7 100644 --- a/include/project.h +++ b/include/project.h @@ -58,7 +58,7 @@ class Project : public QObject QString layoutsLabel; QMap layoutIdsToNames; QMap mapLayouts; - QMap mapLayoutsMaster; +// QMap mapLayoutsMaster; QMap mapSecToMapHoverName; QMap mapSectionNameToValue; QMap mapSectionValueToName; @@ -95,6 +95,7 @@ class Project : public QObject void clearMapCache(); void clearTilesetCache(); + void clearLayoutsTable(); struct DataQualifiers { @@ -265,7 +266,6 @@ class Project : public QObject signals: void reloadProject(); void uncheckMonitorFilesAction(); - void mapCacheCleared(); void disableWildEncountersUI(); }; diff --git a/resources/icons/minimap.ico b/resources/icons/minimap.ico index b9315712a636badcda8c8912a4fcc55123109276..548c7c8fc0710ca5559d887600d8e82f4d7030a8 100644 GIT binary patch literal 1406 zcmeH@*;i9n6vjW=YOy1o>|h7&Xa}{mGp$pt8Z|8fmU+;COa>$&KtQGp1TbWPFx(I_ zk%Zg?LQLRZZf`;vB9KTCmsssvAKE{phramKmp*r&_1oXs!#Zo94J471k^j|$Q=?Q zcUTB{s~Pfk3(is5NT+fjSByev$%R~HN18Pc(vf`BS@O}OH6hEH2Z2L`GmaAEJByGv zR)E~GLX_IeATc*0-&Kghu?rBpvrysAf!JCLu_qhq{$Wr?3I*e(NFT36k+%d_tnJ7c zuR;f1fMU8FBHtxs(A8+A$=m)iH2Fjr942~r!EK4%ysOoEeT-1FW$|xE5Q$Ej1u;Lk`b! zBkU{9@UF-Sq;FA6v>7yEGNy(*;=mlKx#P`P4$Z+6Z-H}F0dKqw?s+RraSaycDU980 z107d^PAJeDVc{q0ODJJpQ-GUykXkn;ZYtr6U&G|89`2Y8fi(@G3sY;|2omNO-I)5d z8{YLEqFT6@y`cCF1lM&4Z;=?mG|}mGJ^AM>B5^B1w@Ch$9*G+?LK_BzH~KL{U~dm# zbv1xQd=i29Eaul;;OFzk9_w57{|L#DP@V`CSK+5BflwKW}Wq%%2G+lo5iKq9!^>K+*&odE=Omd~*%e^}u z+a~HL91rmR*76@R-cH_gtV`OQdz|ALL*`fSy|F7btzLTa>u)BajPc#)p8W7&(x)LQpp&ZzeZmD(DtMQZ@$0pi=A3#QvAZ_`#yT-gXdp;`L&l` S$#S`W+S1+6KG?*6yZsI7c)9@q literal 1150 zcmbu9Ee^s!5QT??15}}r903W3AZQ$dTCfNVf*?5q1Vt(kwe=uzBv>?dnYZ+jrEGsF zZC-cscD|XmlUAgmXAp>9+cIv7v_zz%QcIneuZ#B>_WDPasVU1o?l)6M?3u@2E|H1j z-Iw5lDdWTa%s|LJj0Uz2;xI~T@u&eF_f)0-_B^-!lhxGVp0P5n!h=B#a$Mn6;gM6M zviDcSX8Zf*L=U-)-Ie_@BhHjPIV1RB=;Ix*9{KKa_>qJCaI$&lF}A+W9yQ^)e7Lw8 ruQcDzF|&^v metatileLayerOrder; + // QList metatileLayerOpacity; + + // LayoutPixmapItem *layoutItem = nullptr; + // CollisionPixmapItem *collisionItem = nullptr; + // BorderMetatilesPixmapItem *borderItem = nullptr; + + // QUndoStack editHistory; +void Layout::copyAttributesFrom(Layout *other) { + // +} + QString Layout::layoutConstantFromName(QString mapName) { // Transform map names of the form 'GraniteCave_B1F` into layout constants like 'LAYOUT_GRANITE_CAVE_B1F'. static const QRegularExpression caseChange("([a-z])([A-Z])"); diff --git a/src/core/mapparser.cpp b/src/core/mapparser.cpp index 986c2c242..3d4258bd8 100644 --- a/src/core/mapparser.cpp +++ b/src/core/mapparser.cpp @@ -7,7 +7,7 @@ MapParser::MapParser() { } -MapLayout *MapParser::parse(QString filepath, bool *error, Project *project) +Layout *MapParser::parse(QString filepath, bool *error, Project *project) { QFile file(filepath); if (!file.open(QIODevice::ReadOnly)) { @@ -69,7 +69,7 @@ MapLayout *MapParser::parse(QString filepath, bool *error, Project *project) } } - MapLayout *mapLayout = new MapLayout(); + Layout *mapLayout = new Layout(); mapLayout->width = mapWidth; mapLayout->height = mapHeight; mapLayout->border_width = (borderWidth == 0) ? DEFAULT_BORDER_WIDTH : borderWidth; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b182782fb..25e73e732 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -377,6 +377,15 @@ void MainWindow::showWindowTitle() { .arg(editor->project->getProjectTitle()) ); } + if (editor && editor->layout) { + // // QPixmap pixmap = editor->layout ? editor->layout->render(true) : QPixmap(); + QPixmap pixmap = editor->layout ? editor->layout->render(false) : QPixmap(); + if (!pixmap.isNull()) { + ui->mainTabBar->setTabIcon(0, QIcon(pixmap.scaled(16, 16))); + } else { + ui->mainTabBar->setTabIcon(0, QIcon(QStringLiteral(":/icons/map.ico"))); + } + } } void MainWindow::markMapEdited() { @@ -449,6 +458,7 @@ void MainWindow::applyMapListFilter(QString filterText) { } /// !TODO + // ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(map_name)), false); // ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), true); // ui->mapList->scrollTo(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), QAbstractItemView::PositionAtCenter); } @@ -541,7 +551,6 @@ bool MainWindow::openProject(QString dir) { editor->closeProject(); editor->project = new Project(this); QObject::connect(editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered); - QObject::connect(editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared); QObject::connect(editor->project, &Project::disableWildEncountersUI, [this]() { this->setWildEncountersUIEnabled(false); }); QObject::connect(editor->project, &Project::uncheckMonitorFilesAction, [this]() { porymapConfig.setMonitorFiles(false); @@ -555,6 +564,7 @@ bool MainWindow::openProject(QString dir) { } else { QString open_map = editor->map->name; editor->project->fileWatcher.removePaths(editor->project->fileWatcher.files()); + editor->project->clearLayoutsTable(); editor->project->clearMapCache(); editor->project->clearTilesetCache(); success = loadDataStructures() && populateMapList() && setMap(open_map, true); @@ -701,6 +711,8 @@ bool MainWindow::setMap(QString map_name, bool scroll) { this->ui->mainTabBar->setTabEnabled(3, true); this->ui->mainTabBar->setTabEnabled(4, true); + this->ui->comboBox_LayoutSelector->setEnabled(true); + refreshMapScene(); displayMapProperties(); @@ -1129,111 +1141,6 @@ void MainWindow::scrollTreeView(QString itemName) { } void MainWindow::sortMapList() { - // Project *project = editor->project; - - // QIcon mapFolderIcon; - // mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); - // mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); - - // QIcon folderIcon; - // folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off); - // //folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On); - - // ui->mapList->setUpdatesEnabled(false); - // mapListModel->clear(); - // mapGroupItemsList->clear(); - // QStandardItem *root = mapListModel->invisibleRootItem(); - - // switch (mapSortOrder) - // { - // case MapSortOrder::SortByGroup: - // for (int i = 0; i < project->groupNames.length(); i++) { - // QString group_name = project->groupNames.value(i); - // QStandardItem *group = new QStandardItem; - // group->setText(group_name); - // group->setIcon(mapFolderIcon); - // group->setEditable(false); - // group->setData(group_name, Qt::UserRole); - // group->setData("map_group", MapListUserRoles::TypeRole); - // group->setData(i, MapListUserRoles::GroupRole); - // root->appendRow(group); - // mapGroupItemsList->append(group); - // QStringList names = project->groupedMapNames.value(i); - // for (int j = 0; j < names.length(); j++) { - // QString map_name = names.value(j); - // QStandardItem *map = createMapItem(map_name, i, j); - // group->appendRow(map); - // mapListIndexes.insert(map_name, map->index()); - // } - // } - // break; - // case MapSortOrder::SortByArea: - // { - // QMap mapsecToGroupNum; - // for (int i = 0; i < project->mapSectionNameToValue.size(); i++) { - // QString mapsec_name = project->mapSectionValueToName.value(i); - // QStandardItem *mapsec = new QStandardItem; - // mapsec->setText(mapsec_name); - // mapsec->setIcon(folderIcon); - // mapsec->setEditable(false); - // mapsec->setData(mapsec_name, Qt::UserRole); - // mapsec->setData("map_sec", MapListUserRoles::TypeRole); - // mapsec->setData(i, MapListUserRoles::GroupRole); - // root->appendRow(mapsec); - // mapGroupItemsList->append(mapsec); - // mapsecToGroupNum.insert(mapsec_name, i); - // } - // for (int i = 0; i < project->groupNames.length(); i++) { - // QStringList names = project->groupedMapNames.value(i); - // for (int j = 0; j < names.length(); j++) { - // QString map_name = names.value(j); - // QStandardItem *map = createMapItem(map_name, i, j); - // QString location = project->readMapLocation(map_name); - // QStandardItem *mapsecItem = mapGroupItemsList->at(mapsecToGroupNum[location]); - // mapsecItem->setIcon(mapFolderIcon); - // mapsecItem->appendRow(map); - // mapListIndexes.insert(map_name, map->index()); - // } - // } - // break; - // } - // case MapSortOrder::SortByLayout: - // { - // QMap layoutIndices; - // for (int i = 0; i < project->mapLayoutsTable.length(); i++) { - // QString layoutId = project->mapLayoutsTable.value(i); - // MapLayout *layout = project->mapLayouts.value(layoutId); - // QStandardItem *layoutItem = new QStandardItem; - // layoutItem->setText(layout->name); - // layoutItem->setIcon(folderIcon); - // layoutItem->setEditable(false); - // layoutItem->setData(layout->name, Qt::UserRole); - // layoutItem->setData("map_layout", MapListUserRoles::TypeRole); - // layoutItem->setData(layout->id, MapListUserRoles::TypeRole2); - // layoutItem->setData(i, MapListUserRoles::GroupRole); - // root->appendRow(layoutItem); - // mapGroupItemsList->append(layoutItem); - // layoutIndices[layoutId] = i; - // } - // for (int i = 0; i < project->groupNames.length(); i++) { - // QStringList names = project->groupedMapNames.value(i); - // for (int j = 0; j < names.length(); j++) { - // QString map_name = names.value(j); - // QStandardItem *map = createMapItem(map_name, i, j); - // QString layoutId = project->readMapLayoutId(map_name); - // QStandardItem *layoutItem = mapGroupItemsList->at(layoutIndices.value(layoutId)); - // layoutItem->setIcon(mapFolderIcon); - // layoutItem->appendRow(map); - // mapListIndexes.insert(map_name, map->index()); - // } - // } - // break; - // } - // } - - // ui->mapList->setUpdatesEnabled(true); - // ui->mapList->repaint(); - // updateMapList(); } void MainWindow::onOpenMapListContextMenu(const QPoint &point) { @@ -2533,10 +2440,6 @@ void MainWindow::onLayoutNeedsRedrawing() { redrawLayoutScene(); } -void MainWindow::onMapCacheCleared() { - editor->map = nullptr; -} - void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) { // If saved tilesets are currently in-use, update them and redraw // Otherwise overwrite the cache for the saved tileset @@ -2612,7 +2515,7 @@ void MainWindow::importMapFromAdvanceMap1_92() this->editor->project->setImportExportPath(filepath); MapParser parser; bool error = false; - MapLayout *mapLayout = parser.parse(filepath, &error, editor->project); + Layout *mapLayout = parser.parse(filepath, &error, editor->project); if (error) { QMessageBox msgBox(this); msgBox.setText("Failed to import map from Advance Map 1.92 .map file."); diff --git a/src/project.cpp b/src/project.cpp index c203944ca..f4672fabc 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -45,6 +45,7 @@ Project::Project(QWidget *parent) : Project::~Project() { + clearLayoutsTable(); clearMapCache(); clearTilesetCache(); } @@ -108,7 +109,6 @@ void Project::clearMapCache() { delete map; } mapCache.clear(); - emit mapCacheCleared(); } void Project::clearTilesetCache() { @@ -119,6 +119,17 @@ void Project::clearTilesetCache() { tilesetCache.clear(); } +void Project::clearLayoutsTable() { + // clearMapLayouts + // QMap mapLayouts; + // QMap mapLayoutsMaster; + for (Layout *layout : mapLayouts.values()) { + if (layout) + delete layout; + } + mapLayouts.clear(); +} + Map* Project::loadMap(QString map_name) { Map *map; if (mapCache.contains(map_name)) { @@ -379,7 +390,7 @@ QString Project::readMapLocation(QString map_name) { return ParseUtil::jsonToQString(mapObj["region_map_section"]); } -bool Project::loadLayout(MapLayout *layout) { +bool Project::loadLayout(Layout *layout) { // !TODO: make sure this doesn't break anything, maybe do something better. new layouts work too? if (!layout->loaded) { // Force these to run even if one fails @@ -476,7 +487,7 @@ bool Project::readMapLayouts() { logError(QString("Layout %1 is missing field(s) in %2.").arg(i).arg(layoutsFilepath)); return false; } - MapLayout *layout = new MapLayout(); + Layout *layout = new Layout(); layout->id = ParseUtil::jsonToQString(layoutObj["id"]); if (layout->id.isEmpty()) { logError(QString("Missing 'id' value on layout %1 in %2").arg(i).arg(layoutsFilepath)); @@ -557,8 +568,6 @@ bool Project::readMapLayouts() { } // Deep copy - mapLayoutsMaster = mapLayouts; - mapLayoutsMaster.detach(); mapLayoutsTableMaster = mapLayoutsTable; mapLayoutsTableMaster.detach(); return true; @@ -578,7 +587,7 @@ void Project::saveMapLayouts() { bool useCustomBorderSize = projectConfig.getUseCustomBorderSize(); OrderedJson::array layoutsArr; for (QString layoutId : mapLayoutsTableMaster) { - MapLayout *layout = mapLayouts.value(layoutId); + Layout *layout = mapLayouts.value(layoutId); OrderedJson::object layoutObj; layoutObj["id"] = layout->id; layoutObj["name"] = layout->name; @@ -1046,7 +1055,7 @@ void Project::saveTilesetPalettes(Tileset *tileset) { } } -bool Project::loadLayoutTilesets(MapLayout *layout) { +bool Project::loadLayoutTilesets(Layout *layout) { layout->tileset_primary = getTileset(layout->tileset_primary_label); if (!layout->tileset_primary) { QString defaultTileset = this->getDefaultPrimaryTilesetLabel(); @@ -1114,7 +1123,7 @@ Tileset* Project::loadTileset(QString label, Tileset *tileset) { return tileset; } -bool Project::loadBlockdata(MapLayout *layout) { +bool Project::loadBlockdata(Layout *layout) { QString path = QString("%1/%2").arg(root).arg(layout->blockdata_path); layout->blockdata = readBlockdata(path); layout->lastCommitBlocks.blocks = layout->blockdata; @@ -1143,7 +1152,7 @@ void Project::setNewMapBlockdata(Map *map) { map->layout->lastCommitBlocks.mapDimensions = QSize(width, height); } -bool Project::loadLayoutBorder(MapLayout *layout) { +bool Project::loadLayoutBorder(Layout *layout) { QString path = QString("%1/%2").arg(root).arg(layout->border_path); layout->border = readBlockdata(path); layout->lastCommitBlocks.border = layout->border; @@ -1361,10 +1370,10 @@ void Project::updateMapLayout(Map* map) { mapLayoutsTableMaster.append(map->layoutId); } - // !TODO + // !TODO: why is[was] this a deep copy?? // Deep copy - // MapLayout *layout = mapLayouts.value(map->layoutId); - // MapLayout *newLayout = new MapLayout(); + // Layout *layout = mapLayouts.value(map->layoutId); + // Layout *newLayout = new Layout(); // *newLayout = *layout; // mapLayoutsMaster.insert(map->layoutId, newLayout); } diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index eb3eae45f..597d53d1a 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -110,12 +110,12 @@ void NewMapPopup::init(MapSortOrder type, QVariant data) { } // Creating new map from AdvanceMap import -void NewMapPopup::init(MapLayout *mapLayout) { +void NewMapPopup::init(Layout *mapLayout) { this->importedMap = true; useLayoutSettings(mapLayout); this->map = new Map(); - this->map->layout = new MapLayout(); + this->map->layout = new Layout(); this->map->layout->blockdata = mapLayout->blockdata; if (!mapLayout->border.isEmpty()) { @@ -203,7 +203,7 @@ void NewMapPopup::saveSettings() { settings.floorNumber = ui->spinBox_NewMap_Floor_Number->value(); } -void NewMapPopup::useLayoutSettings(MapLayout *layout) { +void NewMapPopup::useLayoutSettings(Layout *layout) { if (!layout) return; settings.width = layout->width; settings.height = layout->height; @@ -241,7 +241,7 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() { return; } Map *newMap = new Map; - MapLayout *layout; + Layout *layout; // If map name is not unique, use default value. Also use only valid characters. // After stripping invalid characters, strip any leading digits. @@ -266,8 +266,8 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() { layout = this->project->mapLayouts.value(this->layoutId); newMap->needsLayoutDir = false; } else { - layout = new MapLayout; - layout->id = MapLayout::layoutConstantFromName(newMapName); + layout = new Layout; + layout->id = Layout::layoutConstantFromName(newMapName); layout->name = QString("%1_Layout").arg(newMap->name); layout->width = this->ui->spinBox_NewMap_Width->value(); layout->height = this->ui->spinBox_NewMap_Height->value(); From f8c7ada585c2cbeea2850a0be637a624b41a73b3 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 8 Feb 2023 11:48:42 -0500 Subject: [PATCH 13/70] fix layout undo history --- include/core/maplayout.h | 2 ++ include/project.h | 2 +- src/core/maplayout.cpp | 4 ++++ src/editor.cpp | 18 ++++++++++++++++++ src/mainwindow.cpp | 27 +++++++++++++++++++++++---- src/project.cpp | 2 +- 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/include/core/maplayout.h b/include/core/maplayout.h index 1e809c134..968b8960c 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -109,6 +109,8 @@ class Layout : public QObject { // QPixmap renderConnection(MapConnection, Layout *); QPixmap renderBorder(bool ignoreCache = false); + QPixmap getLayoutItemPixmap(); + void setLayoutItem(LayoutPixmapItem *item) { layoutItem = item; } void setCollisionItem(CollisionPixmapItem *item) { collisionItem = item; } void setBorderItem(BorderMetatilesPixmapItem *item) { borderItem = item; } diff --git a/include/project.h b/include/project.h index 9a58905f7..24f14611e 100644 --- a/include/project.h +++ b/include/project.h @@ -34,7 +34,7 @@ class Project : public QObject { Q_OBJECT public: - Project(QWidget *parent = nullptr); + Project(QObject *parent = nullptr); ~Project(); Project(const Project &) = delete; diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 1923cf3dd..4fd05b4f0 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -438,6 +438,10 @@ QPixmap Layout::renderBorder(bool ignoreCache) { return this->border_pixmap; } +QPixmap Layout::getLayoutItemPixmap() { + return this->layoutItem ? this->layoutItem->pixmap() : QPixmap(); +} + bool Layout::hasUnsavedChanges() { return !this->editHistory.isClean(); } diff --git a/src/editor.cpp b/src/editor.cpp index 8703aa240..7d6d2780d 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -100,6 +100,10 @@ void Editor::setEditingMap() { this->cursorMapTileRect->stopSingleTileMode(); this->cursorMapTileRect->setActive(true); + if (this->layout) { + this->editGroup.setActiveStack(&this->layout->editHistory); + } + setMapEditingButtonsEnabled(true); } @@ -128,6 +132,10 @@ void Editor::setEditingCollision() { this->cursorMapTileRect->setSingleTileMode(); this->cursorMapTileRect->setActive(true); + if (this->layout) { + this->editGroup.setActiveStack(&this->layout->editHistory); + } + setMapEditingButtonsEnabled(true); } @@ -152,6 +160,10 @@ void Editor::setEditingObjects() { this->cursorMapTileRect->setSingleTileMode(); this->cursorMapTileRect->setActive(false); + if (this->map) { + this->editGroup.setActiveStack(&this->map->editHistory); + } + setMapEditingButtonsEnabled(false); } @@ -184,6 +196,10 @@ void Editor::setEditingConnections() { setConnectionsEditable(true); this->cursorMapTileRect->setSingleTileMode(); this->cursorMapTileRect->setActive(false); + + if (this->map) { + this->editGroup.setActiveStack(&this->map->editHistory); + } } void Editor::setEditingEncounters() { @@ -1153,6 +1169,8 @@ bool Editor::setLayout(QString layoutId) { // !TODO: editGroup addStack + editGroup.addStack(&layout->editHistory); + map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight())); connect(this->layout, &Layout::layoutDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 25e73e732..b62aa3390 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -221,6 +221,14 @@ void MainWindow::initExtraSignals() { connect(ui->mapList, &QTreeView::customContextMenuRequested, this, &MainWindow::onOpenMapListContextMenu); + ui->areaList->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->areaList, &QTreeView::customContextMenuRequested, + this, &MainWindow::onOpenMapListContextMenu); + + ui->layoutList->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->layoutList, &QTreeView::customContextMenuRequested, + this, &MainWindow::onOpenMapListContextMenu); + // other signals connect(ui->newEventToolButton, &NewEventToolButton::newEventAdded, this, &MainWindow::addNewEvent); connect(ui->tabWidget_EventType, &QTabWidget::currentChanged, this, &MainWindow::eventTabChanged); @@ -296,7 +304,7 @@ void MainWindow::initEditor() { ui->menuEdit->addAction(showHistory); // Toggle an asterisk in the window title when the undo state is changed - connect(&editor->editGroup, &QUndoGroup::cleanChanged, this, &MainWindow::showWindowTitle); + connect(&editor->editGroup, &QUndoGroup::indexChanged, this, &MainWindow::showWindowTitle); // selecting objects from the spinners connect(this->ui->spinner_ObjectID, QOverload::of(&QSpinBox::valueChanged), [this](int value) { @@ -378,8 +386,8 @@ void MainWindow::showWindowTitle() { ); } if (editor && editor->layout) { - // // QPixmap pixmap = editor->layout ? editor->layout->render(true) : QPixmap(); - QPixmap pixmap = editor->layout ? editor->layout->render(false) : QPixmap(); + //QPixmap pixmap = editor->layout ? editor->layout->render(false) : QPixmap(); + QPixmap pixmap = editor->layout->pixmap;//getLayoutItemPixmap(); if (!pixmap.isNull()) { ui->mainTabBar->setTabIcon(0, QIcon(pixmap.scaled(16, 16))); } else { @@ -549,7 +557,7 @@ bool MainWindow::openProject(QString dir) { bool already_open = isProjectOpen() && (editor->project->root == dir); if (!already_open) { editor->closeProject(); - editor->project = new Project(this); + editor->project = new Project(editor); QObject::connect(editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered); QObject::connect(editor->project, &Project::disableWildEncountersUI, [this]() { this->setWildEncountersUIEnabled(false); }); QObject::connect(editor->project, &Project::uncheckMonitorFilesAction, [this]() { @@ -931,6 +939,7 @@ void MainWindow::on_comboBox_LayoutSelector_currentTextChanged(const QString &te // !TODO: method to setMapLayout instead of having to do whole setMap thing, // also edit history and bug fixes setMap(editor->map->name); + markMapEdited(); } } } @@ -1150,6 +1159,16 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) { // return; // } + switch (ui->mapListContainer->currentIndex()) { + // + case MapListTab::Groups: + break; + case MapListTab::Areas: + break; + case MapListTab::Layouts: + break; + } + // QStandardItem *selectedItem = mapListModel->itemFromIndex(index); // QVariant itemType = selectedItem->data(MapListUserRoles::TypeRole); // if (!itemType.isValid()) { diff --git a/src/project.cpp b/src/project.cpp index f4672fabc..15122fac0 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -35,7 +35,7 @@ int Project::max_map_data_size = 10240; // 0x2800 int Project::default_map_size = 20; int Project::max_object_events = 64; -Project::Project(QWidget *parent) : +Project::Project(QObject *parent) : QObject(parent), eventScriptLabelModel(this), eventScriptLabelCompleter(this) From a4fdb0de6410e3cff659bdfb1b8598be29a6013c Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 8 Feb 2023 17:08:42 -0500 Subject: [PATCH 14/70] fix new map popup window to allow layout selection --- forms/newmappopup.ui | 154 +++++++++++++++++++++++++++++++-------- include/ui/newmappopup.h | 3 + src/mainwindow.cpp | 101 +++++++++++++------------ src/ui/maplistmodels.cpp | 1 + src/ui/newmappopup.cpp | 59 +++++++++++++-- 5 files changed, 233 insertions(+), 85 deletions(-) diff --git a/forms/newmappopup.ui b/forms/newmappopup.ui index b102b1ccc..3a83073f8 100644 --- a/forms/newmappopup.ui +++ b/forms/newmappopup.ui @@ -7,7 +7,7 @@ 0 0 410 - 621 + 687 @@ -73,14 +73,14 @@ - + Map Width - + <html><head/><body><p>Width (in blocks) of the new map.</p></body></html> @@ -90,14 +90,14 @@ - + Map Height - + <html><head/><body><p>Height (in blocks) of the new map.</p></body></html> @@ -107,14 +107,14 @@ - + Border Width - + <html><head/><body><p>Width (in blocks) of the new map's border.</p></body></html> @@ -124,14 +124,14 @@ - + Border Height - + <html><head/><body><p>Height (in blocks) of the new map's border.</p></body></html> @@ -141,14 +141,14 @@ - + Primary Tileset - + <html><head/><body><p>The primary tileset for the new map.</p></body></html> @@ -158,14 +158,14 @@ - + Secondary Tileset - + <html><head/><body><p>The secondary tileset for the new map.</p></body></html> @@ -175,14 +175,14 @@ - + Type - + <html><head/><body><p>The map type is a general attribute, which is used for many different things. For example. it determines whether biking or running is allowed.</p></body></html> @@ -192,14 +192,14 @@ - + Location - + <html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is displayed when the player enters it.</p></body></html> @@ -209,14 +209,14 @@ - + Song - + <html><head/><body><p>The default background music for this map.</p></body></html> @@ -226,14 +226,14 @@ - + Can Fly To - + <html><head/><body><p>Whether to add a heal location to the new map.</p></body></html> @@ -243,14 +243,14 @@ - + Show Location Name - + <html><head/><body><p>Whether or not to display the location name when the player enters the map.</p></body></html> @@ -260,14 +260,14 @@ - + Allow Running - + <html><head/><body><p>Allows the player to use Running Shoes</p></body></html> @@ -277,14 +277,14 @@ - + Allow Biking - + <html><head/><body><p>Allows the player to use a Bike</p></body></html> @@ -294,14 +294,14 @@ - + Allow Dig & Escape Rope - + <html><head/><body><p>Allows the player to use Dig or Escape Rope</p></body></html> @@ -311,14 +311,14 @@ - + Floor Number - + <html><head/><body><p>Floor number to be used for maps with elevators.</p></body></html> @@ -328,6 +328,96 @@ + + + + false + + + + + + + Layout + + + + + + + + + Use Existing Layout + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -396,7 +486,7 @@ 0 0 410 - 21 + 22 diff --git a/include/ui/newmappopup.h b/include/ui/newmappopup.h index e668e8632..3d24715df 100644 --- a/include/ui/newmappopup.h +++ b/include/ui/newmappopup.h @@ -23,6 +23,7 @@ class NewMapPopup : public QMainWindow bool importedMap; QString layoutId; void init(); + void initUi(); void init(MapSortOrder type, QVariant data); void init(Layout *); static void setDefaultSettings(Project *project); @@ -60,6 +61,8 @@ class NewMapPopup : public QMainWindow static struct Settings settings; private slots: + void on_checkBox_UseExistingLayout_stateChanged(int state); + void on_comboBox_Layout_currentTextChanged(const QString &text); void on_pushButton_NewMap_Accept_clicked(); void on_lineEdit_NewMap_Name_textChanged(const QString &); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b62aa3390..47ce878ba 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1153,68 +1153,79 @@ void MainWindow::sortMapList() { } void MainWindow::onOpenMapListContextMenu(const QPoint &point) { - /// !TODO - // QModelIndex index = mapListProxyModel->mapToSource(ui->mapList->indexAt(point)); - // if (!index.isValid()) { - // return; - // } + QStandardItemModel *model; + int dataRole; + FilterChildrenProxyModel *proxy; + QTreeView *list; + void (MainWindow::*addFunction)(QAction *); + QString actionText; - switch (ui->mapListContainer->currentIndex()) { - // - case MapListTab::Groups: + switch (this->mapSortOrder) { + case MapSortOrder::SortByGroup: + model = this->mapGroupModel; + dataRole = MapListRoles::GroupRole; + proxy = this->groupListProxyModel; + list = this->ui->mapList; + addFunction = &MainWindow::onAddNewMapToGroupClick; + actionText = "Add New Map to Group"; break; - case MapListTab::Areas: + case MapSortOrder::SortByArea: + model = this->mapAreaModel; + dataRole = Qt::UserRole; + proxy = this->areaListProxyModel; + list = this->ui->areaList; + addFunction = &MainWindow::onAddNewMapToAreaClick; + actionText = "Add New Map to Area"; break; - case MapListTab::Layouts: + case MapSortOrder::SortByLayout: + model = this->layoutTreeModel; + dataRole = Qt::UserRole; + proxy = this->layoutListProxyModel; + list = this->ui->layoutList; + addFunction = &MainWindow::onAddNewMapToLayoutClick; + actionText = "Add New Map with Layout"; break; } - // QStandardItem *selectedItem = mapListModel->itemFromIndex(index); - // QVariant itemType = selectedItem->data(MapListUserRoles::TypeRole); - // if (!itemType.isValid()) { - // return; - // } + QModelIndex index = proxy->mapToSource(list->indexAt(point)); + if (!index.isValid()) { + return; + } - // // Build custom context menu depending on which type of item was selected (map group, map name, etc.) - // if (itemType == "map_group") { - // QString groupName = selectedItem->data(Qt::UserRole).toString(); - // int groupNum = selectedItem->data(MapListUserRoles::GroupRole).toInt(); - // QMenu* menu = new QMenu(this); - // QActionGroup* actions = new QActionGroup(menu); - // actions->addAction(menu->addAction("Add New Map to Group"))->setData(groupNum); - // connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToGroupClick); - // menu->exec(QCursor::pos()); - // } else if (itemType == "map_sec") { - // QString secName = selectedItem->data(Qt::UserRole).toString(); - // QMenu* menu = new QMenu(this); - // QActionGroup* actions = new QActionGroup(menu); - // actions->addAction(menu->addAction("Add New Map to Area"))->setData(secName); - // connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToAreaClick); - // menu->exec(QCursor::pos()); - // } else if (itemType == "map_layout") { - // QString layoutId = selectedItem->data(MapListUserRoles::TypeRole2).toString(); - // QMenu* menu = new QMenu(this); - // QActionGroup* actions = new QActionGroup(menu); - // actions->addAction(menu->addAction("Add New Map with Layout"))->setData(layoutId); - // connect(actions, &QActionGroup::triggered, this, &MainWindow::onAddNewMapToLayoutClick); - // menu->exec(QCursor::pos()); - // } + QStandardItem *selectedItem = model->itemFromIndex(index); + + if (selectedItem->parent()) { + return; + } + + QVariant itemData = selectedItem->data(dataRole); + if (!itemData.isValid()) { + return; + } + + QMenu menu(this); + QActionGroup actions(&menu); + actions.addAction(menu.addAction(actionText))->setData(itemData); + (this->*addFunction)(menu.exec(QCursor::pos())); } -void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) -{ +void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) { + if (!triggeredAction) return; + openNewMapPopupWindow(); this->newMapPrompt->init(MapSortOrder::SortByGroup, triggeredAction->data()); } -void MainWindow::onAddNewMapToAreaClick(QAction* triggeredAction) -{ +void MainWindow::onAddNewMapToAreaClick(QAction* triggeredAction) { + if (!triggeredAction) return; + openNewMapPopupWindow(); this->newMapPrompt->init(MapSortOrder::SortByArea, triggeredAction->data()); } -void MainWindow::onAddNewMapToLayoutClick(QAction* triggeredAction) -{ +void MainWindow::onAddNewMapToLayoutClick(QAction* triggeredAction) { + if (!triggeredAction) return; + openNewMapPopupWindow(); this->newMapPrompt->init(MapSortOrder::SortByLayout, triggeredAction->data()); } diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index b904522c1..bc9ead2f3 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -29,6 +29,7 @@ QStandardItem *MapGroupModel::createMapItem(QString mapName, int groupIndex, int map->setEditable(false); map->setData(mapName, Qt::UserRole); map->setData("map_name", MapListRoles::TypeRole); + map->setData(groupIndex, MapListRoles::GroupRole); // map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); this->mapItems.insert(mapName, map); return map; diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index 597d53d1a..0b13c4748 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -26,7 +26,7 @@ NewMapPopup::~NewMapPopup() delete ui; } -void NewMapPopup::init() { +void NewMapPopup::initUi() { // Populate combo boxes ui->comboBox_NewMap_Primary_Tileset->addItems(project->primaryTilesetLabels); ui->comboBox_NewMap_Secondary_Tileset->addItems(project->secondaryTilesetLabels); @@ -35,6 +35,10 @@ void NewMapPopup::init() { ui->comboBox_NewMap_Type->addItems(project->mapTypes); ui->comboBox_NewMap_Location->addItems(project->mapSectionValueToName.values()); + const QSignalBlocker b(ui->comboBox_Layout); + ui->comboBox_Layout->addItems(project->mapLayoutsTable); + this->layoutId = project->mapLayoutsTable.first(); + // Set spin box limits ui->spinBox_NewMap_Width->setMinimum(1); ui->spinBox_NewMap_Height->setMinimum(1); @@ -66,6 +70,10 @@ void NewMapPopup::init() { ui->spinBox_NewMap_Floor_Number->setVisible(hasFloorNumber); ui->label_NewMap_Floor_Number->setVisible(hasFloorNumber); + this->updateGeometry(); +} + +void NewMapPopup::init() { // Restore previous settings ui->lineEdit_NewMap_Name->setText(project->getNewMapName()); ui->comboBox_NewMap_Group->setTextItem(settings.group); @@ -86,6 +94,7 @@ void NewMapPopup::init() { ui->spinBox_NewMap_Floor_Number->setValue(settings.floorNumber); // Connect signals + // !TODO: make sure this doesnt reconnect a million times connect(ui->spinBox_NewMap_Width, QOverload::of(&QSpinBox::valueChanged), [=](int){checkNewMapDimensions();}); connect(ui->spinBox_NewMap_Height, QOverload::of(&QSpinBox::valueChanged), [=](int){checkNewMapDimensions();}); @@ -94,6 +103,7 @@ void NewMapPopup::init() { // Creating new map by right-clicking in the map list void NewMapPopup::init(MapSortOrder type, QVariant data) { + initUi(); switch (type) { case MapSortOrder::SortByGroup: @@ -103,6 +113,7 @@ void NewMapPopup::init(MapSortOrder type, QVariant data) { settings.location = data.toString(); break; case MapSortOrder::SortByLayout: + this->ui->checkBox_UseExistingLayout->setCheckState(Qt::Checked); useLayout(data.toString()); break; } @@ -205,26 +216,58 @@ void NewMapPopup::saveSettings() { void NewMapPopup::useLayoutSettings(Layout *layout) { if (!layout) return; + settings.width = layout->width; + ui->spinBox_NewMap_Width->setValue(layout->width); + settings.height = layout->height; + ui->spinBox_NewMap_Height->setValue(layout->height); + settings.borderWidth = layout->border_width; + ui->spinBox_NewMap_BorderWidth->setValue(layout->border_width); + settings.borderHeight = layout->border_height; + ui->spinBox_NewMap_BorderWidth->setValue(layout->border_height); + settings.primaryTilesetLabel = layout->tileset_primary_label; + ui->comboBox_NewMap_Primary_Tileset->setCurrentIndex(ui->comboBox_NewMap_Primary_Tileset->findText(layout->tileset_primary_label)); + settings.secondaryTilesetLabel = layout->tileset_secondary_label; + ui->comboBox_NewMap_Secondary_Tileset->setCurrentIndex(ui->comboBox_NewMap_Secondary_Tileset->findText(layout->tileset_secondary_label)); } void NewMapPopup::useLayout(QString layoutId) { this->existingLayout = true; this->layoutId = layoutId; + + this->ui->comboBox_Layout->setCurrentIndex(this->ui->comboBox_Layout->findText(layoutId)); + useLayoutSettings(project->mapLayouts.value(this->layoutId)); +} + +void NewMapPopup::on_checkBox_UseExistingLayout_stateChanged(int state) { + bool layoutEditsEnabled = (state == Qt::Unchecked); + + this->ui->comboBox_Layout->setEnabled(!layoutEditsEnabled); + + this->ui->spinBox_NewMap_Width->setEnabled(layoutEditsEnabled); + this->ui->spinBox_NewMap_Height->setEnabled(layoutEditsEnabled); + this->ui->spinBox_NewMap_BorderWidth->setEnabled(layoutEditsEnabled); + this->ui->spinBox_NewMap_BorderWidth->setEnabled(layoutEditsEnabled); + this->ui->comboBox_NewMap_Primary_Tileset->setEnabled(layoutEditsEnabled); + this->ui->comboBox_NewMap_Secondary_Tileset->setEnabled(layoutEditsEnabled); - // Dimensions and tilesets can't be changed for new maps using an existing layout - ui->spinBox_NewMap_Width->setDisabled(true); - ui->spinBox_NewMap_Height->setDisabled(true); - ui->spinBox_NewMap_BorderWidth->setDisabled(true); - ui->spinBox_NewMap_BorderHeight->setDisabled(true); - ui->comboBox_NewMap_Primary_Tileset->setDisabled(true); - ui->comboBox_NewMap_Secondary_Tileset->setDisabled(true); + if (!layoutEditsEnabled) { + useLayout(this->layoutId);//this->ui->comboBox_Layout->currentText()); + } else { + this->existingLayout = false; + } +} + +void NewMapPopup::on_comboBox_Layout_currentTextChanged(const QString &text) { + if (this->project->mapLayoutsTable.contains(text)) { + useLayout(text); + } } void NewMapPopup::on_lineEdit_NewMap_Name_textChanged(const QString &text) { From a14e70ef5339d874ed5fbbeeea2a90c9b97c3faf Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 8 Feb 2023 19:59:45 -0500 Subject: [PATCH 15/70] update map lists when new maps and layouts are added --- include/ui/maplistmodels.h | 6 +++++ src/mainwindow.cpp | 4 ++++ src/project.cpp | 1 + src/ui/maplistmodels.cpp | 48 +++++++++++++++++++++++++++++++++++++- 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index d730c05e0..2465cc293 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -32,6 +32,8 @@ class MapGroupModel : public QStandardItemModel { QStandardItem *createGroupItem(QString groupName, int groupIndex); QStandardItem *createMapItem(QString mapName, int groupIndex, int mapIndex); + QStandardItem *insertMapItem(QString mapName, QString groupName); + QStandardItem *getItem(const QModelIndex &index) const; QModelIndex indexOfMap(QString mapName); @@ -68,6 +70,8 @@ class MapAreaModel : public QStandardItemModel { QStandardItem *createAreaItem(QString areaName, int areaIndex); QStandardItem *createMapItem(QString mapName, int areaIndex, int mapIndex); + QStandardItem *insertMapItem(QString mapName, QString areaName, int groupIndex); + QStandardItem *getItem(const QModelIndex &index) const; QModelIndex indexOfMap(QString mapName); @@ -104,6 +108,8 @@ class LayoutTreeModel : public QStandardItemModel { QStandardItem *createLayoutItem(QString layoutId); QStandardItem *createMapItem(QString mapName); + QStandardItem *insertMapItem(QString mapName, QString layoutId); + QStandardItem *getItem(const QModelIndex &index) const; QModelIndex indexOfLayout(QString layoutName); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 47ce878ba..18b7d9b94 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1248,6 +1248,10 @@ void MainWindow::onNewMapCreated() { // QStandardItem* groupItem = mapGroupItemsList->at(newMapGroup); // int numMapsInGroup = groupItem->rowCount(); + this->mapGroupModel->insertMapItem(newMapName, editor->project->groupNames[newMapGroup]); + this->mapAreaModel->insertMapItem(newMapName, newMap->location, newMapGroup); + this->layoutTreeModel->insertMapItem(newMapName, newMap->layout->id); + // QStandardItem *newMapItem = createMapItem(newMapName, newMapGroup, numMapsInGroup); // groupItem->appendRow(newMapItem); // mapListIndexes.insert(newMapName, newMapItem->index()); diff --git a/src/project.cpp b/src/project.cpp index 15122fac0..ba273f175 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1775,6 +1775,7 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool if (!existingLayout) { mapLayouts.insert(newMap->layoutId, newMap->layout); mapLayoutsTable.append(newMap->layoutId); + layoutIdsToNames.insert(newMap->layout->id, newMap->layout->name); if (!importedMap) { setNewMapBlockdata(newMap); } diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index bc9ead2f3..71c4caf19 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -35,7 +35,21 @@ QStandardItem *MapGroupModel::createMapItem(QString mapName, int groupIndex, int return map; } +QStandardItem *MapGroupModel::insertMapItem(QString mapName, QString groupName) { + int groupIndex = this->project->groupNames.indexOf(groupName); + QStandardItem *group = this->groupItems[groupName]; + if (!group) { + return nullptr; + } + int mapIndex = group->rowCount(); + QStandardItem *map = createMapItem(mapName, groupIndex, mapIndex); + group->appendRow(map); + return map; +} + void MapGroupModel::initialize() { + this->groupItems.clear(); + this->mapItems.clear(); for (int i = 0; i < this->project->groupNames.length(); i++) { QString group_name = this->project->groupNames.value(i); QStandardItem *group = createGroupItem(group_name, i); @@ -140,7 +154,21 @@ QStandardItem *MapAreaModel::createMapItem(QString mapName, int groupIndex, int return map; } +QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, int groupIndex) { + // int areaIndex = this->project->mapSectionNameToValue[areaName]; + QStandardItem *area = this->areaItems[areaName]; + if (!area) { + return nullptr; + } + int mapIndex = area->rowCount(); + QStandardItem *map = createMapItem(mapName, groupIndex, mapIndex); + area->appendRow(map); + return map; +} + void MapAreaModel::initialize() { + this->areaItems.clear(); + this->mapItems.clear(); for (int i = 0; i < this->project->mapSectionNameToValue.size(); i++) { QString mapsecName = project->mapSectionValueToName.value(i); QStandardItem *areaItem = createAreaItem(mapsecName, i); @@ -256,7 +284,26 @@ QStandardItem *LayoutTreeModel::createMapItem(QString mapName) { return map; } +QStandardItem *LayoutTreeModel::insertMapItem(QString mapName, QString layoutId) { + QStandardItem *layout = nullptr; + if (this->layoutItems.contains(layoutId)) { + layout = this->layoutItems[layoutId]; + } + else { + layout = createLayoutItem(layoutId); + this->root->appendRow(layout); + } + if (!layout) { + return nullptr; + } + QStandardItem *map = createMapItem(mapName); + layout->appendRow(map); + return map; +} + void LayoutTreeModel::initialize() { + this->layoutItems.clear(); + this->mapItems.clear(); for (int i = 0; i < this->project->mapLayoutsTable.length(); i++) { QString layoutId = project->mapLayoutsTable.value(i); QStandardItem *layoutItem = createLayoutItem(layoutId); @@ -265,7 +312,6 @@ void LayoutTreeModel::initialize() { for (auto mapList : this->project->groupedMapNames) { for (auto mapName : mapList) { - // QString layoutId = project->readMapLayoutId(mapName); QStandardItem *map = createMapItem(mapName); this->layoutItems[layoutId]->appendRow(map); From 0ec8f4fee5064fa1df5ec76ce50a70a6e1367cb0 Mon Sep 17 00:00:00 2001 From: garak Date: Mon, 13 Feb 2023 17:44:56 -0500 Subject: [PATCH 16/70] add drag-drop reordering for maps in groups --- forms/mainwindow.ui | 11 ++- include/ui/eventfilters.h | 12 +++ include/ui/maplistmodels.h | 28 ++++++- include/ui/montabwidget.h | 2 - porymap.pro | 2 + src/mainwindow.cpp | 41 ++++++--- src/ui/eventfilters.cpp | 10 +++ src/ui/maplistmodels.cpp | 165 ++++++++++++++++++++++++++++++++++--- src/ui/montabwidget.cpp | 10 +-- 9 files changed, 242 insertions(+), 39 deletions(-) create mode 100644 include/ui/eventfilters.h create mode 100644 src/ui/eventfilters.cpp diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 9ecc927f2..fe6a0ca27 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -154,7 +154,7 @@ - + 0 @@ -289,7 +289,7 @@ - + 0 @@ -424,7 +424,7 @@ - + 0 @@ -3607,6 +3607,11 @@ QWidget
mapview.h
+ + MapTree + QTreeView +
maplistmodels.h
+
diff --git a/include/ui/eventfilters.h b/include/ui/eventfilters.h new file mode 100644 index 000000000..984ce23a3 --- /dev/null +++ b/include/ui/eventfilters.h @@ -0,0 +1,12 @@ +#include +#include + + + +class WheelFilter : public QObject { + Q_OBJECT +public: + WheelFilter(QObject *parent) : QObject(parent) {} + virtual ~WheelFilter() {} + bool eventFilter(QObject *obj, QEvent *event) override; +}; diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 2465cc293..6a5c1e92d 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -2,6 +2,8 @@ #ifndef MAPLISTMODELS_H #define MAPLISTMODELS_H +#include +#include #include #include @@ -17,6 +19,20 @@ enum MapListRoles { +class MapTree : public QTreeView { + Q_OBJECT +public: + MapTree(QWidget *parent) : QTreeView(parent) { + this->setDropIndicatorShown(true); + this->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + } + +public slots: + void removeSelected(); +}; + + + class MapGroupModel : public QStandardItemModel { Q_OBJECT @@ -26,11 +42,16 @@ class MapGroupModel : public QStandardItemModel { QVariant data(const QModelIndex &index, int role) const override; + Qt::DropActions supportedDropActions() const override; + QStringList mimeTypes() const override; + virtual QMimeData *mimeData(const QModelIndexList &indexes) const override; + virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; + public: void setMap(QString mapName) { this->openMap = mapName; } QStandardItem *createGroupItem(QString groupName, int groupIndex); - QStandardItem *createMapItem(QString mapName, int groupIndex, int mapIndex); + QStandardItem *createMapItem(QString mapName, QStandardItem *fromItem = nullptr); QStandardItem *insertMapItem(QString mapName, QString groupName); @@ -39,6 +60,9 @@ class MapGroupModel : public QStandardItemModel { void initialize(); +private: + void updateProject(); + private: Project *project; QStandardItem *root = nullptr; @@ -50,7 +74,7 @@ class MapGroupModel : public QStandardItemModel { QString openMap; signals: - void edited(); + void dragMoveCompleted(); }; diff --git a/include/ui/montabwidget.h b/include/ui/montabwidget.h index 4b66969c3..6d9160689 100644 --- a/include/ui/montabwidget.h +++ b/include/ui/montabwidget.h @@ -32,8 +32,6 @@ public slots: void deactivateTab(int tabIndex); private: - bool eventFilter(QObject *object, QEvent *event); - void actionCopyTab(int index); void actionAddDeleteTab(int index); diff --git a/porymap.pro b/porymap.pro index a6df62240..04fc6e00d 100644 --- a/porymap.pro +++ b/porymap.pro @@ -57,6 +57,7 @@ SOURCES += src/core/block.cpp \ src/ui/cursortilerect.cpp \ src/ui/customattributestable.cpp \ src/ui/eventframes.cpp \ + src/ui/eventfilters.cpp \ src/ui/filterchildrenproxymodel.cpp \ src/ui/maplistmodels.cpp \ src/ui/graphicsview.cpp \ @@ -147,6 +148,7 @@ HEADERS += include/core/block.h \ include/ui/cursortilerect.h \ include/ui/customattributestable.h \ include/ui/eventframes.h \ + include/ui/eventfilters.h \ include/ui/filterchildrenproxymodel.h \ include/ui/maplistmodels.h \ include/ui/graphicsview.h \ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 18b7d9b94..6445d010d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -20,6 +20,7 @@ #include "montabwidget.h" #include "imageexport.h" #include "maplistmodels.h" +#include "eventfilters.h" #include #include @@ -212,6 +213,10 @@ void MainWindow::initCustomUI() { ui->mainTabBar->setTabIcon(3, QIcon(QStringLiteral(":/icons/connections.ico"))); ui->mainTabBar->addTab("Wild Pokemon"); ui->mainTabBar->setTabIcon(4, QIcon(QStringLiteral(":/icons/tall_grass.ico"))); + + WheelFilter *wheelFilter = new WheelFilter(this); + ui->mainTabBar->installEventFilter(wheelFilter); + this->ui->mapListContainer->tabBar()->installEventFilter(wheelFilter); } void MainWindow::initExtraSignals() { @@ -1110,6 +1115,16 @@ bool MainWindow::populateMapList() { groupListProxyModel->setSourceModel(this->mapGroupModel); ui->mapList->setModel(groupListProxyModel); + // + // connect(this->mapGroupModel, &QStandardItemModel::dataChanged, [=](const QModelIndex &, const QModelIndex &, const QList &){ + // qDebug() << "mapGroupModel dataChanged"; + // }); + + // connect(this->mapGroupModel, &MapGroupModel::edited, [=, this](){ + // qDebug() << "model edited with" << this->ui->mapList->selectionModel()->selection().size() << "items"; + // }); removeSelected + connect(this->mapGroupModel, &MapGroupModel::dragMoveCompleted, this->ui->mapList, &MapTree::removeSelected); + this->mapAreaModel = new MapAreaModel(editor->project); this->areaListProxyModel = new FilterChildrenProxyModel(); areaListProxyModel->setSourceModel(this->mapAreaModel); @@ -1121,10 +1136,11 @@ bool MainWindow::populateMapList() { ui->layoutList->setModel(layoutListProxyModel); /// !TODO - // ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); - // ui->mapList->setDragEnabled(true); - // ui->mapList->setAcceptDrops(true); - // ui->mapList->setDropIndicatorShown(true); + ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); + ui->mapList->setDragEnabled(true); + ui->mapList->setAcceptDrops(true); + ui->mapList->setDropIndicatorShown(true); + ui->mapList->setDragDropMode(QAbstractItemView::InternalMove); return success; } @@ -1244,19 +1260,11 @@ void MainWindow::onNewMapCreated() { editor->project->saveMap(newMap); editor->project->saveAllDataStructures(); - // !TODO - // QStandardItem* groupItem = mapGroupItemsList->at(newMapGroup); - // int numMapsInGroup = groupItem->rowCount(); - + // Add new Map / Layout to the mapList models this->mapGroupModel->insertMapItem(newMapName, editor->project->groupNames[newMapGroup]); this->mapAreaModel->insertMapItem(newMapName, newMap->location, newMapGroup); this->layoutTreeModel->insertMapItem(newMapName, newMap->layout->id); - // QStandardItem *newMapItem = createMapItem(newMapName, newMapGroup, numMapsInGroup); - // groupItem->appendRow(newMapItem); - // mapListIndexes.insert(newMapName, newMapItem->index()); - - // sortMapList(); setMap(newMapName, true); if (newMap->needsHealLocation) { @@ -1512,11 +1520,18 @@ void MainWindow::updateMapList() { mapAreaModel->setMap(this->editor->map->name); areaListProxyModel->layoutChanged(); } + else { + // !TODO + qDebug() << "need to clear map list"; + } if (this->editor->layout) { layoutTreeModel->setLayout(this->editor->layout->id); layoutListProxyModel->layoutChanged(); } + else { + qDebug() << "need to clear layout list"; + } } void MainWindow::on_action_Save_Project_triggered() { diff --git a/src/ui/eventfilters.cpp b/src/ui/eventfilters.cpp new file mode 100644 index 000000000..24f2e0bd3 --- /dev/null +++ b/src/ui/eventfilters.cpp @@ -0,0 +1,10 @@ +#include "eventfilters.h" + + + +bool WheelFilter::eventFilter(QObject *, QEvent *event) { + if (event->type() == QEvent::Wheel) { + return true; + } + return false; +} diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 71c4caf19..dd0b254db 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -1,6 +1,18 @@ #include "maplistmodels.h" +#include + #include "project.h" +#include "filterchildrenproxymodel.h" + + + +void MapTree::removeSelected() { + while (!this->selectedIndexes().isEmpty()) { + QModelIndex i = this->selectedIndexes().takeLast(); + this->model()->removeRow(i.row(), i.parent()); + } +} @@ -11,6 +23,122 @@ MapGroupModel::MapGroupModel(Project *project, QObject *parent) : QStandardItemM initialize(); } +Qt::DropActions MapGroupModel::supportedDropActions() const { + return Qt::MoveAction; +} + +QStringList MapGroupModel::mimeTypes() const { + QStringList types; + types << "application/porymap.mapgroupmodel.map" + << "application/porymap.mapgroupmodel.group"; + return types; +} + +QMimeData *MapGroupModel::mimeData(const QModelIndexList &indexes) const { + QMimeData *mimeData = QStandardItemModel::mimeData(indexes); + QByteArray encodedData; + + QDataStream stream(&encodedData, QIODevice::WriteOnly); + + for (const QModelIndex &index : indexes) { + if (index.isValid()) { + QString mapName = data(index, Qt::UserRole).toString(); + stream << mapName; + } + } + + mimeData->setData("application/porymap.mapgroupmodel.map", encodedData); + return mimeData; +} + +bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parentIndex) { + if (action == Qt::IgnoreAction) + return true; + + if (!data->hasFormat("application/porymap.mapgroupmodel.map")) + return false; + + if (!parentIndex.isValid()) + return false; + + int firstRow = 0; + + if (row != -1) { + firstRow = row; + } + else if (parentIndex.isValid()) { + firstRow = rowCount(parentIndex); + } + + QByteArray encodedData = data->data("application/porymap.mapgroupmodel.map"); + QDataStream stream(&encodedData, QIODevice::ReadOnly); + QStringList droppedMaps; + int rowCount = 0; + + QList newItems; + + while (!stream.atEnd()) { + QString mapName; + stream >> mapName; + droppedMaps << mapName; + rowCount++; + } + + this->insertRows(firstRow, rowCount, parentIndex); + + int newItemIndex = 0; + for (QString mapName : droppedMaps) { + QModelIndex mapIndex = index(firstRow, 0, parentIndex); + QStandardItem *mapItem = this->itemFromIndex(mapIndex); + createMapItem(mapName, mapItem); + firstRow++; + } + + // updateProject(); + + emit dragMoveCompleted(); + + return false; +} + + +/* + QStringList groupNames; + QMap mapGroups; + QList groupedMapNames; + QStringList mapNames; +*/ +void MapGroupModel::updateProject() { + // + QStringList groups; + int numGroups = this->root->rowCount(); + qDebug() << "group count:" << numGroups; + + for (int g = 0; g < this->root->rowCount(); g++) { + QStandardItem *groupItem = this->item(g); + qDebug() << g << "group item" << groupItem->text(); //data(Qt::UserRole).toString(); + for (int m = 0; m < groupItem->rowCount(); m++) { + // + QStandardItem *mapItem = groupItem->child(m); + qDebug() << " " << m << "map item" << mapItem->data(Qt::UserRole).toString(); + } + } + + QList maps; + for (auto mapName : this->mapItems.keys()) { + // + QStandardItem *mapItem = this->mapItems[mapName]; + QStandardItem *groupItem = mapItem->parent(); + if (!groupItem) { + qDebug() << "FAIL: no parent" << mapName; + continue; + } + auto mapIndex = this->indexFromItem(mapItem).row(); + auto groupIndex = this->indexFromItem(groupItem).row(); + // qDebug().nospace() << "map: " << mapName << "[" << parentIndex.row() << "." << mapIndex.row() << "]"; + } +} + QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex) { QStandardItem *group = new QStandardItem; group->setText(groupName); @@ -18,31 +146,30 @@ QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex) group->setData(groupName, Qt::UserRole); group->setData("map_group", MapListRoles::TypeRole); group->setData(groupIndex, MapListRoles::GroupRole); - // group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + group->setFlags(Qt::ItemIsEditable | /* Qt::ItemIsSelectable | */ Qt::ItemIsEnabled | /* Qt::ItemIsDragEnabled | */ Qt::ItemIsDropEnabled); this->groupItems.insert(groupName, group); return group; } -QStandardItem *MapGroupModel::createMapItem(QString mapName, int groupIndex, int mapIndex) { - QStandardItem *map = new QStandardItem; - map->setText(QString("[%1.%2] ").arg(groupIndex).arg(mapIndex, 2, 10, QLatin1Char('0')) + mapName); +QStandardItem *MapGroupModel::createMapItem(QString mapName, QStandardItem *map) { + if (!map) map = new QStandardItem; map->setEditable(false); map->setData(mapName, Qt::UserRole); map->setData("map_name", MapListRoles::TypeRole); - map->setData(groupIndex, MapListRoles::GroupRole); - // map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); - this->mapItems.insert(mapName, map); + // map->setData(groupIndex, MapListRoles::GroupRole); + map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + this->mapItems[mapName] = map; return map; } QStandardItem *MapGroupModel::insertMapItem(QString mapName, QString groupName) { - int groupIndex = this->project->groupNames.indexOf(groupName); + //int groupIndex = this->project->groupNames.indexOf(groupName); QStandardItem *group = this->groupItems[groupName]; if (!group) { return nullptr; } - int mapIndex = group->rowCount(); - QStandardItem *map = createMapItem(mapName, groupIndex, mapIndex); + //int mapIndex = group->rowCount(); + QStandardItem *map = createMapItem(mapName); group->appendRow(map); return map; } @@ -54,10 +181,12 @@ void MapGroupModel::initialize() { QString group_name = this->project->groupNames.value(i); QStandardItem *group = createGroupItem(group_name, i); root->appendRow(group); + //this->setItem(0, i, group); QStringList names = this->project->groupedMapNames.value(i); for (int j = 0; j < names.length(); j++) { QString map_name = names.value(j); - QStandardItem *map = createMapItem(map_name, i, j); + QStandardItem *map = createMapItem(map_name); + //this->setItem(i, j, map); group->appendRow(map); } } @@ -90,10 +219,13 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico")); static QIcon mapFolderIcon; + static QIcon folderIcon; static bool loaded = false; if (!loaded) { mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off); mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On); + folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off); + folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On); loaded = true; } @@ -101,6 +233,9 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { QString type = item->data(MapListRoles::TypeRole).toString(); if (type == "map_group") { + if (!item->hasChildren()) { + return folderIcon; + } return mapFolderIcon; } else if (type == "map_name") { QString mapName = item->data(Qt::UserRole).toString(); @@ -118,6 +253,14 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { return mapGrayIcon; } } + else if (role == Qt::DisplayRole) { + // + QStandardItem *item = this->getItem(index)->child(row, col); + + if (item->data(MapListRoles::TypeRole).toString() == "map_name") { + return QString("[%1.%2] ").arg(this->getItem(index)->row()).arg(row, 2, 10, QLatin1Char('0')) + item->data(Qt::UserRole).toString(); + } + } return QStandardItemModel::data(index, role); } diff --git a/src/ui/montabwidget.cpp b/src/ui/montabwidget.cpp index 6845a02ba..e31739bd2 100644 --- a/src/ui/montabwidget.cpp +++ b/src/ui/montabwidget.cpp @@ -3,6 +3,7 @@ #include "editor.h" #include "encountertablemodel.h" #include "encountertabledelegates.h" +#include "eventfilters.h" @@ -11,20 +12,13 @@ static WildMonInfo encounterClipboard; MonTabWidget::MonTabWidget(Editor *editor, QWidget *parent) : QTabWidget(parent) { this->editor = editor; populate(); - this->tabBar()->installEventFilter(this); + this->tabBar()->installEventFilter(new WheelFilter(this)); } MonTabWidget::~MonTabWidget() { } -bool MonTabWidget::eventFilter(QObject *, QEvent *event) { - if (event->type() == QEvent::Wheel) { - return true; - } - return false; -} - void MonTabWidget::populate() { EncounterFields fields = editor->project->wildMonFields; activeTabs.resize(fields.size()); From d6f3bb100803598da3df2693987aa8d9bdbc9eb5 Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 14 Feb 2023 01:50:14 -0500 Subject: [PATCH 17/70] allow editing map group names --- include/ui/maplistmodels.h | 25 +++++++++- src/mainwindow.cpp | 2 + src/ui/maplistmodels.cpp | 97 ++++++++++++++++++++++++-------------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 6a5c1e92d..ef21d8aec 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -33,12 +34,31 @@ public slots: +class GroupNameDelegate : public QStyledItemDelegate { + Q_OBJECT + +public: + GroupNameDelegate(Project *project, QObject *parent = nullptr) : QStyledItemDelegate(parent), project(project) {} + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +private: + Project *project = nullptr; +}; + + + +class QRegularExpressionValidator; + class MapGroupModel : public QStandardItemModel { Q_OBJECT public: MapGroupModel(Project *project, QObject *parent = nullptr); - ~MapGroupModel() {} + ~MapGroupModel() { } QVariant data(const QModelIndex &index, int role) const override; @@ -47,6 +67,8 @@ class MapGroupModel : public QStandardItemModel { virtual QMimeData *mimeData(const QModelIndexList &indexes) const override; virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; + virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + public: void setMap(QString mapName) { this->openMap = mapName; } @@ -69,7 +91,6 @@ class MapGroupModel : public QStandardItemModel { QMap groupItems; QMap mapItems; - // TODO: if reordering, will the item be the same? QString openMap; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6445d010d..d5c985b37 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1115,6 +1115,8 @@ bool MainWindow::populateMapList() { groupListProxyModel->setSourceModel(this->mapGroupModel); ui->mapList->setModel(groupListProxyModel); + this->ui->mapList->setItemDelegateForColumn(0, new GroupNameDelegate(this->editor->project, this)); + // // connect(this->mapGroupModel, &QStandardItemModel::dataChanged, [=](const QModelIndex &, const QModelIndex &, const QList &){ // qDebug() << "mapGroupModel dataChanged"; diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index dd0b254db..6c0a06d1b 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -1,6 +1,7 @@ #include "maplistmodels.h" #include +#include #include "project.h" #include "filterchildrenproxymodel.h" @@ -16,6 +17,33 @@ void MapTree::removeSelected() { +QWidget *GroupNameDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { + QLineEdit *editor = new QLineEdit(parent); + static const QRegularExpression expression("gMapGroup_[A-Za-z0-9_]+"); + QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression, parent); + editor->setValidator(validator); + editor->setFrame(false); + return editor; +} + +void GroupNameDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { + QString groupName = index.data(Qt::UserRole).toString(); + QLineEdit *le = static_cast(editor); + le->setText(groupName); +} + +void GroupNameDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { + QLineEdit *le = static_cast(editor); + QString groupName = le->text(); + model->setData(index, groupName, Qt::UserRole); +} + +void GroupNameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const { + editor->setGeometry(option.rect); +} + + + MapGroupModel::MapGroupModel(Project *project, QObject *parent) : QStandardItemModel(parent) { this->project = project; this->root = this->invisibleRootItem(); @@ -94,81 +122,66 @@ bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i firstRow++; } - // updateProject(); - emit dragMoveCompleted(); + updateProject(); return false; } +void MapGroupModel::updateProject() { + if (!this->project) return; -/* QStringList groupNames; QMap mapGroups; QList groupedMapNames; QStringList mapNames; -*/ -void MapGroupModel::updateProject() { - // - QStringList groups; - int numGroups = this->root->rowCount(); - qDebug() << "group count:" << numGroups; for (int g = 0; g < this->root->rowCount(); g++) { QStandardItem *groupItem = this->item(g); - qDebug() << g << "group item" << groupItem->text(); //data(Qt::UserRole).toString(); + QString groupName = groupItem->data(Qt::UserRole).toString(); + groupNames.append(groupName); + mapGroups[groupName] = g; + QStringList mapsInGroup; for (int m = 0; m < groupItem->rowCount(); m++) { - // QStandardItem *mapItem = groupItem->child(m); - qDebug() << " " << m << "map item" << mapItem->data(Qt::UserRole).toString(); + QString mapName = mapItem->data(Qt::UserRole).toString(); + mapsInGroup.append(mapName); + mapNames.append(mapName); } + groupedMapNames.append(mapsInGroup); } - QList maps; - for (auto mapName : this->mapItems.keys()) { - // - QStandardItem *mapItem = this->mapItems[mapName]; - QStandardItem *groupItem = mapItem->parent(); - if (!groupItem) { - qDebug() << "FAIL: no parent" << mapName; - continue; - } - auto mapIndex = this->indexFromItem(mapItem).row(); - auto groupIndex = this->indexFromItem(groupItem).row(); - // qDebug().nospace() << "map: " << mapName << "[" << parentIndex.row() << "." << mapIndex.row() << "]"; - } + this->project->groupNames = groupNames; + this->project->mapGroups = mapGroups; + this->project->groupedMapNames = groupedMapNames; + this->project->mapNames = mapNames; } QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex) { QStandardItem *group = new QStandardItem; group->setText(groupName); - group->setEditable(true); group->setData(groupName, Qt::UserRole); group->setData("map_group", MapListRoles::TypeRole); group->setData(groupIndex, MapListRoles::GroupRole); - group->setFlags(Qt::ItemIsEditable | /* Qt::ItemIsSelectable | */ Qt::ItemIsEnabled | /* Qt::ItemIsDragEnabled | */ Qt::ItemIsDropEnabled); + group->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); this->groupItems.insert(groupName, group); return group; } QStandardItem *MapGroupModel::createMapItem(QString mapName, QStandardItem *map) { if (!map) map = new QStandardItem; - map->setEditable(false); map->setData(mapName, Qt::UserRole); map->setData("map_name", MapListRoles::TypeRole); - // map->setData(groupIndex, MapListRoles::GroupRole); map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); this->mapItems[mapName] = map; return map; } QStandardItem *MapGroupModel::insertMapItem(QString mapName, QString groupName) { - //int groupIndex = this->project->groupNames.indexOf(groupName); QStandardItem *group = this->groupItems[groupName]; if (!group) { return nullptr; } - //int mapIndex = group->rowCount(); QStandardItem *map = createMapItem(mapName); group->appendRow(map); return map; @@ -181,12 +194,10 @@ void MapGroupModel::initialize() { QString group_name = this->project->groupNames.value(i); QStandardItem *group = createGroupItem(group_name, i); root->appendRow(group); - //this->setItem(0, i, group); QStringList names = this->project->groupedMapNames.value(i); for (int j = 0; j < names.length(); j++) { QString map_name = names.value(j); QStandardItem *map = createMapItem(map_name); - //this->setItem(i, j, map); group->appendRow(map); } } @@ -256,15 +267,31 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { else if (role == Qt::DisplayRole) { // QStandardItem *item = this->getItem(index)->child(row, col); + QString type = item->data(MapListRoles::TypeRole).toString(); - if (item->data(MapListRoles::TypeRole).toString() == "map_name") { + if (type == "map_name") { return QString("[%1.%2] ").arg(this->getItem(index)->row()).arg(row, 2, 10, QLatin1Char('0')) + item->data(Qt::UserRole).toString(); } + else if (type == "map_group") { + return item->data(Qt::UserRole).toString(); + } } return QStandardItemModel::data(index, role); } +bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int role) { + if (role == Qt::UserRole && data(index, MapListRoles::TypeRole).toString() == "map_group") { + // verify uniqueness of new group name + if (this->project->groupNames.contains(value.toString())) { + return false; + } + } + if (QStandardItemModel::setData(index, value, role)) { + this->updateProject(); + } +} + MapAreaModel::MapAreaModel(Project *project, QObject *parent) : QStandardItemModel(parent) { @@ -288,7 +315,7 @@ QStandardItem *MapAreaModel::createAreaItem(QString mapsecName, int areaIndex) { QStandardItem *MapAreaModel::createMapItem(QString mapName, int groupIndex, int mapIndex) { QStandardItem *map = new QStandardItem; - map->setText(QString("[%1.%2] ").arg(groupIndex).arg(mapIndex, 2, 10, QLatin1Char('0')) + mapName); + map->setText(mapName); map->setEditable(false); map->setData(mapName, Qt::UserRole); map->setData("map_name", MapListRoles::TypeRole); From 5d98f8e2f8796a1fabac8c06c379b82f27059b9e Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 14 Feb 2023 03:11:18 -0500 Subject: [PATCH 18/70] fix crash in model data function --- src/ui/maplistmodels.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 6c0a06d1b..b4f6e9dce 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -220,6 +220,8 @@ QModelIndex MapGroupModel::indexOfMap(QString mapName) { } QVariant MapGroupModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) return QVariant(); + int row = index.row(); int col = index.column(); From 2ea0590f6e27d1571516269c3a57923447324e4f Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 14 Feb 2023 12:09:22 -0500 Subject: [PATCH 19/70] save changes to layouts --- include/core/maplayout.h | 5 +-- include/project.h | 11 ++++--- src/core/maplayout.cpp | 23 +++++++++++-- src/editor.cpp | 9 +++-- src/mainwindow.cpp | 71 ++++++++++++---------------------------- src/project.cpp | 48 +++++++++++++++++---------- 6 files changed, 87 insertions(+), 80 deletions(-) diff --git a/include/core/maplayout.h b/include/core/maplayout.h index 968b8960c..c17248cee 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -19,8 +19,6 @@ class Layout : public QObject { public: Layout() {} - void copyAttributesFrom(Layout *other); - static QString layoutConstantFromName(QString mapName); bool loaded = false; @@ -72,6 +70,9 @@ class Layout : public QObject { QUndoStack editHistory; public: + Layout *copy(); + void copyFrom(Layout *other); + int getWidth(); int getHeight(); int getBorderWidth(); diff --git a/include/project.h b/include/project.h index 24f14611e..34a6a49d4 100644 --- a/include/project.h +++ b/include/project.h @@ -58,7 +58,7 @@ class Project : public QObject QString layoutsLabel; QMap layoutIdsToNames; QMap mapLayouts; -// QMap mapLayoutsMaster; + QMap mapLayoutsMaster; QMap mapSecToMapHoverName; QMap mapSectionNameToValue; QMap mapSectionValueToName; @@ -157,11 +157,12 @@ class Project : public QObject void loadTilesetPalettes(Tileset*); void readTilesetPaths(Tileset* tileset); - void saveLayoutBlockdata(Map*); - void saveLayoutBorder(Map*); + void saveLayout(Layout *); + void saveLayoutBlockdata(Layout *); + void saveLayoutBorder(Layout *); void writeBlockdata(QString, const Blockdata &); void saveAllMaps(); - void saveMap(Map*); + void saveMap(Map *); void saveAllDataStructures(); void saveMapLayouts(); void saveMapGroups(); @@ -238,7 +239,7 @@ class Project : public QObject static int getMaxObjectEvents(); private: - void updateMapLayout(Map*); + void updateLayout(Layout *); void setNewMapBlockdata(Map* map); void setNewMapBorder(Map *map); diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 4fd05b4f0..3dd9b9f2b 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -50,8 +50,27 @@ // BorderMetatilesPixmapItem *borderItem = nullptr; // QUndoStack editHistory; -void Layout::copyAttributesFrom(Layout *other) { - // +Layout *Layout::copy() { + Layout *layout = new Layout; + layout->copyFrom(this); + return layout; +} + +void Layout::copyFrom(Layout *other) { + this->id = other->id; + this->name = other->name; + this->width = other->width; + this->height = other->height; + this->border_width = other->border_width; + this->border_height = other->border_height; + this->border_path = other->border_path; + this->blockdata_path = other->blockdata_path; + this->tileset_primary_label = other->tileset_primary_label; + this->tileset_secondary_label = other->tileset_secondary_label; + this->tileset_primary = other->tileset_primary; + this->tileset_secondary = other->tileset_secondary; + this->blockdata = other->blockdata; + this->border = other->border; } QString Layout::layoutConstantFromName(QString mapName) { diff --git a/src/editor.cpp b/src/editor.cpp index 7d6d2780d..fc77b2b6d 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -62,10 +62,13 @@ void Editor::saveProject() { } void Editor::save() { - if (project && map) { + if (this->project && this->map) { saveUiFields(); - project->saveMap(map); - project->saveAllDataStructures(); + this->project->saveMap(this->map); + this->project->saveAllDataStructures(); + } + else if (this->project && this->layout) { + this->project->saveLayout(this->layout); } } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d5c985b37..db766c0ce 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -684,10 +684,6 @@ void MainWindow::on_action_Reload_Project_triggered() { } void MainWindow::unsetMap() { - // - logInfo("Disabling map-related edits"); - - // this->editor->unsetMap(); // disable other tabs @@ -696,7 +692,6 @@ void MainWindow::unsetMap() { this->ui->mainTabBar->setTabEnabled(3, false); this->ui->mainTabBar->setTabEnabled(4, false); - // this->ui->comboBox_LayoutSelector->setEnabled(false); } @@ -752,8 +747,12 @@ bool MainWindow::setMap(QString map_name, bool scroll) { } bool MainWindow::setLayout(QString layoutId) { - // if this->editor->setLayout(layoutName); - // this->editor->layout = layout; + if (this->editor->map) + logInfo("Switching to a layout-only editing mode. Disabling map-related edits."); + + setMap(QString()); + + logInfo(QString("Setting layout to '%1'").arg(layoutId)); if (!this->editor->setLayout(layoutId)) { return false; @@ -762,17 +761,7 @@ bool MainWindow::setLayout(QString layoutId) { 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(); // !TODO: make sure these connections are not duplicated / cleared later @@ -780,15 +769,6 @@ bool MainWindow::setLayout(QString layoutId) { connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing); // connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); - // displayMapProperties - - - // - // 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; @@ -1116,15 +1096,6 @@ bool MainWindow::populateMapList() { ui->mapList->setModel(groupListProxyModel); this->ui->mapList->setItemDelegateForColumn(0, new GroupNameDelegate(this->editor->project, this)); - - // - // connect(this->mapGroupModel, &QStandardItemModel::dataChanged, [=](const QModelIndex &, const QModelIndex &, const QList &){ - // qDebug() << "mapGroupModel dataChanged"; - // }); - - // connect(this->mapGroupModel, &MapGroupModel::edited, [=, this](){ - // qDebug() << "model edited with" << this->ui->mapList->selectionModel()->selection().size() << "items"; - // }); removeSelected connect(this->mapGroupModel, &MapGroupModel::dragMoveCompleted, this->ui->mapList, &MapTree::removeSelected); this->mapAreaModel = new MapAreaModel(editor->project); @@ -1497,12 +1468,6 @@ void MainWindow::on_layoutList_activated(const QModelIndex &index) { QVariant data = index.data(Qt::UserRole); if (index.data(MapListRoles::TypeRole) == "map_layout" && !data.isNull()) { QString layoutId = data.toString(); - // - logInfo("Switching to a layout-only editing mode"); - setMap(QString()); - //setLayout(layoutId); - // setLayout(layout) - qDebug() << "set layout" << layoutId; if (!setLayout(layoutId)) { QMessageBox msgBox(this); @@ -1517,22 +1482,28 @@ void MainWindow::on_layoutList_activated(const QModelIndex &index) { void MainWindow::updateMapList() { if (this->editor->map) { - mapGroupModel->setMap(this->editor->map->name); - groupListProxyModel->layoutChanged(); - mapAreaModel->setMap(this->editor->map->name); - areaListProxyModel->layoutChanged(); + this->mapGroupModel->setMap(this->editor->map->name); + this->groupListProxyModel->layoutChanged(); + this->mapAreaModel->setMap(this->editor->map->name); + this->areaListProxyModel->layoutChanged(); } else { - // !TODO - qDebug() << "need to clear map list"; + this->mapGroupModel->setMap(QString()); + this->groupListProxyModel->layoutChanged(); + this->ui->mapList->clearSelection(); + this->mapAreaModel->setMap(QString()); + this->areaListProxyModel->layoutChanged(); + this->ui->areaList->clearSelection(); } if (this->editor->layout) { - layoutTreeModel->setLayout(this->editor->layout->id); - layoutListProxyModel->layoutChanged(); + this->layoutTreeModel->setLayout(this->editor->layout->id); + this->layoutListProxyModel->layoutChanged(); } else { - qDebug() << "need to clear layout list"; + this->layoutTreeModel->setLayout(QString()); + this->layoutListProxyModel->layoutChanged(); + this->ui->layoutList->clearSelection(); } } diff --git a/src/project.cpp b/src/project.cpp index ba273f175..245f3fb8b 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -563,13 +563,12 @@ bool Project::readMapLayouts() { return false; } mapLayouts.insert(layout->id, layout); + mapLayoutsMaster.insert(layout->id, layout->copy()); mapLayoutsTable.append(layout->id); + mapLayoutsTableMaster.append(layout->id); layoutIdsToNames.insert(layout->id, layout->name); } - // Deep copy - mapLayoutsTableMaster = mapLayoutsTable; - mapLayoutsTableMaster.detach(); return true; } @@ -587,7 +586,7 @@ void Project::saveMapLayouts() { bool useCustomBorderSize = projectConfig.getUseCustomBorderSize(); OrderedJson::array layoutsArr; for (QString layoutId : mapLayoutsTableMaster) { - Layout *layout = mapLayouts.value(layoutId); + Layout *layout = mapLayoutsMaster.value(layoutId); OrderedJson::object layoutObj; layoutObj["id"] = layout->id; layoutObj["name"] = layout->name; @@ -1191,14 +1190,14 @@ void Project::setNewMapBorder(Map *map) { map->layout->lastCommitBlocks.borderDimensions = QSize(width, height); } -void Project::saveLayoutBorder(Map *map) { - QString path = QString("%1/%2").arg(root).arg(map->layout->border_path); - writeBlockdata(path, map->layout->border); +void Project::saveLayoutBorder(Layout *layout) { + QString path = QString("%1/%2").arg(root).arg(layout->border_path); + writeBlockdata(path, layout->border); } -void Project::saveLayoutBlockdata(Map* map) { - QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path); - writeBlockdata(path, map->layout->blockdata); +void Project::saveLayoutBlockdata(Layout *layout) { + QString path = QString("%1/%2").arg(root).arg(layout->blockdata_path); + writeBlockdata(path, layout->blockdata); } void Project::writeBlockdata(QString path, const Blockdata &blockdata) { @@ -1353,21 +1352,28 @@ void Project::saveMap(Map *map) { jsonDoc.dump(&mapFile); mapFile.close(); - saveLayoutBorder(map); - saveLayoutBlockdata(map); + saveLayout(map->layout); saveHealLocations(map); - // Update global data structures with current map data. - updateMapLayout(map); - map->isPersistedToFile = true; map->hasUnsavedDataChanges = false; map->editHistory.setClean(); } -void Project::updateMapLayout(Map* map) { - if (!mapLayoutsTableMaster.contains(map->layoutId)) { - mapLayoutsTableMaster.append(map->layoutId); +void Project::saveLayout(Layout *layout) { + // + saveLayoutBorder(layout); + saveLayoutBlockdata(layout); + + // Update global data structures with current map data. + updateLayout(layout); + + layout->editHistory.setClean(); +} + +void Project::updateLayout(Layout *layout) { + if (!mapLayoutsTableMaster.contains(layout->id)) { + mapLayoutsTableMaster.append(layout->id); } // !TODO: why is[was] this a deep copy?? @@ -1376,6 +1382,12 @@ void Project::updateMapLayout(Map* map) { // Layout *newLayout = new Layout(); // *newLayout = *layout; // mapLayoutsMaster.insert(map->layoutId, newLayout); + if (mapLayoutsMaster.contains(layout->id)) { + mapLayoutsMaster[layout->id]->copyFrom(layout); + } + else { + mapLayoutsMaster.insert(layout->id, layout->copy()); + } } void Project::saveAllDataStructures() { From ff086a6fe623763afa0b692a576ff6cfad0ccd8f Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 14 Feb 2023 12:32:37 -0500 Subject: [PATCH 20/70] remove redundant mapsceneeventfilter file --- include/ui/eventfilters.h | 16 ++++++++++++++++ include/ui/mapsceneeventfilter.h | 19 ------------------- porymap.pro | 2 -- src/editor.cpp | 2 +- src/project.cpp | 6 ------ src/ui/eventfilters.cpp | 16 ++++++++++++++++ src/ui/mapsceneeventfilter.cpp | 23 ----------------------- 7 files changed, 33 insertions(+), 51 deletions(-) delete mode 100644 include/ui/mapsceneeventfilter.h delete mode 100644 src/ui/mapsceneeventfilter.cpp diff --git a/include/ui/eventfilters.h b/include/ui/eventfilters.h index 984ce23a3..851c344bd 100644 --- a/include/ui/eventfilters.h +++ b/include/ui/eventfilters.h @@ -3,6 +3,7 @@ +/// Prevent wheel scroll class WheelFilter : public QObject { Q_OBJECT public: @@ -10,3 +11,18 @@ class WheelFilter : public QObject { virtual ~WheelFilter() {} bool eventFilter(QObject *obj, QEvent *event) override; }; + + + +/// Ctrl+Wheel = zoom +class MapSceneEventFilter : public QObject { + Q_OBJECT +protected: + bool eventFilter(QObject *obj, QEvent *event) override; +public: + explicit MapSceneEventFilter(QObject *parent = nullptr) : QObject(parent) {} + +signals: + void wheelZoom(int delta); +public slots: +}; diff --git a/include/ui/mapsceneeventfilter.h b/include/ui/mapsceneeventfilter.h deleted file mode 100644 index 7de427e31..000000000 --- a/include/ui/mapsceneeventfilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MAPSCENEEVENTFILTER_H -#define MAPSCENEEVENTFILTER_H - -#include - -class MapSceneEventFilter : public QObject -{ - Q_OBJECT -protected: - bool eventFilter(QObject *obj, QEvent *event) override; -public: - explicit MapSceneEventFilter(QObject *parent = nullptr); - -signals: - void wheelZoom(int delta); -public slots: -}; - -#endif // MAPSCENEEVENTFILTER_H diff --git a/porymap.pro b/porymap.pro index 04fc6e00d..bf9a200fb 100644 --- a/porymap.pro +++ b/porymap.pro @@ -66,7 +66,6 @@ SOURCES += src/core/block.cpp \ src/ui/prefabcreationdialog.cpp \ src/ui/regionmappixmapitem.cpp \ src/ui/citymappixmapitem.cpp \ - src/ui/mapsceneeventfilter.cpp \ src/ui/metatilelayersitem.cpp \ src/ui/metatileselector.cpp \ src/ui/movablerect.cpp \ @@ -158,7 +157,6 @@ HEADERS += include/core/block.h \ include/ui/prefabcreationdialog.h \ include/ui/regionmappixmapitem.h \ include/ui/citymappixmapitem.h \ - include/ui/mapsceneeventfilter.h \ include/ui/metatilelayersitem.h \ include/ui/metatileselector.h \ include/ui/movablerect.h \ diff --git a/src/editor.cpp b/src/editor.cpp index fc77b2b6d..48b8ce4e0 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -4,7 +4,7 @@ #include "log.h" #include "mapconnection.h" #include "currentselectedmetatilespixmapitem.h" -#include "mapsceneeventfilter.h" +#include "eventfilters.h" #include "metatile.h" #include "montabwidget.h" #include "encountertablemodel.h" diff --git a/src/project.cpp b/src/project.cpp index 245f3fb8b..f2615ebf7 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1376,12 +1376,6 @@ void Project::updateLayout(Layout *layout) { mapLayoutsTableMaster.append(layout->id); } - // !TODO: why is[was] this a deep copy?? - // Deep copy - // Layout *layout = mapLayouts.value(map->layoutId); - // Layout *newLayout = new Layout(); - // *newLayout = *layout; - // mapLayoutsMaster.insert(map->layoutId, newLayout); if (mapLayoutsMaster.contains(layout->id)) { mapLayoutsMaster[layout->id]->copyFrom(layout); } diff --git a/src/ui/eventfilters.cpp b/src/ui/eventfilters.cpp index 24f2e0bd3..1e7b2b804 100644 --- a/src/ui/eventfilters.cpp +++ b/src/ui/eventfilters.cpp @@ -1,5 +1,7 @@ #include "eventfilters.h" +#include + bool WheelFilter::eventFilter(QObject *, QEvent *event) { @@ -8,3 +10,17 @@ bool WheelFilter::eventFilter(QObject *, QEvent *event) { } return false; } + + + +bool MapSceneEventFilter::eventFilter(QObject*, QEvent *event) { + if (event->type() == QEvent::GraphicsSceneWheel) { + QGraphicsSceneWheelEvent *wheelEvent = static_cast(event); + if (wheelEvent->modifiers() & Qt::ControlModifier) { + emit wheelZoom(wheelEvent->delta() > 0 ? 1 : -1); + event->accept(); + return true; + } + } + return false; +} diff --git a/src/ui/mapsceneeventfilter.cpp b/src/ui/mapsceneeventfilter.cpp deleted file mode 100644 index f8ae14cb5..000000000 --- a/src/ui/mapsceneeventfilter.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "mapsceneeventfilter.h" -#include -#include - -MapSceneEventFilter::MapSceneEventFilter(QObject *parent) : QObject(parent) -{ - -} - -bool MapSceneEventFilter::eventFilter(QObject*, QEvent *event) -{ - if (event->type() == QEvent::GraphicsSceneWheel) - { - QGraphicsSceneWheelEvent *wheelEvent = static_cast(event); - if (wheelEvent->modifiers() & Qt::ControlModifier) - { - emit wheelZoom(wheelEvent->delta() > 0 ? 1 : -1); - event->accept(); - return true; - } - } - return false; -} From ac83e0fbe35a49f605e2851360dcb65715344183 Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 14 Feb 2023 20:44:20 -0500 Subject: [PATCH 21/70] no need to manually crop map tab icon --- src/mainwindow.cpp | 46 ++++++++-------------------------------------- src/project.cpp | 2 +- 2 files changed, 9 insertions(+), 39 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index db766c0ce..e9e1e9122 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -330,18 +330,6 @@ void MainWindow::initEditor() { } void MainWindow::initMiscHeapObjects() { - // mapIcon = new QIcon(QStringLiteral(":/icons/map.ico")); - // mapEditedIcon = new QIcon(QStringLiteral(":/icons/map_edited.ico")); - // mapOpenedIcon = new QIcon(QStringLiteral(":/icons/map_opened.ico")); - - /// !TODO - // mapListModel = new QStandardItemModel; - // mapGroupItemsList = new QList; - // mapListProxyModel = new FilterChildrenProxyModel; - - // mapListProxyModel->setSourceModel(mapListModel); - // ui->mapList->setModel(mapListProxyModel); - eventTabObjectWidget = ui->tab_Objects; eventTabWarpWidget = ui->tab_Warps; eventTabTriggerWidget = ui->tab_Triggers; @@ -351,27 +339,13 @@ void MainWindow::initMiscHeapObjects() { ui->tabWidget_EventType->clear(); } -// TODO +// !TODO: scroll view on first showing void MainWindow::initMapSortOrder() { - // QMenu *mapSortOrderMenu = new QMenu(this); - // QActionGroup *mapSortOrderActionGroup = new QActionGroup(ui->toolButton_MapSortOrder); - - // porymapConfig.setMapSortOrder(mapSortOrder); - - // mapSortOrderMenu->addAction(ui->actionSort_by_Group); - // mapSortOrderMenu->addAction(ui->actionSort_by_Area); - // mapSortOrderMenu->addAction(ui->actionSort_by_Layout); - // ui->toolButton_MapSortOrder->setMenu(mapSortOrderMenu); - - // mapSortOrderActionGroup->addAction(ui->actionSort_by_Group); - // mapSortOrderActionGroup->addAction(ui->actionSort_by_Area); - // mapSortOrderActionGroup->addAction(ui->actionSort_by_Layout); - - // connect(mapSortOrderActionGroup, &QActionGroup::triggered, this, &MainWindow::mapSortOrder_changed); + mapSortOrder = porymapConfig.getMapSortOrder(); + if (mapSortOrder == MapSortOrder::SortByLayout) + mapSortOrder = MapSortOrder::SortByGroup; - // QAction* sortOrder = ui->toolButton_MapSortOrder->menu()->actions()[mapSortOrder]; - // ui->toolButton_MapSortOrder->setIcon(sortOrder->icon()); - // sortOrder->setChecked(true); + this->ui->mapListContainer->setCurrentIndex(static_cast(this->mapSortOrder)); } void MainWindow::showWindowTitle() { @@ -391,14 +365,14 @@ void MainWindow::showWindowTitle() { ); } if (editor && editor->layout) { - //QPixmap pixmap = editor->layout ? editor->layout->render(false) : QPixmap(); - QPixmap pixmap = editor->layout->pixmap;//getLayoutItemPixmap(); + QPixmap pixmap = editor->layout->pixmap; if (!pixmap.isNull()) { - ui->mainTabBar->setTabIcon(0, QIcon(pixmap.scaled(16, 16))); + ui->mainTabBar->setTabIcon(0, QIcon(pixmap)); } else { ui->mainTabBar->setTabIcon(0, QIcon(QStringLiteral(":/icons/map.ico"))); } } + updateMapList(); } void MainWindow::markMapEdited() { @@ -485,10 +459,6 @@ void MainWindow::loadUserSettings() { this->editor->settings->cursorTileRectEnabled = porymapConfig.getShowCursorTile(); ui->checkBox_ToggleBorder->setChecked(porymapConfig.getShowBorder()); ui->checkBox_ToggleGrid->setChecked(porymapConfig.getShowGrid()); - mapSortOrder = porymapConfig.getMapSortOrder(); - this->ui->mapListContainer->blockSignals(true); - this->ui->mapListContainer->setCurrentIndex(static_cast(this->mapSortOrder)); - this->ui->mapListContainer->blockSignals(false); ui->horizontalSlider_CollisionTransparency->blockSignals(true); this->editor->collisionOpacity = static_cast(porymapConfig.getCollisionOpacity()) / 100; ui->horizontalSlider_CollisionTransparency->setValue(porymapConfig.getCollisionOpacity()); diff --git a/src/project.cpp b/src/project.cpp index f2615ebf7..0dfb7763f 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -432,7 +432,7 @@ bool Project::loadMapLayout(Map* map) { return false; } - if (map->hasUnsavedChanges() /* || map->layout->hasUnsavedChanges() */) { + if (map->hasUnsavedChanges() || map->layout->hasUnsavedChanges()) { return true; } else { return loadLayout(map->layout); From e79b6e2fcace94df3eb9348b2f6a52ad8203220b Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 21 Feb 2023 11:03:33 -0500 Subject: [PATCH 22/70] add placeholder text for mapgroup label --- src/ui/maplistmodels.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index b4f6e9dce..e3dfba144 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -20,6 +20,7 @@ void MapTree::removeSelected() { QWidget *GroupNameDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { QLineEdit *editor = new QLineEdit(parent); static const QRegularExpression expression("gMapGroup_[A-Za-z0-9_]+"); + editor->setPlaceholderText("gMapGroup_"); QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression, parent); editor->setValidator(validator); editor->setFrame(false); From f485ebdd3e236b10925f7f9e81d340bfbf47bc91 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 22 Feb 2023 15:41:29 -0500 Subject: [PATCH 23/70] preserve layout in config --- include/config.h | 4 ++++ include/mainwindow.h | 8 ++++++-- src/config.cpp | 12 +++++++++++ src/editor.cpp | 2 ++ src/mainwindow.cpp | 49 ++++++++++++++++++++++++++++++++++++-------- 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/include/config.h b/include/config.h index 923abae27..d306fb5d4 100644 --- a/include/config.h +++ b/include/config.h @@ -344,12 +344,15 @@ class UserConfig: public KeyValueConfigBase } virtual void reset() override { this->recentMap = QString(); + this->recentLayout = QString(); this->useEncounterJson = true; this->customScripts.clear(); this->readKeys.clear(); } void setRecentMap(const QString &map); QString getRecentMap(); + void setRecentLayout(const QString &map); + QString getRecentLayout(); void setEncounterJsonActive(bool active); bool getEncounterJsonActive(); void setProjectDir(QString projectDir); @@ -371,6 +374,7 @@ class UserConfig: public KeyValueConfigBase private: QString projectDir; QString recentMap; + QString recentLayout; bool useEncounterJson; QMap customScripts; QStringList readKeys; diff --git a/include/mainwindow.h b/include/mainwindow.h index 522bf0f27..d09fb9174 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -357,10 +357,12 @@ private slots: bool tilesetNeedsRedraw = false; + bool setDefaultView(); + bool setRecentView(); bool setLayout(QString layoutId); - bool setMap(QString, bool scroll = false); void unsetMap(); + void redrawMapScene(); void redrawLayoutScene(); void refreshMapScene(); @@ -373,7 +375,9 @@ private slots: QString getExistingDirectory(QString); bool openProject(QString dir); QString getDefaultMap(); - void setRecentMap(QString map_name); + QString getDefaultLayout(); + void setRecentMapConfig(QString map_name); + void setRecentLayoutConfig(QString layoutId); void updateMapList(); diff --git a/src/config.cpp b/src/config.cpp index 9dddcd427..39c8e807f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1102,6 +1102,8 @@ QString UserConfig::getConfigFilepath() { void UserConfig::parseConfigKeyValue(QString key, QString value) { if (key == "recent_map") { this->recentMap = value; + } else if (key == "recent_layout") { + this->recentLayout = value; } else if (key == "use_encounter_json") { this->useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { @@ -1118,6 +1120,7 @@ void UserConfig::setUnreadKeys() { QMap UserConfig::getKeyValueMap() { QMap map; map.insert("recent_map", this->recentMap); + map.insert("recent_layout", this->recentLayout); map.insert("use_encounter_json", QString::number(this->useEncounterJson)); map.insert("custom_scripts", this->outputCustomScripts()); return map; @@ -1146,6 +1149,15 @@ QString UserConfig::getRecentMap() { return this->recentMap; } +void UserConfig::setRecentLayout(const QString &layout) { + this->recentLayout = layout; + this->save(); +} + +QString UserConfig::getRecentLayout() { + return this->recentLayout; +} + void UserConfig::setEncounterJsonActive(bool active) { this->useEncounterJson = active; this->save(); diff --git a/src/editor.cpp b/src/editor.cpp index 48b8ce4e0..d5d48e6ab 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1164,6 +1164,8 @@ bool Editor::setMap(QString map_name) { bool Editor::setLayout(QString layoutId) { // + if (layoutId.isEmpty()) return false; + this->layout = this->project->loadLayout(layoutId); if (!displayLayout()) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e9e1e9122..02ae9ace8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -342,8 +342,8 @@ void MainWindow::initMiscHeapObjects() { // !TODO: scroll view on first showing void MainWindow::initMapSortOrder() { mapSortOrder = porymapConfig.getMapSortOrder(); - if (mapSortOrder == MapSortOrder::SortByLayout) - mapSortOrder = MapSortOrder::SortByGroup; + // if (mapSortOrder == MapSortOrder::SortByLayout) + // mapSortOrder = MapSortOrder::SortByGroup; this->ui->mapListContainer->setCurrentIndex(static_cast(this->mapSortOrder)); } @@ -541,16 +541,13 @@ bool MainWindow::openProject(QString dir) { this->preferenceEditor->updateFields(); }); editor->project->set_root(dir); - success = loadDataStructures() - && populateMapList() - && setMap(getDefaultMap(), true); + success = loadDataStructures() && populateMapList() && setDefaultView(); } else { - QString open_map = editor->map->name; editor->project->fileWatcher.removePaths(editor->project->fileWatcher.files()); editor->project->clearLayoutsTable(); editor->project->clearMapCache(); editor->project->clearTilesetCache(); - success = loadDataStructures() && populateMapList() && setMap(open_map, true); + success = loadDataStructures() && populateMapList() && setRecentView(); } projectOpenFailure = !success; @@ -581,6 +578,22 @@ bool MainWindow::isProjectOpen() { return !projectOpenFailure && editor && editor->project; } +bool MainWindow::setDefaultView() { + if (this->mapSortOrder == MapSortOrder::SortByLayout) { + return setLayout(getDefaultLayout()); + } else { + return setMap(getDefaultMap(), true); + } +} + +bool MainWindow::setRecentView() { + if (this->mapSortOrder == MapSortOrder::SortByLayout) { + return setLayout(userConfig.getRecentLayout()); + } else { + return setMap(userConfig.getRecentMap(), true); + } +} + QString MainWindow::getDefaultMap() { if (editor && editor->project) { QList names = editor->project->groupedMapNames; @@ -618,6 +631,18 @@ void MainWindow::openSubWindow(QWidget * window) { } } +QString MainWindow::getDefaultLayout() { + if (editor && editor->project) { + QString recentLayout = userConfig.getRecentLayout(); + if (!recentLayout.isEmpty() && editor->project->mapLayoutsTable.contains(recentLayout)) { + return recentLayout; + } else if (!editor->project->mapLayoutsTable.isEmpty()) { + return editor->project->mapLayoutsTable.first(); + } + } + return QString(); +} + QString MainWindow::getExistingDirectory(QString dir) { return QFileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly); } @@ -707,7 +732,7 @@ bool MainWindow::setMap(QString map_name, bool scroll) { connect(editor->layout, &Layout::layoutChanged, [this]() { onMapChanged(nullptr); }); connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing); - setRecentMap(map_name); + setRecentMapConfig(map_name); updateMapList(); Scripting::cb_MapOpened(map_name); @@ -741,6 +766,8 @@ bool MainWindow::setLayout(QString layoutId) { updateTilesetEditor(); + setRecentLayoutConfig(layoutId); + return true; } @@ -825,10 +852,14 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_ } } -void MainWindow::setRecentMap(QString mapName) { +void MainWindow::setRecentMapConfig(QString mapName) { userConfig.setRecentMap(mapName); } +void MainWindow::setRecentLayoutConfig(QString layoutId) { + userConfig.setRecentLayout(layoutId); +} + void MainWindow::displayMapProperties() { // Block signals to the comboboxes while they are being modified const QSignalBlocker blocker1(ui->comboBox_Song); From 2d2b7f723bc1439732732bfbd61d5f3101f558f2 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 22 Feb 2023 15:51:16 -0500 Subject: [PATCH 24/70] api util setMainTab ignores command when in layout only mode --- src/scriptapi/apiutility.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/scriptapi/apiutility.cpp b/src/scriptapi/apiutility.cpp index 712a81716..1b8d8afee 100644 --- a/src/scriptapi/apiutility.cpp +++ b/src/scriptapi/apiutility.cpp @@ -144,6 +144,9 @@ void ScriptUtility::setMainTab(int index) { // Can't select Wild Encounters tab if it's disabled if (index == 4 && !userConfig.getEncounterJsonActive()) return; + // don't change tab when not editing a map + if (!window->editor || !window->editor->map) + return; window->on_mainTabBar_tabBarClicked(index); } From f4cd57c9887cdc5216d1ef3e1734e8b99a6b0055 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 7 Apr 2023 21:50:46 -0400 Subject: [PATCH 25/70] some code cleanup --- include/core/editcommands.h | 35 +++-- include/core/maplayout.h | 2 +- include/core/regionmapeditcommands.h | 4 +- include/editor.h | 19 +-- include/ui/layoutpixmapitem.h | 14 +- src/core/editcommands.cpp | 55 ++++--- src/core/regionmapeditcommands.cpp | 10 +- src/editor.cpp | 220 ++++++++++++--------------- src/mainwindow.cpp | 10 +- src/project.cpp | 4 +- src/scriptapi/apimap.cpp | 4 +- src/ui/collisionpixmapitem.cpp | 4 +- src/ui/layoutpixmapitem.cpp | 4 +- src/ui/mapimageexporter.cpp | 4 +- src/ui/newmappopup.cpp | 1 - src/ui/regionmapeditor.cpp | 4 +- 16 files changed, 184 insertions(+), 210 deletions(-) diff --git a/include/core/editcommands.h b/include/core/editcommands.h index 7d89a35a7..691746c0e 100644 --- a/include/core/editcommands.h +++ b/include/core/editcommands.h @@ -22,9 +22,9 @@ enum CommandId { ID_PaintCollision, ID_BucketFillCollision, ID_MagicFillCollision, - ID_ResizeMap, + ID_ResizeLayout, ID_PaintBorder, - ID_ScriptEditMap, + ID_ScriptEditLayout, ID_EventMove, ID_EventShift, ID_EventCreate, @@ -194,9 +194,9 @@ class ShiftMetatiles : public QUndoCommand { /// Implements a command to commit a map or border resize action. -class ResizeMap : public QUndoCommand { +class ResizeLayout : public QUndoCommand { public: - ResizeMap(Layout *layout, QSize oldMapDimensions, QSize newMapDimensions, + ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QSize newLayoutDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, QSize oldBorderDimensions, QSize newBorderDimensions, const Blockdata &oldBorder, const Blockdata &newBorder, @@ -206,15 +206,15 @@ class ResizeMap : public QUndoCommand { void redo() override; bool mergeWith(const QUndoCommand *) override { return false; } - int id() const override { return CommandId::ID_ResizeMap; } + int id() const override { return CommandId::ID_ResizeLayout; } private: Layout *layout = nullptr; - int oldMapWidth; - int oldMapHeight; - int newMapWidth; - int newMapHeight; + int oldLayoutWidth; + int oldLayoutHeight; + int newLayoutWidth; + int newLayoutHeight; int oldBorderWidth; int oldBorderHeight; @@ -342,13 +342,12 @@ class EventPaste : public EventDuplicate { -// !TODO: rename map vars to layout /// Implements a command to commit map edits from the scripting API. /// The scripting api can edit map/border blocks and dimensions. -class ScriptEditMap : public QUndoCommand { +class ScriptEditLayout : public QUndoCommand { public: - ScriptEditMap(Layout *layout, - QSize oldMapDimensions, QSize newMapDimensions, + ScriptEditLayout(Layout *layout, + QSize oldLayoutDimensions, QSize newLayoutDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, QSize oldBorderDimensions, QSize newBorderDimensions, const Blockdata &oldBorder, const Blockdata &newBorder, @@ -358,7 +357,7 @@ class ScriptEditMap : public QUndoCommand { void redo() override; bool mergeWith(const QUndoCommand *) override { return false; } - int id() const override { return CommandId::ID_ScriptEditMap; } + int id() const override { return CommandId::ID_ScriptEditLayout; } private: Layout *layout = nullptr; @@ -369,10 +368,10 @@ class ScriptEditMap : public QUndoCommand { Blockdata newBorder; Blockdata oldBorder; - int oldMapWidth; - int oldMapHeight; - int newMapWidth; - int newMapHeight; + int oldLayoutWidth; + int oldLayoutHeight; + int newLayoutWidth; + int newLayoutHeight; int oldBorderWidth; int oldBorderHeight; diff --git a/include/core/maplayout.h b/include/core/maplayout.h index c17248cee..7ec240b6e 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -55,7 +55,7 @@ class Layout : public QObject { Blockdata cached_border; struct { Blockdata blocks; - QSize mapDimensions; + QSize layoutDimensions; Blockdata border; QSize borderDimensions; } lastCommitBlocks; // to track map changes diff --git a/include/core/regionmapeditcommands.h b/include/core/regionmapeditcommands.h index 69bea2510..e142c5ccf 100644 --- a/include/core/regionmapeditcommands.h +++ b/include/core/regionmapeditcommands.h @@ -64,9 +64,9 @@ class EditLayout : public QUndoCommand { /// Edit Layout Dimensions -class ResizeLayout : public QUndoCommand { +class ResizeRMLayout : public QUndoCommand { public: - ResizeLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight, + ResizeRMLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight, QMap> oldLayouts, QMap> newLayouts, QUndoCommand *parent = nullptr); void undo() override; diff --git a/include/editor.h b/include/editor.h index d6d973b5c..c3e0c5ffe 100644 --- a/include/editor.h +++ b/include/editor.h @@ -46,8 +46,8 @@ class Editor : public QObject QObject *parent = nullptr; Project *project = nullptr; - QPointer map = nullptr; // !TODO: since removed onMapCacheCleared, make sure this works as intended - QPointer layout = nullptr; /* NEW */ + QPointer map = nullptr; + QPointer layout = nullptr; QUndoGroup editGroup; // Manages the undo history for each map @@ -118,8 +118,6 @@ class Editor : public QObject void updateCursorRectPos(int x, int y); void setCursorRectVisible(bool visible); - - QGraphicsScene *scene = nullptr; QGraphicsPixmapItem *current_view = nullptr; LayoutPixmapItem *map_item = nullptr; @@ -154,15 +152,18 @@ class Editor : public QObject EditAction mapEditAction = EditAction::Paint; EditAction objectEditAction = EditAction::Select; - /// !TODO this - enum class EditMode { None, Disabled, Map, Layout, Objects, Connections, Encounters }; - EditMode editMode = EditMode::Map; + enum class EditMode { None, Disabled, Metatiles, Collision, Header, Events, Connections, Encounters }; + EditMode editMode = EditMode::None; void setEditMode(EditMode mode) { this->editMode = mode; } EditMode getEditMode() { return this->editMode; } - void setEditingMap(); + bool getEditingLayout(); + + void setEditorView(); + + void setEditingMetatiles(); void setEditingCollision(); - void setEditingLayout(); + void setEditingHeader(); void setEditingObjects(); void setEditingConnections(); void setEditingEncounters(); diff --git a/include/ui/layoutpixmapitem.h b/include/ui/layoutpixmapitem.h index ab4d94a51..08496c54c 100644 --- a/include/ui/layoutpixmapitem.h +++ b/include/ui/layoutpixmapitem.h @@ -14,25 +14,16 @@ class LayoutPixmapItem : public QObject, public QGraphicsPixmapItem { using QGraphicsPixmapItem::paint; public: - enum class PaintMode { - Disabled, - Metatiles, - EventObjects - }; - LayoutPixmapItem(Layout *layout, MetatileSelector *metatileSelector, Settings *settings) { this->layout = layout; // this->map->setMapItem(this); this->metatileSelector = metatileSelector; this->settings = settings; - this->paintingMode = PaintMode::Metatiles; this->lockedAxis = LayoutPixmapItem::Axis::None; this->prevStraightPathState = false; setAcceptHoverEvents(true); } - LayoutPixmapItem::PaintMode paintingMode; - Layout *layout; MetatileSelector *metatileSelector; @@ -95,12 +86,17 @@ class LayoutPixmapItem : public QObject, public QGraphicsPixmapItem { void lockNondominantAxis(QGraphicsSceneMouseEvent *event); QPoint adjustCoords(QPoint pos); + void setEditsEnabled(bool enabled) { this->editsEnabled = enabled; } + bool getEditsEnabled() { return this->editsEnabled; } + private: void paintSmartPath(int x, int y, bool fromScriptCall = false); static QList smartPathTable; unsigned actionId_ = 0; + bool editsEnabled = true; + signals: void startPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *); void endPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *); diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp index a20969056..22227b423 100644 --- a/src/core/editcommands.cpp +++ b/src/core/editcommands.cpp @@ -24,7 +24,6 @@ int getEventTypeMask(QList events) { return eventTypeMask; } -/// !TODO: void renderBlocks(Layout *layout, bool ignoreCache = false) { layout->layoutItem->draw(ignoreCache); layout->collisionItem->draw(ignoreCache); @@ -178,7 +177,7 @@ bool ShiftMetatiles::mergeWith(const QUndoCommand *command) { ************************************************************************ ******************************************************************************/ -ResizeMap::ResizeMap(Layout *layout, QSize oldMapDimensions, QSize newMapDimensions, +ResizeLayout::ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QSize newLayoutDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, QSize oldBorderDimensions, QSize newBorderDimensions, const Blockdata &oldBorder, const Blockdata &newBorder, @@ -187,11 +186,11 @@ ResizeMap::ResizeMap(Layout *layout, QSize oldMapDimensions, QSize newMapDimensi this->layout = layout; - this->oldMapWidth = oldMapDimensions.width(); - this->oldMapHeight = oldMapDimensions.height(); + this->oldLayoutWidth = oldLayoutDimensions.width(); + this->oldLayoutHeight = oldLayoutDimensions.height(); - this->newMapWidth = newMapDimensions.width(); - this->newMapHeight = newMapDimensions.height(); + this->newLayoutWidth = newLayoutDimensions.width(); + this->newLayoutHeight = newLayoutDimensions.height(); this->oldMetatiles = oldMetatiles; this->newMetatiles = newMetatiles; @@ -206,33 +205,33 @@ ResizeMap::ResizeMap(Layout *layout, QSize oldMapDimensions, QSize newMapDimensi this->newBorder = newBorder; } -void ResizeMap::redo() { +void ResizeLayout::redo() { QUndoCommand::redo(); if (!layout) return; layout->blockdata = newMetatiles; - layout->setDimensions(newMapWidth, newMapHeight, false, true); + layout->setDimensions(newLayoutWidth, newLayoutHeight, false, true); layout->border = newBorder; layout->setBorderDimensions(newBorderWidth, newBorderHeight, false, true); - layout->lastCommitBlocks.mapDimensions = QSize(layout->getWidth(), layout->getHeight()); + layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight()); layout->lastCommitBlocks.borderDimensions = QSize(layout->getBorderWidth(), layout->getBorderHeight()); layout->needsRedrawing(); } -void ResizeMap::undo() { +void ResizeLayout::undo() { if (!layout) return; layout->blockdata = oldMetatiles; - layout->setDimensions(oldMapWidth, oldMapHeight, false, true); + layout->setDimensions(oldLayoutWidth, oldLayoutHeight, false, true); layout->border = oldBorder; layout->setBorderDimensions(oldBorderWidth, oldBorderHeight, false, true); - layout->lastCommitBlocks.mapDimensions = QSize(layout->getWidth(), layout->getHeight()); + layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight()); layout->lastCommitBlocks.borderDimensions = QSize(layout->getBorderWidth(), layout->getBorderHeight()); layout->needsRedrawing(); @@ -487,23 +486,23 @@ int EventPaste::id() const { ************************************************************************ ******************************************************************************/ -ScriptEditMap::ScriptEditMap(Layout *layout, - QSize oldMapDimensions, QSize newMapDimensions, +ScriptEditLayout::ScriptEditLayout(Layout *layout, + QSize oldLayoutDimensions, QSize newLayoutDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, QSize oldBorderDimensions, QSize newBorderDimensions, const Blockdata &oldBorder, const Blockdata &newBorder, QUndoCommand *parent) : QUndoCommand(parent) { - setText("Script Edit Map"); + setText("Script Edit Layout"); this->layout = layout; this->newMetatiles = newMetatiles; this->oldMetatiles = oldMetatiles; - this->oldMapWidth = oldMapDimensions.width(); - this->oldMapHeight = oldMapDimensions.height(); - this->newMapWidth = newMapDimensions.width(); - this->newMapHeight = newMapDimensions.height(); + this->oldLayoutWidth = oldLayoutDimensions.width(); + this->oldLayoutHeight = oldLayoutDimensions.height(); + this->newLayoutWidth = newLayoutDimensions.width(); + this->newLayoutHeight = newLayoutDimensions.height(); this->oldBorder = oldBorder; this->newBorder = newBorder; @@ -514,14 +513,14 @@ ScriptEditMap::ScriptEditMap(Layout *layout, this->newBorderHeight = newBorderDimensions.height(); } -void ScriptEditMap::redo() { +void ScriptEditLayout::redo() { QUndoCommand::redo(); if (!layout) return; - if (newMapWidth != layout->getWidth() || newMapHeight != layout->getHeight()) { + if (newLayoutWidth != layout->getWidth() || newLayoutHeight != layout->getHeight()) { layout->blockdata = newMetatiles; - layout->setDimensions(newMapWidth, newMapHeight, false); + layout->setDimensions(newLayoutWidth, newLayoutHeight, false); } else { layout->setBlockdata(newMetatiles); } @@ -534,21 +533,20 @@ void ScriptEditMap::redo() { } layout->lastCommitBlocks.blocks = newMetatiles; - layout->lastCommitBlocks.mapDimensions = QSize(newMapWidth, newMapHeight); + layout->lastCommitBlocks.layoutDimensions = QSize(newLayoutWidth, newLayoutHeight); layout->lastCommitBlocks.border = newBorder; layout->lastCommitBlocks.borderDimensions = QSize(newBorderWidth, newBorderHeight); - // !TODO renderBlocks(layout); layout->borderItem->draw(); } -void ScriptEditMap::undo() { +void ScriptEditLayout::undo() { if (!layout) return; - if (oldMapWidth != layout->getWidth() || oldMapHeight != layout->getHeight()) { + if (oldLayoutWidth != layout->getWidth() || oldLayoutHeight != layout->getHeight()) { layout->blockdata = oldMetatiles; - layout->setDimensions(oldMapWidth, oldMapHeight, false); + layout->setDimensions(oldLayoutWidth, oldLayoutHeight, false); } else { layout->setBlockdata(oldMetatiles); } @@ -561,11 +559,10 @@ void ScriptEditMap::undo() { } layout->lastCommitBlocks.blocks = oldMetatiles; - layout->lastCommitBlocks.mapDimensions = QSize(oldMapWidth, oldMapHeight); + layout->lastCommitBlocks.layoutDimensions = QSize(oldLayoutWidth, oldLayoutHeight); layout->lastCommitBlocks.border = oldBorder; layout->lastCommitBlocks.borderDimensions = QSize(oldBorderWidth, oldBorderHeight); - // !TODO renderBlocks(layout); layout->borderItem->draw(); diff --git a/src/core/regionmapeditcommands.cpp b/src/core/regionmapeditcommands.cpp index e718d596e..1be247b02 100644 --- a/src/core/regionmapeditcommands.cpp +++ b/src/core/regionmapeditcommands.cpp @@ -90,7 +90,7 @@ bool EditLayout::mergeWith(const QUndoCommand *command) { /// -ResizeLayout::ResizeLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight, +ResizeRMLayout::ResizeRMLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight, QMap> oldLayouts, QMap> newLayouts, QUndoCommand *parent) : QUndoCommand(parent) { setText("Change Layout Dimensions"); @@ -104,7 +104,7 @@ ResizeLayout::ResizeLayout(RegionMap *map, int oldWidth, int oldHeight, int newW this->newLayouts = newLayouts; } -void ResizeLayout::redo() { +void ResizeRMLayout::redo() { QUndoCommand::redo(); if (!map) return; @@ -113,7 +113,7 @@ void ResizeLayout::redo() { map->setAllLayouts(this->newLayouts); } -void ResizeLayout::undo() { +void ResizeRMLayout::undo() { if (!map) return; map->setLayoutDimensions(oldWidth, oldHeight, false); @@ -122,8 +122,8 @@ void ResizeLayout::undo() { QUndoCommand::undo(); } -bool ResizeLayout::mergeWith(const QUndoCommand *command) { - const ResizeLayout *other = static_cast(command); +bool ResizeRMLayout::mergeWith(const QUndoCommand *command) { + const ResizeRMLayout *other = static_cast(command); if (this->map != other->map) return false; diff --git a/src/editor.cpp b/src/editor.cpp index d5d48e6ab..06cc771fe 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -83,130 +83,119 @@ void Editor::closeProject() { } } -void Editor::setEditingMap() { - current_view = map_item; - if (map_item) { - map_item->paintingMode = LayoutPixmapItem::PaintMode::Metatiles; - displayMapConnections(); - map_item->draw(); - map_item->setVisible(true); - } - if (collision_item) { - collision_item->setVisible(false); - } - if (events_group) { - events_group->setVisible(false); +bool Editor::getEditingLayout() { + return this->editMode == EditMode::Metatiles || this->editMode == EditMode::Collision; +} + +void Editor::setEditorView() { + // based on editMode + if (!map_item || !collision_item) return; + if (!this->layout) return; + + map_item->setVisible(true); // is map item ever not visible + collision_item->setVisible(false); + + switch (this->editMode) { + case EditMode::Metatiles: + case EditMode::Connections: + case EditMode::Events: + current_view = map_item; + break; + case EditMode::Collision: + current_view = collision_item; + break; + default: + current_view = nullptr; + return; } + + map_item->draw(); + collision_item->draw(); + displayMapConnections(); + + current_view->setVisible(true); + setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); setConnectionItemsVisible(ui->checkBox_ToggleBorder->isChecked()); setConnectionsEditable(false); - this->cursorMapTileRect->stopSingleTileMode(); + this->cursorMapTileRect->setSingleTileMode(); this->cursorMapTileRect->setActive(true); - if (this->layout) { + switch (this->editMode) { + case EditMode::Metatiles: + case EditMode::Collision: this->editGroup.setActiveStack(&this->layout->editHistory); + break; + case EditMode::Events: + if (this->map) { + this->editGroup.setActiveStack(&this->map->editHistory); + } + break; + case EditMode::Connections: + populateConnectionMapPickers(); // !TODO: move to setmap or sumn/ displaymapconnections type ish + ui->label_NumConnections->setText(QString::number(map->connections.length())); + setDiveEmergeControls(); + + setConnectionEditControlsEnabled(selected_connection_item != nullptr); + if (selected_connection_item) { + onConnectionOffsetChanged(selected_connection_item->connection->offset); + setConnectionMap(selected_connection_item->connection->map_name); + setCurrentConnectionDirection(selected_connection_item->connection->direction); + } + maskNonVisibleConnectionTiles(); + + setBorderItemsVisible(true, 0.4); + setConnectionItemsVisible(true); + setConnectionsEditable(true); + this->cursorMapTileRect->setActive(false); + map_item->setEditsEnabled(false); // !TODO + case EditMode::Header: + case EditMode::Encounters: + default: + this->editGroup.setActiveStack(nullptr); + break; } - setMapEditingButtonsEnabled(true); + if (this->events_group) { + this->events_group->setVisible(this->editMode == EditMode::Events); + } + setMapEditingButtonsEnabled(this->editMode != EditMode::Events); } -void Editor::setEditingLayout() { - // +void Editor::setEditingMetatiles() { + this->editMode = EditMode::Metatiles; + + setEditorView(); } void Editor::setEditingCollision() { - current_view = collision_item; - if (collision_item) { - displayMapConnections(); - collision_item->draw(); - collision_item->setVisible(true); - } - if (map_item) { - map_item->paintingMode = LayoutPixmapItem::PaintMode::Metatiles; - map_item->draw(); - map_item->setVisible(true); - } - if (events_group) { - events_group->setVisible(false); - } - setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionsEditable(false); - this->cursorMapTileRect->setSingleTileMode(); - this->cursorMapTileRect->setActive(true); + this->editMode = EditMode::Collision; - if (this->layout) { - this->editGroup.setActiveStack(&this->layout->editHistory); - } + setEditorView(); +} + +void Editor::setEditingHeader() { + this->editMode = EditMode::Header; - setMapEditingButtonsEnabled(true); + setEditorView(); } void Editor::setEditingObjects() { - current_view = map_item; - if (events_group) { - events_group->setVisible(true); - } - if (map_item) { - // !TODO: change this pixmapitem paintmode - map_item->paintingMode = LayoutPixmapItem::PaintMode::EventObjects; - displayMapConnections(); - map_item->draw(); - map_item->setVisible(true); - } - if (collision_item) { - collision_item->setVisible(false); - } - setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionItemsVisible(ui->checkBox_ToggleBorder->isChecked()); - setConnectionsEditable(false); - this->cursorMapTileRect->setSingleTileMode(); - this->cursorMapTileRect->setActive(false); - - if (this->map) { - this->editGroup.setActiveStack(&this->map->editHistory); - } + this->editMode = EditMode::Events; - setMapEditingButtonsEnabled(false); + setEditorView(); } void Editor::setEditingConnections() { - current_view = map_item; - if (map_item) { - map_item->paintingMode = LayoutPixmapItem::PaintMode::Disabled; - map_item->draw(); - map_item->setVisible(true); - populateConnectionMapPickers(); - ui->label_NumConnections->setText(QString::number(map->connections.length())); - setDiveEmergeControls(); - bool controlsEnabled = selected_connection_item != nullptr; - setConnectionEditControlsEnabled(controlsEnabled); - if (selected_connection_item) { - onConnectionOffsetChanged(selected_connection_item->connection->offset); - setConnectionMap(selected_connection_item->connection->map_name); - setCurrentConnectionDirection(selected_connection_item->connection->direction); - } - maskNonVisibleConnectionTiles(); - } - if (collision_item) { - collision_item->setVisible(false); - } - if (events_group) { - events_group->setVisible(false); - } - setBorderItemsVisible(true, 0.4); - setConnectionItemsVisible(true); - setConnectionsEditable(true); - this->cursorMapTileRect->setSingleTileMode(); - this->cursorMapTileRect->setActive(false); + this->editMode = EditMode::Connections; - if (this->map) { - this->editGroup.setActiveStack(&this->map->editHistory); - } + setEditorView(); } void Editor::setEditingEncounters() { - // + this->editMode = EditMode::Encounters; + + setEditorView(); } void Editor::setMapEditingButtonsEnabled(bool enabled) { @@ -1048,7 +1037,7 @@ void Editor::onHoveredMapMetatileChanged(const QPoint &pos) { return; this->updateCursorRectPos(x, y); - if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { + if (this->getEditingLayout()) { int blockIndex = y * layout->getWidth() + x; int metatileId = layout->blockdata.at(blockIndex).metatileId; this->ui->statusBar->showMessage(QString("X: %1, Y: %2, %3, Scale = %4x") @@ -1057,19 +1046,19 @@ void Editor::onHoveredMapMetatileChanged(const QPoint &pos) { .arg(getMetatileDisplayMessage(metatileId)) .arg(QString::number(zoomLevels[this->scaleIndex], 'g', 2))); } - else if (map_item->paintingMode == LayoutPixmapItem::PaintMode::EventObjects) { + else if (this->editMode == EditMode::Events) { this->ui->statusBar->showMessage(QString("X: %1, Y: %2, Scale = %3x") .arg(x) .arg(y) .arg(QString::number(zoomLevels[this->scaleIndex], 'g', 2))); } + Scripting::cb_BlockHoverChanged(x, y); } void Editor::onHoveredMapMetatileCleared() { this->setCursorRectVisible(false); - if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles - || map_item->paintingMode == LayoutPixmapItem::PaintMode::EventObjects) { + if (!map_item->getEditsEnabled()) { this->ui->statusBar->clearMessage(); } Scripting::cb_BlockHoverCleared(); @@ -1080,7 +1069,7 @@ void Editor::onHoveredMapMovementPermissionChanged(int x, int y) { return; this->updateCursorRectPos(x, y); - if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { + if (this->getEditingLayout()) { int blockIndex = y * layout->getWidth() + x; uint16_t collision = layout->blockdata.at(blockIndex).collision; uint16_t elevation = layout->blockdata.at(blockIndex).elevation; @@ -1095,7 +1084,7 @@ void Editor::onHoveredMapMovementPermissionChanged(int x, int y) { void Editor::onHoveredMapMovementPermissionCleared() { this->setCursorRectVisible(false); - if (map_item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { + if (this->getEditingLayout()) { this->ui->statusBar->clearMessage(); } Scripting::cb_BlockHoverCleared(); @@ -1142,14 +1131,11 @@ bool Editor::setMap(QString map_name) { 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; @@ -1163,7 +1149,6 @@ bool Editor::setMap(QString map_name) { } bool Editor::setLayout(QString layoutId) { - // if (layoutId.isEmpty()) return false; this->layout = this->project->loadLayout(layoutId); @@ -1172,8 +1157,6 @@ bool Editor::setLayout(QString layoutId) { return false; } - // !TODO: editGroup addStack - editGroup.addStack(&layout->editHistory); map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight())); @@ -1195,7 +1178,7 @@ bool Editor::setLayout(QString layoutId) { } void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) { - if (item->paintingMode != LayoutPixmapItem::PaintMode::Metatiles) { + if (!this->getEditingLayout()) { return; } @@ -1208,7 +1191,7 @@ void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem * } void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *item) { - if (!(item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles)) { + if (!this->getEditingLayout()) { return; } this->cursorMapTileRect->stopRightClickSelectionAnchor(); @@ -1243,13 +1226,13 @@ void Editor::setStraightPathCursorMode(QGraphicsSceneMouseEvent *event) { void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) { // TODO: add event tab object painting tool buttons stuff here - if (item->paintingMode == LayoutPixmapItem::PaintMode::Disabled) { + if (!item->getEditsEnabled()) { return; } QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); - if (item->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { + if (this->getEditingLayout()) { if (mapEditAction == EditAction::Paint) { if (event->buttons() & Qt::RightButton) { item->updateMetatileSelection(event); @@ -1296,7 +1279,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i } item->shift(event); } - } else if (item->paintingMode == LayoutPixmapItem::PaintMode::EventObjects) { + } else if (this->editMode == EditMode::Events) { if (objectEditAction == EditAction::Paint && event->type() == QEvent::GraphicsSceneMousePress) { // Right-clicking while in paint mode will change mode to select. if (event->buttons() & Qt::RightButton) { @@ -1354,7 +1337,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i } void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) { - if (item->paintingMode != LayoutPixmapItem::PaintMode::Metatiles) { + if (!item->getEditsEnabled()) { return; } @@ -1426,7 +1409,6 @@ bool Editor::displayLayout() { scene->removeItem(this->map_ruler); } - // !TODO: disassociate these functions from Map displayMetatileSelector(); displayMapMetatiles(); displayMovementPermissionSelector(); @@ -2116,7 +2098,7 @@ void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) { } void Editor::duplicateSelectedEvents() { - if (!selected_events || !selected_events->length() || !map || !current_view || map_item->paintingMode != LayoutPixmapItem::PaintMode::EventObjects) + if (!selected_events || !selected_events->length() || !map || !current_view || this->getEditingLayout()) return; QList selectedEvents; @@ -2288,7 +2270,7 @@ bool Editor::startDetachedProcess(const QString &command, const QString &working // is clicking on the background instead of an event. void Editor::objectsView_onMousePress(QMouseEvent *event) { // make sure we are in object editing mode - if (map_item && map_item->paintingMode != LayoutPixmapItem::PaintMode::EventObjects) { + if (map_item && this->editMode != EditMode::Events) { return; } if (this->objectEditAction == EditAction::Paint && event->buttons() & Qt::RightButton) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 02ae9ace8..5844afaa2 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1780,11 +1780,11 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index) Scripting::cb_MapViewTabChanged(oldIndex, index); if (index == 0) { - editor->setEditingMap(); + editor->setEditingMetatiles(); } else if (index == 1) { editor->setEditingCollision(); } else if (index == 2) { - editor->setEditingMap(); + editor->setEditingMetatiles(); if (projectConfig.getPrefabFilepath().isEmpty() && !projectConfig.getPrefabImportPrompted()) { // User hasn't set up prefabs and hasn't been prompted before. // Ask if they'd like to import the default prefabs file. @@ -1802,8 +1802,6 @@ 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) @@ -1822,6 +1820,8 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index) clickToolButtonFromEditAction(editor->objectEditAction); } else if (index == 3) { editor->setEditingConnections(); + } else if (index == 4) { + editor->setEditingEncounters(); } if (!editor->map) return; @@ -2727,7 +2727,7 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() { if (oldMapDimensions != newMapDimensions || oldBorderDimensions != newBorderDimensions) { layout->setDimensions(newMapDimensions.width(), newMapDimensions.height(), true, true); layout->setBorderDimensions(newBorderDimensions.width(), newBorderDimensions.height(), true, true); - editor->layout->editHistory.push(new ResizeMap(layout, + editor->layout->editHistory.push(new ResizeLayout(layout, oldMapDimensions, newMapDimensions, oldMetatiles, layout->blockdata, oldBorderDimensions, newBorderDimensions, diff --git a/src/project.cpp b/src/project.cpp index 0dfb7763f..096579557 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1126,7 +1126,7 @@ bool Project::loadBlockdata(Layout *layout) { QString path = QString("%1/%2").arg(root).arg(layout->blockdata_path); layout->blockdata = readBlockdata(path); layout->lastCommitBlocks.blocks = layout->blockdata; - layout->lastCommitBlocks.mapDimensions = QSize(layout->getWidth(), layout->getHeight()); + layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight()); if (layout->blockdata.count() != layout->getWidth() * layout->getHeight()) { logWarn(QString("Layout blockdata length %1 does not match dimensions %2x%3 (should be %4). Resizing blockdata.") @@ -1148,7 +1148,7 @@ void Project::setNewMapBlockdata(Map *map) { map->layout->blockdata.append(block); } map->layout->lastCommitBlocks.blocks = map->layout->blockdata; - map->layout->lastCommitBlocks.mapDimensions = QSize(width, height); + map->layout->lastCommitBlocks.layoutDimensions = QSize(width, height); } bool Project::loadLayoutBorder(Layout *layout) { diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index 155d34926..ea18e0cc9 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -44,8 +44,8 @@ void MainWindow::tryCommitMapChanges(bool commitChanges) { if (commitChanges) { Layout *layout = this->editor->layout; if (layout) { - layout->editHistory.push(new ScriptEditMap(layout, - layout->lastCommitBlocks.mapDimensions, QSize(layout->getWidth(), layout->getHeight()), + layout->editHistory.push(new ScriptEditLayout(layout, + layout->lastCommitBlocks.layoutDimensions, QSize(layout->getWidth(), layout->getHeight()), layout->lastCommitBlocks.blocks, layout->blockdata, layout->lastCommitBlocks.borderDimensions, QSize(layout->getBorderWidth(), layout->getBorderHeight()), layout->lastCommitBlocks.border, layout->border diff --git a/src/ui/collisionpixmapitem.cpp b/src/ui/collisionpixmapitem.cpp index 0c809c3f1..3a3c62a01 100644 --- a/src/ui/collisionpixmapitem.cpp +++ b/src/ui/collisionpixmapitem.cpp @@ -8,7 +8,7 @@ void CollisionPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { this->previousPos = pos; emit this->hoveredMapMovementPermissionChanged(pos.x(), pos.y()); } - if (this->settings->betterCursors && this->paintingMode == LayoutPixmapItem::PaintMode::Metatiles) { + if (this->settings->betterCursors && this->getEditsEnabled()) { setCursor(this->settings->mapCursor); } } @@ -21,7 +21,7 @@ void CollisionPixmapItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) { void CollisionPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { emit this->hoveredMapMovementPermissionCleared(); - if (this->settings->betterCursors && this->paintingMode == LayoutPixmapItem::PaintMode::Metatiles){ + if (this->settings->betterCursors && this->getEditsEnabled()){ unsetCursor(); } this->has_mouse = false; diff --git a/src/ui/layoutpixmapitem.cpp b/src/ui/layoutpixmapitem.cpp index a595695ad..93489c7ee 100644 --- a/src/ui/layoutpixmapitem.cpp +++ b/src/ui/layoutpixmapitem.cpp @@ -694,7 +694,7 @@ void LayoutPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { this->metatilePos = pos; emit this->hoveredMapMetatileChanged(pos); } - if (this->settings->betterCursors && this->paintingMode != LayoutPixmapItem::PaintMode::Disabled) { + if (this->settings->betterCursors && this->editsEnabled) { setCursor(this->settings->mapCursor); } } @@ -707,7 +707,7 @@ void LayoutPixmapItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) { void LayoutPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { emit this->hoveredMapMetatileCleared(); - if (this->settings->betterCursors && this->paintingMode != LayoutPixmapItem::PaintMode::Disabled) { + if (this->settings->betterCursors && this->editsEnabled) { unsetCursor(); } this->has_mouse = false; diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index e81208b89..66c0dd0b1 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -183,8 +183,8 @@ bool MapImageExporter::historyItemAppliesToFrame(const QUndoCommand *command) { case CommandId::ID_BucketFillMetatile: case CommandId::ID_MagicFillMetatile: case CommandId::ID_ShiftMetatiles: - case CommandId::ID_ResizeMap: - case CommandId::ID_ScriptEditMap: + case CommandId::ID_ResizeLayout: + case CommandId::ID_ScriptEditLayout: return true; case CommandId::ID_PaintCollision: case CommandId::ID_BucketFillCollision: diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index 0b13c4748..3da703a70 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -94,7 +94,6 @@ void NewMapPopup::init() { ui->spinBox_NewMap_Floor_Number->setValue(settings.floorNumber); // Connect signals - // !TODO: make sure this doesnt reconnect a million times connect(ui->spinBox_NewMap_Width, QOverload::of(&QSpinBox::valueChanged), [=](int){checkNewMapDimensions();}); connect(ui->spinBox_NewMap_Height, QOverload::of(&QSpinBox::valueChanged), [=](int){checkNewMapDimensions();}); diff --git a/src/ui/regionmapeditor.cpp b/src/ui/regionmapeditor.cpp index 39d79ca73..74cbac4af 100644 --- a/src/ui/regionmapeditor.cpp +++ b/src/ui/regionmapeditor.cpp @@ -1101,7 +1101,7 @@ void RegionMapEditor::on_spinBox_RM_LayoutWidth_valueChanged(int value) { int newHeight = this->region_map->layoutHeight(); QMap> newLayouts = this->region_map->getAllLayouts(); - ResizeLayout *commit = new ResizeLayout(this->region_map, oldWidth, oldHeight, newWidth, newHeight, oldLayouts, newLayouts); + ResizeRMLayout *commit = new ResizeRMLayout(this->region_map, oldWidth, oldHeight, newWidth, newHeight, oldLayouts, newLayouts); this->region_map->editHistory.push(commit); } } @@ -1118,7 +1118,7 @@ void RegionMapEditor::on_spinBox_RM_LayoutHeight_valueChanged(int value) { int newHeight = this->region_map->layoutHeight(); QMap> newLayouts = this->region_map->getAllLayouts(); - ResizeLayout *commit = new ResizeLayout(this->region_map, oldWidth, oldHeight, newWidth, newHeight, oldLayouts, newLayouts); + ResizeRMLayout *commit = new ResizeRMLayout(this->region_map, oldWidth, oldHeight, newWidth, newHeight, oldLayouts, newLayouts); this->region_map->editHistory.push(commit); } } From c0a46ae05472e807639fb77cc2c6f21dd5430556 Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 27 Apr 2023 14:35:22 -0400 Subject: [PATCH 26/70] fix layout redraw when changing used tileset --- src/mainwindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5844afaa2..19bb0d9df 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2628,9 +2628,9 @@ void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName void MainWindow::on_comboBox_PrimaryTileset_currentTextChanged(const QString &tilesetLabel) { - if (editor->project->primaryTilesetLabels.contains(tilesetLabel) && editor->map) { + if (editor->project->primaryTilesetLabels.contains(tilesetLabel) && editor->layout) { editor->updatePrimaryTileset(tilesetLabel); - redrawMapScene(); + redrawLayoutScene(); on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value()); updateTilesetEditor(); prefab.updatePrefabUi(editor->layout); @@ -2640,9 +2640,9 @@ void MainWindow::on_comboBox_PrimaryTileset_currentTextChanged(const QString &ti void MainWindow::on_comboBox_SecondaryTileset_currentTextChanged(const QString &tilesetLabel) { - if (editor->project->secondaryTilesetLabels.contains(tilesetLabel) && editor->map) { + if (editor->project->secondaryTilesetLabels.contains(tilesetLabel) && editor->layout) { editor->updateSecondaryTileset(tilesetLabel); - redrawMapScene(); + redrawLayoutScene(); on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value()); updateTilesetEditor(); prefab.updatePrefabUi(editor->layout); From 3f7913b69468317c63c176201a9d4d65c0cecee7 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 23 Jun 2023 13:51:52 -0400 Subject: [PATCH 27/70] fix segfault in map image exporter --- src/ui/mapimageexporter.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index 66c0dd0b1..c6aef0cd6 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -98,8 +98,11 @@ void MapImageExporter::saveImage() { progress.setMaximum(1); progress.setValue(0); - int maxWidth = this->map->getWidth() * 16; - int maxHeight = this->map->getHeight() * 16; + Layout *layout = this->map->layout; + if (!layout) break; + + int maxWidth = layout->getWidth() * 16; + int maxHeight = layout->getHeight() * 16; if (showBorder) { maxWidth += 2 * STITCH_MODE_BORDER_DISTANCE * 16; maxHeight += 2 * STITCH_MODE_BORDER_DISTANCE * 16; From 95c21a4572824d7e9900467f16ab071557a0204e Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 28 Sep 2023 19:56:54 -0400 Subject: [PATCH 28/70] do not show nonexistent map sections --- src/ui/maplistmodels.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index e3dfba144..277147e0b 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -268,7 +268,6 @@ QVariant MapGroupModel::data(const QModelIndex &index, int role) const { } } else if (role == Qt::DisplayRole) { - // QStandardItem *item = this->getItem(index)->child(row, col); QString type = item->data(MapListRoles::TypeRole).toString(); @@ -342,7 +341,9 @@ QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, in void MapAreaModel::initialize() { this->areaItems.clear(); this->mapItems.clear(); - for (int i = 0; i < this->project->mapSectionNameToValue.size(); i++) { + this->setSortRole(MapListRoles::GroupRole); + + for (int i : this->project->mapSectionNameToValue) { QString mapsecName = project->mapSectionValueToName.value(i); QStandardItem *areaItem = createAreaItem(mapsecName, i); this->root->appendRow(areaItem); @@ -359,6 +360,7 @@ void MapAreaModel::initialize() { } } } + this->sort(0, Qt::AscendingOrder); } QStandardItem *MapAreaModel::getItem(const QModelIndex &index) const { @@ -422,6 +424,16 @@ QVariant MapAreaModel::data(const QModelIndex &index, int role) const { return mapGrayIcon; } } + else if (role == Qt::DisplayRole) { + QStandardItem *item = this->getItem(index)->child(row, col); + QString type = item->data(MapListRoles::TypeRole).toString(); + + if (type == "map_section") { + return QString("[0x%1] %2") + .arg(QString("%1").arg(item->data(MapListRoles::GroupRole).toInt(), 2, 16, QLatin1Char('0')).toUpper()) + .arg(item->data(Qt::UserRole).toString()); + } + } return QStandardItemModel::data(index, role); } From 46ada327331116f6cc5fac4eec29daf6c3c7d853 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 25 Oct 2023 12:25:19 -0400 Subject: [PATCH 29/70] fix map tab icon --- src/mainwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 19bb0d9df..394946860 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -365,6 +365,7 @@ void MainWindow::showWindowTitle() { ); } if (editor && editor->layout) { + ui->mainTabBar->setTabIcon(0, QIcon()); QPixmap pixmap = editor->layout->pixmap; if (!pixmap.isNull()) { ui->mainTabBar->setTabIcon(0, QIcon(pixmap)); From 6041c46abf6ca067ad970a7857bdee7671de461a Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 26 Oct 2023 14:13:32 -0400 Subject: [PATCH 30/70] fix scripting api usage of map/layout pointers --- src/scriptapi/apimap.cpp | 62 ++++++++++++++++++------------------ src/scriptapi/apioverlay.cpp | 9 ++---- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index ea18e0cc9..3dcb8071e 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -24,7 +24,7 @@ void MainWindow::tryRedrawMapArea(bool forceRedraw) { this->editor->updateMapBorder(); this->editor->updateMapConnections(); if (this->tilesetEditor) - this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label); + this->tilesetEditor->updateTilesets(this->editor->layout->tileset_primary_label, this->editor->layout->tileset_secondary_label); if (this->editor->metatile_selector_item) this->editor->metatile_selector_item->draw(); if (this->editor->selected_border_metatiles_item) @@ -341,7 +341,7 @@ void MainWindow::refreshAfterPaletteChange(Tileset *tileset) { } void MainWindow::setTilesetPalette(Tileset *tileset, int paletteIndex, QList> colors) { - if (!this->editor || !this->editor->map || !this->editor->layout) + if (!this->editor || !this->editor->layout) return; if (paletteIndex >= tileset->palettes.size()) return; @@ -357,7 +357,7 @@ void MainWindow::setTilesetPalette(Tileset *tileset, int paletteIndex, QList> colors, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return; this->setTilesetPalette(this->editor->layout->tileset_primary, paletteIndex, colors); if (forceRedraw) { @@ -366,7 +366,7 @@ void MainWindow::setPrimaryTilesetPalette(int paletteIndex, QList> co } void MainWindow::setPrimaryTilesetPalettes(QList>> palettes, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return; for (int i = 0; i < palettes.size(); i++) { this->setTilesetPalette(this->editor->layout->tileset_primary, i, palettes[i]); @@ -377,7 +377,7 @@ void MainWindow::setPrimaryTilesetPalettes(QList>> palettes, bo } void MainWindow::setSecondaryTilesetPalette(int paletteIndex, QList> colors, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return; this->setTilesetPalette(this->editor->layout->tileset_secondary, paletteIndex, colors); if (forceRedraw) { @@ -386,7 +386,7 @@ void MainWindow::setSecondaryTilesetPalette(int paletteIndex, QList> } void MainWindow::setSecondaryTilesetPalettes(QList>> palettes, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return; for (int i = 0; i < palettes.size(); i++) { this->setTilesetPalette(this->editor->layout->tileset_secondary, i, palettes[i]); @@ -420,25 +420,25 @@ QJSValue MainWindow::getTilesetPalettes(const QList> &palettes) { } QJSValue MainWindow::getPrimaryTilesetPalette(int paletteIndex) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return QJSValue(); return this->getTilesetPalette(this->editor->layout->tileset_primary->palettes, paletteIndex); } QJSValue MainWindow::getPrimaryTilesetPalettes() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return QJSValue(); return this->getTilesetPalettes(this->editor->layout->tileset_primary->palettes); } QJSValue MainWindow::getSecondaryTilesetPalette(int paletteIndex) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return QJSValue(); return this->getTilesetPalette(this->editor->layout->tileset_secondary->palettes, paletteIndex); } QJSValue MainWindow::getSecondaryTilesetPalettes() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return QJSValue(); return this->getTilesetPalettes(this->editor->layout->tileset_secondary->palettes); } @@ -452,7 +452,7 @@ void MainWindow::refreshAfterPalettePreviewChange() { } void MainWindow::setTilesetPalettePreview(Tileset *tileset, int paletteIndex, QList> colors) { - if (!this->editor || !this->editor->map || !this->editor->layout) + if (!this->editor || !this->editor->layout) return; if (paletteIndex >= tileset->palettePreviews.size()) return; @@ -467,7 +467,7 @@ void MainWindow::setTilesetPalettePreview(Tileset *tileset, int paletteIndex, QL } void MainWindow::setPrimaryTilesetPalettePreview(int paletteIndex, QList> colors, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return; this->setTilesetPalettePreview(this->editor->layout->tileset_primary, paletteIndex, colors); if (forceRedraw) { @@ -476,7 +476,7 @@ void MainWindow::setPrimaryTilesetPalettePreview(int paletteIndex, QList>> palettes, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return; for (int i = 0; i < palettes.size(); i++) { this->setTilesetPalettePreview(this->editor->layout->tileset_primary, i, palettes[i]); @@ -487,7 +487,7 @@ void MainWindow::setPrimaryTilesetPalettesPreview(QList>> palet } void MainWindow::setSecondaryTilesetPalettePreview(int paletteIndex, QList> colors, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return; this->setTilesetPalettePreview(this->editor->layout->tileset_secondary, paletteIndex, colors); if (forceRedraw) { @@ -496,7 +496,7 @@ void MainWindow::setSecondaryTilesetPalettePreview(int paletteIndex, QList>> palettes, bool forceRedraw) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return; for (int i = 0; i < palettes.size(); i++) { this->setTilesetPalettePreview(this->editor->layout->tileset_secondary, i, palettes[i]); @@ -507,61 +507,61 @@ void MainWindow::setSecondaryTilesetPalettesPreview(QList>> pal } QJSValue MainWindow::getPrimaryTilesetPalettePreview(int paletteIndex) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return QJSValue(); return this->getTilesetPalette(this->editor->layout->tileset_primary->palettePreviews, paletteIndex); } QJSValue MainWindow::getPrimaryTilesetPalettesPreview() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return QJSValue(); return this->getTilesetPalettes(this->editor->layout->tileset_primary->palettePreviews); } QJSValue MainWindow::getSecondaryTilesetPalettePreview(int paletteIndex) { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return QJSValue(); return this->getTilesetPalette(this->editor->layout->tileset_secondary->palettePreviews, paletteIndex); } QJSValue MainWindow::getSecondaryTilesetPalettesPreview() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return QJSValue(); return this->getTilesetPalettes(this->editor->layout->tileset_secondary->palettePreviews); } int MainWindow::getNumPrimaryTilesetMetatiles() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return 0; return this->editor->layout->tileset_primary->metatiles.length(); } int MainWindow::getNumSecondaryTilesetMetatiles() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return 0; return this->editor->layout->tileset_secondary->metatiles.length(); } int MainWindow::getNumPrimaryTilesetTiles() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return 0; return this->editor->layout->tileset_primary->tiles.length(); } int MainWindow::getNumSecondaryTilesetTiles() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return 0; return this->editor->layout->tileset_secondary->tiles.length(); } QString MainWindow::getPrimaryTileset() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_primary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary) return QString(); return this->editor->layout->tileset_primary->name; } QString MainWindow::getSecondaryTileset() { - if (!this->editor || !this->editor->map || !this->editor->layout || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary) return QString(); return this->editor->layout->tileset_secondary->name; } @@ -591,19 +591,19 @@ void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) { } Metatile * MainWindow::getMetatile(int metatileId) { - if (!this->editor || !this->editor->map || !this->editor->layout) + if (!this->editor || !this->editor->layout) return nullptr; return Tileset::getMetatile(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); } QString MainWindow::getMetatileLabel(int metatileId) { - if (!this->editor || !this->editor->map || !this->editor->map->layout) + if (!this->editor || !this->editor->layout) return QString(); - return Tileset::getMetatileLabel(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + return Tileset::getMetatileLabel(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); } void MainWindow::setMetatileLabel(int metatileId, QString label) { - if (!this->editor || !this->editor->map || !this->editor->layout) + if (!this->editor || !this->editor->layout) return; // If the Tileset Editor is opened on this metatile we need to update the text box @@ -612,13 +612,13 @@ void MainWindow::setMetatileLabel(int metatileId, QString label) { return; } - if (!Tileset::setMetatileLabel(metatileId, label, this->editor->layout->tileset_primary, this->editor->map->layout->tileset_secondary)) { + if (!Tileset::setMetatileLabel(metatileId, label, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary)) { logError("Failed to set metatile label. Must be a valid metatile id and a label containing only letters, numbers, and underscores."); return; } if (this->editor->project) - this->editor->project->saveTilesetMetatileLabels(this->editor->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + this->editor->project->saveTilesetMetatileLabels(this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary); } int MainWindow::getMetatileLayerType(int metatileId) { diff --git a/src/scriptapi/apioverlay.cpp b/src/scriptapi/apioverlay.cpp index 7e634fab5..b12f5f095 100644 --- a/src/scriptapi/apioverlay.cpp +++ b/src/scriptapi/apioverlay.cpp @@ -254,8 +254,7 @@ void MapView::addImage(int x, int y, QString filepath, int layer, bool useCache) } void MapView::createImage(int x, int y, QString filepath, int width, int height, int xOffset, int yOffset, qreal hScale, qreal vScale, int paletteId, bool setTransparency, int layer, bool useCache) { - if (!this->editor || !this->editor->map || !this->editor->layout - || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) return; QList palette; if (paletteId != -1) @@ -265,8 +264,7 @@ void MapView::createImage(int x, int y, QString filepath, int width, int height, } void MapView::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency, int layer) { - if (!this->editor || !this->editor->map || !this->editor->layout - || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) return; QImage image = getPalettedTileImage(tileId, this->editor->layout->tileset_primary, @@ -285,8 +283,7 @@ void MapView::addTileImage(int x, int y, QJSValue tileObj, bool setTransparency, } void MapView::addMetatileImage(int x, int y, int metatileId, bool setTransparency, int layer) { - if (!this->editor || !this->editor->map || !this->editor->layout - || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) + if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary) return; QImage image = getMetatileImage(static_cast(metatileId), this->editor->layout->tileset_primary, From 263e45fe200bd97b6a49e8441050221a3c305c09 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 27 Oct 2023 11:16:21 -0400 Subject: [PATCH 31/70] fix new map popup population issue --- src/mainwindow.cpp | 1 + src/ui/newmappopup.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 394946860..692509f96 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1269,6 +1269,7 @@ void MainWindow::openNewMapPopupWindow() { void MainWindow::on_action_NewMap_triggered() { openNewMapPopupWindow(); + this->newMapPrompt->initUi(); this->newMapPrompt->init(); } diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index 3da703a70..95a22f9d2 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -121,6 +121,7 @@ void NewMapPopup::init(MapSortOrder type, QVariant data) { // Creating new map from AdvanceMap import void NewMapPopup::init(Layout *mapLayout) { + initUi(); this->importedMap = true; useLayoutSettings(mapLayout); From a00558a0d15bb969ad6f3416f63c77a08a17d02b Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 27 Oct 2023 14:19:29 -0400 Subject: [PATCH 32/70] drop gMapGroup_ prefix necessity for renaming groups --- src/ui/maplistmodels.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 277147e0b..15baedaa0 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -19,7 +19,7 @@ void MapTree::removeSelected() { QWidget *GroupNameDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { QLineEdit *editor = new QLineEdit(parent); - static const QRegularExpression expression("gMapGroup_[A-Za-z0-9_]+"); + static const QRegularExpression expression("[A-Za-z0-9_]+"); editor->setPlaceholderText("gMapGroup_"); QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression, parent); editor->setValidator(validator); From cd5b1f98d2531b008ca58fa89b205a826dda220d Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 9 Jan 2024 21:50:22 -0500 Subject: [PATCH 33/70] add toggleable button to hide empty map folders --- forms/mainwindow.ui | 75 ++++++++++++++++++++++++++ include/mainwindow.h | 3 ++ include/ui/filterchildrenproxymodel.h | 4 +- resources/icons/folder_eye_closed.ico | Bin 0 -> 4286 bytes resources/icons/folder_eye_open.ico | Bin 0 -> 4286 bytes resources/images.qrc | 2 + src/mainwindow.cpp | 21 ++++++++ src/ui/filterchildrenproxymodel.cpp | 9 ++++ 8 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 resources/icons/folder_eye_closed.ico create mode 100644 resources/icons/folder_eye_open.ico diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 7d14043a7..244f1b291 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -79,6 +79,31 @@ 3 + + + + <html><head/><body><p>Toggle hide all empty map folders</p></body></html> + + + + + + + :/icons/folder_eye_closed.ico + :/icons/folder_eye_open.ico + + + + QToolButton::InstantPopup + + + true + + + true + + + @@ -214,6 +239,31 @@ 3 + + + + <html><head/><body><p>Toggle hide all empty mapsection folders</p></body></html> + + + + + + + :/icons/folder_eye_closed.ico + :/icons/folder_eye_open.ico + + + + QToolButton::InstantPopup + + + true + + + true + + + @@ -349,6 +399,31 @@ 3 + + + + <html><head/><body><p>Toggle hide all unused layouts</p></body></html> + + + + + + + :/icons/folder_eye_closed.ico + :/icons/folder_eye_open.ico + + + + QToolButton::InstantPopup + + + true + + + true + + + diff --git a/include/mainwindow.h b/include/mainwindow.h index 1e496139c..4a5d57778 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -279,10 +279,13 @@ private slots: void on_horizontalSlider_CollisionTransparency_valueChanged(int value); + void on_toolButton_HideShow_Groups_clicked(); void on_toolButton_ExpandAll_Groups_clicked(); void on_toolButton_CollapseAll_Groups_clicked(); + void on_toolButton_HideShow_Areas_clicked(); void on_toolButton_ExpandAll_Areas_clicked(); void on_toolButton_CollapseAll_Areas_clicked(); + void on_toolButton_HideShow_Layouts_clicked(); void on_toolButton_ExpandAll_Layouts_clicked(); void on_toolButton_CollapseAll_Layouts_clicked(); diff --git a/include/ui/filterchildrenproxymodel.h b/include/ui/filterchildrenproxymodel.h index b73cbd623..5853d6257 100644 --- a/include/ui/filterchildrenproxymodel.h +++ b/include/ui/filterchildrenproxymodel.h @@ -9,9 +9,11 @@ class FilterChildrenProxyModel : public QSortFilterProxyModel public: explicit FilterChildrenProxyModel(QObject *parent = nullptr); + void toggleHideEmpty() { this->hideEmpty = !this->hideEmpty; } protected: bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const; - +private: + bool hideEmpty = false; }; #endif // FILTERCHILDRENPROXYMODEL_H diff --git a/resources/icons/folder_eye_closed.ico b/resources/icons/folder_eye_closed.ico new file mode 100644 index 0000000000000000000000000000000000000000..354abadb4e6511d9f13ef4a089aa3e29e2380084 GIT binary patch literal 4286 zcmeI0drXs87{=>Vm`3B`B3@^VOEz7Mn`o3xK|nS)H8XBAG0RkxiKr+S5fJNTP9+Kq z5m4i0>gEug%z<}6Wr|!BC>Ki+s8mp#=w#rHwv=bj`J`AXNO4QtA0F~+doJI3-tRrn zIbVxR)`5S62Fb*$EcOkV%tj`Y4IyljITF#{S^*$?#mmbbrY87w_Cg`j@_Qs2T@+L7aLR-Y>OeVYl6FUyE zm-k(hTpl`0St>J?Cu=rTAcz0BnTz_(%m} z^}vn?K=ggf*r>UK$%oV!zP$+jHYqS5Bo}W9LQPrFRN&pnLQIJ($IuN)r>XyT zV+=MEw&h{w(K4(psKt(IU{e(kVga*GRKR}!b&T9q(k8Y$OE97lm)LSl*_U_LsP7b= z3purCCur~s^*2-+5PY+3x~)jUz>o}lo=}BJM{eQMxJpbse6vMFpBN*?ifg(CoxW?- z7wf+DZUY>*<{{>9AiS~x-&Yv0t_=dO+(&2s6X?7C0$l&7!QAr?F#B9BW}U5h%DEc2 zrqses^l?m|_2*$7a1wpiT^wZ87i%B$2>4{T5g)CR&H`p9R-j8@BCG>X zVeC&u@JM?I|9rqduR$V!pJyai!FE@Hq}yZVIrR5A@P4DVc(ZZXLj8xp*T>7TAgK~Z zxCSdV^^ljIU#-+%+ssy@TZH26z_fu!MLSxvGOVSxWrci7&?oYxGFGQxB(z z%qr^kC9gfvS0KIy2)b^7M|w3T^1MvrIdp+JNj2djKc^G#B0YRmI`|Z7EyjyuJ(XIV zp^kf838?!HdEKagob3T>dQQ`TFAiVBn2<{t9dh{@?ASJy=csp4J-iBaSbRk*;mP;s zQlN!LzLx81K;)&{7`7-{PHpMAXHWm1qP|$8fKqyno)6L(qOJhT}{{WHv~5B=uXvtFZCEODth9chMGq7FskBe;DGv;&r zn|ddwsO)1R29bxB?(ONG$v#RUv1k6X^6IzW%lqy3Kgm7AFc!^t8mkAfCgS^G-_LI)6}C%RTMmG;)klW_JbD+ilE3XC}OqPLM)(i zDPYw|6;ZLoD{_jpigI593M{9fXsL>#?8Vb(R#ssJU2T(os6&3c%)Il?GxMM4KkvH| zNiY5l86pv%lDPLI5~)NY`IxXtVnsxIPX&PF4gXyXdfJ!QY#+q?Mw78Rj9~p8(p~Ap zM!H608)2Q-!G!nC>|+~wu(wx|qPKT4o{0`L2pzhx>9h4p+2cc6=QMY&e}l z@u8h2AQjqE!}1ZQ1fm}T5fAjkzw#!&K3knoOW6 z8>)L%h+Q)jVcYF7$aFXc8k=FDi8=iJY;eHQ6p(XKDnT=DH{ZhiU-Qpt^{pcc;7e_r zlQlR*eg8%^0vcY$#i5TE_Nt+8&vG=i$fUowJV0-0b z{L%z$u2ta&J(wF`35jPCq+2f_@FxeH+c*-(g63iW4jVL=B?I*tXprS0JiQS8HzmVh zeHu(Qr?2W*yZDk$38j83u<%SB98(&Rz&+Shqk?a>3Y+v`ZbB`Lwr0W5muvIB@C2`P z#wG<4m$O`NGWz(Ohp~S)CWhoIs5zMQ7UC=#{Ufx7SJ@*>+f#xQ+@`=fCDzN7@X-^O z!iSiBv=*a6%kW7Dqe4m{_$<5>3+dI9T-S2OtDo7ZG1S$bhf+)C{84U?Un4MiM;>-p zx8cCecDR=-u&zP@FCDyDe^oqr&)!>VY`fBg&)xS2Q~!OjcovQRZ}i>wH-P!atKf0* z4pQ&7!|9p=&csE_bp>3B2l0GG+}S^%Mv3G*Dp-eP-lncGF?gb%j}!L+pIS8>F5kth zgXPHJIrIl(aZD3Wtu)dPEkLKJ}cEzSDto^R853L$z8HquH@Cl*@tA$3TgmTxGxO zD!`Iw9<}>v_0Kc^gxB1O$4l@m=e%TU%sVE7MQ}DIynyk+IT#+qb@)Hc-WU!=YhJ>ptMPw9d1vnS(Yf8{>xGh2GZj@R~8v|YzXb*U1WjJYMxc%h|H?E0b6 z&!_&X;x>A?jehRR8rB_n&AzA`M0*dcWPe-wv!o50xKq}stF)%3(J$un$F7h%yvLE_ zJw<4;J&t)(&UKV?tXJVW{aK~%;y2wX7>W3oaoi>OaxBYl!*U&#vYyIk!Z^OeeHkKr zl>bUR@msFeZ@T*Z#Ptg1gqXuMuJJk8F0M}wdzv%4WBil4p>=rfX)y;8hwj$)EN600 zQAp&>zgGBS^5*y7|2qb>fVR|_(^&74zC^sAi8Hb@x^2ANZ4vi~ah}naK_icons/fill_color.ico icons/folder_closed_map.ico icons/folder_closed.ico + icons/folder_eye_closed.ico + icons/folder_eye_open.ico icons/folder_map_edited.ico icons/folder_map_opened.ico icons/folder_map.ico diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 08b18d432..d9e23785b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2821,6 +2821,13 @@ void MainWindow::initTilesetEditor() { connect(this->tilesetEditor, &TilesetEditor::tilesetsSaved, this, &MainWindow::onTilesetsSaved); } +void MainWindow::on_toolButton_HideShow_Groups_clicked() { + if (ui->mapList) { + this->groupListProxyModel->toggleHideEmpty(); + this->groupListProxyModel->setFilterRegularExpression(this->ui->lineEdit_filterBox->text()); + } +} + void MainWindow::on_toolButton_ExpandAll_Groups_clicked() { if (ui->mapList) { ui->mapList->expandToDepth(0); @@ -2833,6 +2840,13 @@ void MainWindow::on_toolButton_CollapseAll_Groups_clicked() { } } +void MainWindow::on_toolButton_HideShow_Areas_clicked() { + if (ui->areaList) { + this->areaListProxyModel->toggleHideEmpty(); + this->areaListProxyModel->setFilterRegularExpression(this->ui->lineEdit_filterBox->text()); + } +} + void MainWindow::on_toolButton_ExpandAll_Areas_clicked() { if (ui->areaList) { ui->areaList->expandToDepth(0); @@ -2845,6 +2859,13 @@ void MainWindow::on_toolButton_CollapseAll_Areas_clicked() { } } +void MainWindow::on_toolButton_HideShow_Layouts_clicked() { + if (ui->layoutList) { + this->layoutListProxyModel->toggleHideEmpty(); + this->layoutListProxyModel->setFilterRegularExpression(this->ui->lineEdit_filterBox->text()); + } +} + void MainWindow::on_toolButton_ExpandAll_Layouts_clicked() { if (ui->layoutList) { ui->layoutList->expandToDepth(0); diff --git a/src/ui/filterchildrenproxymodel.cpp b/src/ui/filterchildrenproxymodel.cpp index a08c150c7..99464ae60 100644 --- a/src/ui/filterchildrenproxymodel.cpp +++ b/src/ui/filterchildrenproxymodel.cpp @@ -8,6 +8,15 @@ FilterChildrenProxyModel::FilterChildrenProxyModel(QObject *parent) : bool FilterChildrenProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { + if (this->hideEmpty && source_parent.row() < 0) // want to hide children + { + QModelIndex source_index = sourceModel()->index(source_row, this->filterKeyColumn(), source_parent) ; + if(source_index.isValid()) + { + if (!sourceModel()->hasChildren(source_index)) + return false; + } + } // custom behaviour : if(filterRegularExpression().pattern().isEmpty() == false) { From 99eb92c3b298e2d411947a36bd3d1266374a43b7 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 10 Jan 2024 14:34:48 -0500 Subject: [PATCH 34/70] timelapse replay layout edits then map edits --- include/ui/mapimageexporter.h | 1 + src/mainwindow.cpp | 12 +++ src/ui/mapimageexporter.cpp | 189 +++++++++++++++++++--------------- 3 files changed, 118 insertions(+), 84 deletions(-) diff --git a/include/ui/mapimageexporter.h b/include/ui/mapimageexporter.h index 6d8ae643d..39cc24aae 100644 --- a/include/ui/mapimageexporter.h +++ b/include/ui/mapimageexporter.h @@ -27,6 +27,7 @@ class MapImageExporter : public QDialog private: Ui::MapImageExporter *ui; + Layout *layout = nullptr; Map *map = nullptr; Editor *editor = nullptr; QGraphicsScene *scene = nullptr; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d9e23785b..1c7da36c6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1208,6 +1208,7 @@ void MainWindow::scrollTreeView(QString itemName) { } } +// !TODO: remove this? void MainWindow::sortMapList() { } @@ -2564,6 +2565,17 @@ void MainWindow::on_action_Export_Map_Image_triggered() { } void MainWindow::on_actionExport_Stitched_Map_Image_triggered() { + if (!this->editor->map) { + QMessageBox warning(this); + warning.setText("Notice"); + warning.setInformativeText("Map stich images are not possible without a map selected."); + warning.setStandardButtons(QMessageBox::Ok); + warning.setDefaultButton(QMessageBox::Cancel); + warning.setIcon(QMessageBox::Warning); + + warning.exec(); + return; + } showExportMapImageWindow(ImageExporterMode::Stitch); } diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index c6aef0cd6..44d41f19e 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -29,15 +29,18 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor { ui->setupUi(this); this->map = editor_->map; + this->layout = editor_->layout; this->editor = editor_; this->mode = mode; this->setWindowTitle(getTitle(this->mode)); this->ui->groupBox_Connections->setVisible(this->mode == ImageExporterMode::Normal); this->ui->groupBox_Timelapse->setVisible(this->mode == ImageExporterMode::Timelapse); - this->ui->comboBox_MapSelection->addItems(editor->project->mapNames); - this->ui->comboBox_MapSelection->setCurrentText(map->name); - this->ui->comboBox_MapSelection->setEnabled(false);// TODO: allow selecting map from drop-down + if (this->map) { + this->ui->comboBox_MapSelection->addItems(editor->project->mapNames); + this->ui->comboBox_MapSelection->setCurrentText(map->name); + this->ui->comboBox_MapSelection->setEnabled(false);// TODO: allow selecting map from drop-down + } updatePreview(); } @@ -53,13 +56,13 @@ void MapImageExporter::saveImage() { switch (this->mode) { case ImageExporterMode::Normal: - defaultFilename = map->name; + defaultFilename = this->map? this->map->name : this->layout->name; break; case ImageExporterMode::Stitch: - defaultFilename = QString("Stitch_From_%1").arg(map->name); + defaultFilename = QString("Stitch_From_%1").arg(this->map? this->map->name : this->layout->name); break; case ImageExporterMode::Timelapse: - defaultFilename = QString("Timelapse_%1").arg(map->name); + defaultFilename = QString("Timelapse_%1").arg(this->map? this->map->name : this->layout->name); break; } @@ -91,89 +94,98 @@ void MapImageExporter::saveImage() { } case ImageExporterMode::Timelapse: // !TODO: also need layout editHistory! - QProgressDialog progress("Building map timelapse...", "Cancel", 0, 1, this); - progress.setAutoClose(true); - progress.setWindowModality(Qt::WindowModal); - progress.setModal(true); - progress.setMaximum(1); - progress.setValue(0); - - Layout *layout = this->map->layout; - if (!layout) break; + QGifImage timelapseImg; + timelapseImg.setDefaultDelay(timelapseDelayMs); + timelapseImg.setDefaultTransparentColor(QColor(0, 0, 0)); - int maxWidth = layout->getWidth() * 16; - int maxHeight = layout->getHeight() * 16; - if (showBorder) { - maxWidth += 2 * STITCH_MODE_BORDER_DISTANCE * 16; - maxHeight += 2 * STITCH_MODE_BORDER_DISTANCE * 16; - } - // Rewind to the specified start of the map edit history. - int i = 0; - while (this->map->editHistory.canUndo()) { - progress.setValue(i); - this->map->editHistory.undo(); - int width = this->map->getWidth() * 16; - int height = this->map->getHeight() * 16; + auto generateTimelapseFromHistory = [=, this, &timelapseImg](QString progressText, QUndoStack &historyStack){ + // + QProgressDialog progress(progressText, "Cancel", 0, 1, this); + progress.setAutoClose(true); + progress.setWindowModality(Qt::WindowModal); + progress.setModal(true); + progress.setMaximum(1); + progress.setValue(0); + + int maxWidth = this->layout->getWidth() * 16; + int maxHeight = this->layout->getHeight() * 16; if (showBorder) { - width += 2 * STITCH_MODE_BORDER_DISTANCE * 16; - height += 2 * STITCH_MODE_BORDER_DISTANCE * 16; - } - if (width > maxWidth) { - maxWidth = width; - } - if (height > maxHeight) { - maxHeight = height; + maxWidth += 2 * STITCH_MODE_BORDER_DISTANCE * 16; + maxHeight += 2 * STITCH_MODE_BORDER_DISTANCE * 16; } - i++; - } - QGifImage timelapseImg(QSize(maxWidth, maxHeight)); - timelapseImg.setDefaultDelay(timelapseDelayMs); - timelapseImg.setDefaultTransparentColor(QColor(0, 0, 0)); - // Draw each frame, skpping the specified number of map edits in - // the undo history. - progress.setMaximum(i); - while (i > 0) { - if (progress.wasCanceled()) { - progress.close(); - while (i > 0 && this->map->editHistory.canRedo()) { - i--; - this->map->editHistory.redo(); + // Rewind to the specified start of the map edit history. + int i = 0; + while (historyStack.canUndo()) { + progress.setValue(i); + historyStack.undo(); + int width = this->layout->getWidth() * 16; + int height = this->layout->getHeight() * 16; + if (showBorder) { + width += 2 * STITCH_MODE_BORDER_DISTANCE * 16; + height += 2 * STITCH_MODE_BORDER_DISTANCE * 16; } - return; - } - while (this->map->editHistory.canRedo() && - !historyItemAppliesToFrame(this->map->editHistory.command(this->map->editHistory.index()))) { - i--; - this->map->editHistory.redo(); - } - progress.setValue(progress.maximum() - i); - QPixmap pixmap = this->getFormattedMapPixmap(this->map, !this->showBorder); - if (pixmap.width() < maxWidth || pixmap.height() < maxHeight) { - QPixmap pixmap2 = QPixmap(maxWidth, maxHeight); - QPainter painter(&pixmap2); - pixmap2.fill(QColor(0, 0, 0)); - painter.drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap); - painter.end(); - pixmap = pixmap2; + if (width > maxWidth) { + maxWidth = width; + } + if (height > maxHeight) { + maxHeight = height; + } + i++; } - timelapseImg.addFrame(pixmap.toImage()); - for (int j = 0; j < timelapseSkipAmount; j++) { - if (i > 0) { + + // Draw each frame, skpping the specified number of map edits in + // the undo history. + progress.setMaximum(i); + while (i > 0) { + if (progress.wasCanceled()) { + progress.close(); + while (i > 0 && historyStack.canRedo()) { + i--; + historyStack.redo(); + } + return; + } + while (historyStack.canRedo() && + !historyItemAppliesToFrame(historyStack.command(historyStack.index()))) { i--; - this->map->editHistory.redo(); - while (this->map->editHistory.canRedo() && - !historyItemAppliesToFrame(this->map->editHistory.command(this->map->editHistory.index()))) { + historyStack.redo(); + } + progress.setValue(progress.maximum() - i); + QPixmap pixmap = this->getFormattedMapPixmap(this->map, !this->showBorder); + if (pixmap.width() < maxWidth || pixmap.height() < maxHeight) { + QPixmap pixmap2 = QPixmap(maxWidth, maxHeight); + QPainter painter(&pixmap2); + pixmap2.fill(QColor(0, 0, 0)); + painter.drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap); + painter.end(); + pixmap = pixmap2; + } + timelapseImg.addFrame(pixmap.toImage()); + for (int j = 0; j < timelapseSkipAmount; j++) { + if (i > 0) { i--; - this->map->editHistory.redo(); + historyStack.redo(); + while (historyStack.canRedo() && + !historyItemAppliesToFrame(historyStack.command(historyStack.index()))) { + i--; + historyStack.redo(); + } } } } - } - // The latest map state is the last animated frame. - QPixmap pixmap = this->getFormattedMapPixmap(this->map, !this->showBorder); - timelapseImg.addFrame(pixmap.toImage()); + // The latest map state is the last animated frame. + QPixmap pixmap = this->getFormattedMapPixmap(this->map, !this->showBorder); + timelapseImg.addFrame(pixmap.toImage()); + progress.close(); + }; + + if (this->layout) + generateTimelapseFromHistory("Building layout timelapse...", this->layout->editHistory); + + if (this->map) + generateTimelapseFromHistory("Building map timelapse...", this->map->editHistory); + timelapseImg.save(filepath); - progress.close(); break; } this->close(); @@ -358,18 +370,23 @@ void MapImageExporter::updatePreview() { scene->itemsBoundingRect().height() + 2); } +// THIS QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { QPixmap pixmap; + Layout *layout; + // draw background layer / base image - Layout *layout = map->layout; - if (!layout) { - return QPixmap(); + if (!this->map) { + layout = this->layout; + layout->render(true); + pixmap = layout->pixmap; + } else { + layout = map->layout; + map->layout->render(true); + pixmap = map->layout->pixmap; } - layout->render(true); - pixmap = layout->pixmap; - if (showCollision) { QPainter collisionPainter(&pixmap); layout->renderCollision(true); @@ -401,6 +418,10 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) { pixmap = newPixmap; } + if (!this->map) { + return pixmap; + } + if (!this->mode) { // if showing connections, draw on outside of image QPainter connectionPainter(&pixmap); From abc433bc78ed53e33459f0fb699221d16b1022eb Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 12 Jan 2024 14:39:49 -0500 Subject: [PATCH 35/70] allow dragging and dropping to rearrange map groups --- include/ui/maplistmodels.h | 2 +- src/ui/maplistmodels.cpp | 96 +++++++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 27 deletions(-) diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index ef21d8aec..10270a13e 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -72,7 +72,7 @@ class MapGroupModel : public QStandardItemModel { public: void setMap(QString mapName) { this->openMap = mapName; } - QStandardItem *createGroupItem(QString groupName, int groupIndex); + QStandardItem *createGroupItem(QString groupName, int groupIndex, QStandardItem *fromItem = nullptr); QStandardItem *createMapItem(QString mapName, QStandardItem *fromItem = nullptr); QStandardItem *insertMapItem(QString mapName, QString groupName); diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 15baedaa0..d22f2af63 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -59,7 +59,9 @@ Qt::DropActions MapGroupModel::supportedDropActions() const { QStringList MapGroupModel::mimeTypes() const { QStringList types; types << "application/porymap.mapgroupmodel.map" - << "application/porymap.mapgroupmodel.group"; + << "application/porymap.mapgroupmodel.group" + << "application/porymap.mapgroupmodel.source.row" + << "application/porymap.mapgroupmodel.source.column"; return types; } @@ -69,6 +71,17 @@ QMimeData *MapGroupModel::mimeData(const QModelIndexList &indexes) const { QDataStream stream(&encodedData, QIODevice::WriteOnly); + // if dropping a selection containing a group(s) and map(s), clear all selection but first group. + for (const QModelIndex &index : indexes) { + if (index.isValid() && data(index, MapListRoles::TypeRole).toString() == "map_group") { + QString groupName = data(index, Qt::UserRole).toString(); + stream << groupName; + mimeData->setData("application/porymap.mapgroupmodel.group", encodedData); + mimeData->setData("application/porymap.mapgroupmodel.source.row", QByteArray::number(index.row())); + return mimeData; + } + } + for (const QModelIndex &index : indexes) { if (index.isValid()) { QString mapName = data(index, Qt::UserRole).toString(); @@ -83,11 +96,8 @@ QMimeData *MapGroupModel::mimeData(const QModelIndexList &indexes) const { bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parentIndex) { if (action == Qt::IgnoreAction) return true; - - if (!data->hasFormat("application/porymap.mapgroupmodel.map")) - return false; - if (!parentIndex.isValid()) + if (!parentIndex.isValid() && !data->hasFormat("application/porymap.mapgroupmodel.group")) return false; int firstRow = 0; @@ -99,34 +109,68 @@ bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i firstRow = rowCount(parentIndex); } - QByteArray encodedData = data->data("application/porymap.mapgroupmodel.map"); - QDataStream stream(&encodedData, QIODevice::ReadOnly); - QStringList droppedMaps; - int rowCount = 0; + if (data->hasFormat("application/porymap.mapgroupmodel.group")) { + if (parentIndex.row() != -1 || parentIndex.column() != -1) { + return false; + } + QByteArray encodedData = data->data("application/porymap.mapgroupmodel.group"); + QDataStream stream(&encodedData, QIODevice::ReadOnly); + QString groupName; + int rowCount = 1; + + while (!stream.atEnd()) { + stream >> groupName; + } + + this->insertRow(row, parentIndex); + + // copy children to new node + int sourceRow = data->data("application/porymap.mapgroupmodel.source.row").toInt(); + QModelIndex originIndex = this->index(sourceRow, 0); + QModelIndexList children; + QStringList mapsToMove; + for (int i = 0; i < this->rowCount(originIndex); ++i ) { + children << this->index( i, 0, originIndex); + mapsToMove << this->index( i, 0 , originIndex).data(Qt::UserRole).toString(); + } - QList newItems; + QModelIndex groupIndex = index(row, 0, parentIndex); + QStandardItem *groupItem = this->itemFromIndex(groupIndex); + createGroupItem(groupName, row, groupItem); - while (!stream.atEnd()) { - QString mapName; - stream >> mapName; - droppedMaps << mapName; - rowCount++; + for (QString mapName : mapsToMove) { + QStandardItem *mapItem = createMapItem(mapName); + groupItem->appendRow(mapItem); + } } + else if (data->hasFormat("application/porymap.mapgroupmodel.map")) { + QByteArray encodedData = data->data("application/porymap.mapgroupmodel.map"); + QDataStream stream(&encodedData, QIODevice::ReadOnly); + QStringList droppedMaps; + int rowCount = 0; + + while (!stream.atEnd()) { + QString mapName; + stream >> mapName; + droppedMaps << mapName; + rowCount++; + } - this->insertRows(firstRow, rowCount, parentIndex); + this->insertRows(firstRow, rowCount, parentIndex); - int newItemIndex = 0; - for (QString mapName : droppedMaps) { - QModelIndex mapIndex = index(firstRow, 0, parentIndex); - QStandardItem *mapItem = this->itemFromIndex(mapIndex); - createMapItem(mapName, mapItem); - firstRow++; + int newItemIndex = 0; + for (QString mapName : droppedMaps) { + QModelIndex mapIndex = index(firstRow, 0, parentIndex); + QStandardItem *mapItem = this->itemFromIndex(mapIndex); + createMapItem(mapName, mapItem); + firstRow++; + } } emit dragMoveCompleted(); updateProject(); - return false; + return true; } void MapGroupModel::updateProject() { @@ -158,13 +202,13 @@ void MapGroupModel::updateProject() { this->project->mapNames = mapNames; } -QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex) { - QStandardItem *group = new QStandardItem; +QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex, QStandardItem *group) { + if (!group) group = new QStandardItem; group->setText(groupName); group->setData(groupName, Qt::UserRole); group->setData("map_group", MapListRoles::TypeRole); group->setData(groupIndex, MapListRoles::GroupRole); - group->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); + group->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsSelectable); this->groupItems.insert(groupName, group); return group; } From b620e3d81644082a7a5d123e61928d5a6dc05636 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 12 Jan 2024 15:48:51 -0500 Subject: [PATCH 36/70] add button to lock group edits --- forms/mainwindow.ui | 37 ++++++++++++++++++++++++++------ include/mainwindow.h | 1 + resources/icons/lock_edit.ico | Bin 0 -> 4418 bytes resources/icons/unlock_edit.ico | Bin 0 -> 4286 bytes resources/images.qrc | 2 ++ src/mainwindow.cpp | 29 ++++++++++++++++++++----- 6 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 resources/icons/lock_edit.ico create mode 100644 resources/icons/unlock_edit.ico diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 244f1b291..92bf0b134 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -89,8 +89,8 @@ - :/icons/folder_eye_closed.ico - :/icons/folder_eye_open.ico + :/icons/folder_eye_open.ico + :/icons/folder_eye_closed.ico @@ -144,6 +144,31 @@ + + + + <html><head/><body><p>Toggle editability of group folders</p></body></html> + + + + + + + :/icons/lock_edit.ico + :/icons/unlock_edit.ico + + + + QToolButton::InstantPopup + + + true + + + true + + + @@ -249,8 +274,8 @@ - :/icons/folder_eye_closed.ico - :/icons/folder_eye_open.ico + :/icons/folder_eye_open.ico + :/icons/folder_eye_closed.ico @@ -409,8 +434,8 @@ - :/icons/folder_eye_closed.ico - :/icons/folder_eye_open.ico + :/icons/folder_eye_open.ico + :/icons/folder_eye_closed.ico diff --git a/include/mainwindow.h b/include/mainwindow.h index 4a5d57778..536f659cb 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -282,6 +282,7 @@ private slots: void on_toolButton_HideShow_Groups_clicked(); void on_toolButton_ExpandAll_Groups_clicked(); void on_toolButton_CollapseAll_Groups_clicked(); + void on_toolButton_EnableDisable_EditGroups_clicked(); void on_toolButton_HideShow_Areas_clicked(); void on_toolButton_ExpandAll_Areas_clicked(); void on_toolButton_CollapseAll_Areas_clicked(); diff --git a/resources/icons/lock_edit.ico b/resources/icons/lock_edit.ico new file mode 100644 index 0000000000000000000000000000000000000000..f30f424914e61f251359e82f311b28b90d34cfd2 GIT binary patch literal 4418 zcmb`Kc~I5Y6~}*ofC~87d1KRRn`xWO#G1OqnKlH)IK=7Hg|w#sL`^kB4U51~RFqA8 zpb+J;KHveG;1XO450u6lR-Y`&j*mqnAc!n+1eHWt-nZvGmcWyTkm+H*-2408bI<48 zbMNoR4?)nQpT)lx__y$ug&^1pg75}uG0Bm{_kX4t(mYerJd*y;j4|yr00K*gF`HH< z{FcPa`oHEe#-70E^@>O~qr63~9$w$C-1NyYy0#~ASr?9uaXwRt=W+~=HLYp!*#O2-?DpPq0{c8bZ_107>`dSp35;f*0ecj@j2(^qTOk&BKHee z;C2C~ZWm$fuE5$I2e8A(AA55j;rDK*VBvBKW}X>X;BgV`D^O7VL))xcoZ>Tk`Qwi{HdK-L;dXU}@1eXtDLu>`!+atpVx5%%QH0tl9 z9EOupjkhQU$09KAg-+Ar+gf;KU{e{e@^T-jqS2L{74hh?+s$h z&rtjOwxW9|#Q zpFcnvgk!-lmZj7q_*xSl4FOxP0oL(=m~(K6f+MYY4f)w$`w<@&zrf$hhG9;z2s|sk zrFS;ARSs+T;-m)5r}fW|WL3gAss<~3l?c2CH2(nn^IO1XJO?RkQ=70t(FJGXe_TEU zjx}4pl}`>_YSdUhVg2i9UF!-+MZ=gITZ?xN+(2*(&_bIrF$afFrLZp;f^+F0c2=ul zNwH?l_x%PQsuBLg^_x%)%%W=`N~nk6oPt&UWiRDmM|<(^j!1l14!G3=R{O5bns2@T zzwl|Ky;l6R|6}WSDxx*X8=>bM2VqkTRvjuua5L3m!d}?QfIsh$VjtDV=3wsZ`3G|0 z{~hp0;@eHwe^Y5C%;V}{mHHj#Y>a?D$u#Be$X?KSn3Mz6;k{ikunQ_;{%=S|q$y4N z{M#HXz>#J(-p+iCHKXUB_uh&2-hygx_OC1$Za$7VBopeJ(lfep-*p6O}0q-k@|=Gz4-5!(SQeQEu?_rzc83&XzzXvBT1p5i(T6`Pv;hRW%1T4vT42N%Dz%g$CYx(&v9EK>i4i<@xREN77ao;>n zMel|o@*Biz^8Hip0RG@zfP<7n{R`lHN;FO;#KYUu13vp)U&=v?FIp(6z=b~G?X1UG z5Z?g3@N(!!RKVbiN*JD~hLN-e#?o4iM*20H`v%9WAfjBB{JWF>ehlJw-ZyaVVj8+1 z+(%JiK9b}z_yu|)aZfqtu!=-qX@cgvXDkQ0H2kHcyul^63t9bu;u(-l?PaRv6;h54 z@fiEDf96wa>3VD4BjlvXaId}=ot+OLITnPnh*A`UT!rlO63$^NKBr{3Ftn=HDpUp2 zkUE$hxecqZdWger;}>Bycuh-uPaIYUOY%2k|Bw-X8%b3q#hRaaHW`U>DeioE2UQ6b zC^=Dx)V*cQ*F2A7Yv*=?*@o|T1)e{FGUpP$@bln7TVe^spCrD=W9` z<3AeDs8FIpM`jzE&Z=1WM`*zQiF|f9$~{(%Z$hgkv3WojKO`ss{lw47RvF%0J6J95A4t#c4+<)D} z_4CxP&!(ZZr5P=)t%x`(VZP>kQ#-Bc;Li;Y4^uTZHlReQgd*b-VyFghzWK%$3bvHQ zf74h?`Cd%qaa329Yxr$#Z3sUWrlPUAq*s~_zW(8$fL#~TzeeZ74owZx&z*rRCJJ7A zJx)8WS-pql<>7uhJ~kRx|8oVZx>`JW(uabAd;|p?+C|_Q{ja8j&v_fgMoS-7S61N8 zohIa5&O&zPC46-<1t*gekt$Ebxie`f%*#dj%`$x7(}V7=E+oXqKIFL^U?w&VU)a8F zt7T$*EGll@L{E1QDyc2X&%<>Vt+TXPiI(PjcuMQ;>gvSV(_dlR){iY`!X5K@1z*_Z zveSajUk9Iodev<_>FYyZZy&Y2c=q%u+S}W3Ls^7VDe{ibKHX_S{ISq8YNz9K0OE6_ zpA;XvooZh5Ws00x<4Tby)Fi~kY-bq(vkV$(Up?rWWe=I_Mks{>nf^La!-F_({(NV+;u*s09KG I4wM4$KSovGegFUf literal 0 HcmV?d00001 diff --git a/resources/icons/unlock_edit.ico b/resources/icons/unlock_edit.ico new file mode 100644 index 0000000000000000000000000000000000000000..85a99e980c95ca2f81fc4b8b63fea7d9a0d10f8f GIT binary patch literal 4286 zcmb_fX;4&G7Jh($3fSy)IhoO#R87WA95XJlY9<7QSj3vDh$Lg?Ph7@?sKZV%7*Pa7 zcBAY|w}2^71DZesQgIBcEsH?2*(@5tB`g|CP)L;Rn{ysZu%!u9&7nT-efOSwzVDoS z-{T?(I`p%0rNF<1^QMAeEeOIN2{a^ZBJj9210XQ8m>G@#iLja=B`hK668FCg{z16j~kr!L{i_Dz-cWf@SHaAT8_c7<}?j{_U9be5jGPX2=Bi2-amr( zY~Kpo9s7ruJMNF5u`QExJU<(FEyv(kb867wXU*#*`!nxI+%I66+XWcAU4)^#0uFl* zVXtohJc}RUHMcV`b2$SOuUstixCr)@kgvooht}jwJX4HG4IEReY4BT_x}NV`EmLD_ zC9w6{xY#;Y0dHsDgI~o%WZwsZ>qhW?LOtF&kc{_g$*-C)>F=l?!BX)Wo=kW z`7b@iP{A;^3G4lo2)qq+{sjE%JHTpMLkz6bJFs5S2WR5{xNa02YoYuWzD00p8ppaB z`EQ}Twv-Vn#;`b{8E+lBhTtxsi#B7X2D?vVU|Ti{=jsuB(l`!tinU;Vzi;88p5ULE zzY*2IB(4dPlvW7NY1kN0^O6P|+KadMp27!pfLkkIaq#kj`7J;HFMQi+uNA-S|5W~t z6_k^_9Xig55S-$%@klj-JE;yc_QEyqWhH znYlNk|jWm=Ykm|tShg~JW(o`TSzzhC0;g>`R8>!0&(g7$gZTFiUNxI@}V$ebYoWeH%u}Zv>mj_pimn z__I$L4wHt~=Ri(c95Pap;N#^1--E6%Y0%)8EDx>6g#qBr{Kr_9)CQfXI_O5%L+^wN z`X?J<5Yq(1m}U_Z{U&i-?~4XVNXzPPdg<@S2>#%64OcE^;=vDhQBhtBnLHW(f!;_x zP{$fJ68K&t-g~Ar(4+ouL+jdHiu;g11Skf90%{AXmX`=cTEKJc$NqUwsio(gC67>) znT*@5&FJm@0ilsWsEMvdS;%E1|GSDc%*M}>^p}ShWW+!aVmFi zXP9-==dQrBCr}oBjT8PJJo!3t3B>;bc#KSsU_`K-1owH2&7eF~jqbdA=s2fFj(_bm zH&1Hg4>{t8XFm<$@+Aer0{wZ-8w4F*GmA0bYXtt*Fu2cm#3?fuYVGS>E^Q1QZ zV}VC7G&F>w!hD1t3*vQrmz#~B$E>~G_Gg423q*KGAiUiVWY8GbV%msbApYs+sg5>& z<{TOv!leQQB0@u$eXt3!=h9nSaiEAI*!Vh2Jci^5Ogo z6uC&3rNGP6Bb^q!N?;9qb{X7%)zjTIJ^O4H?sRpctLqLuYQ2Y(Idi_Btv`OGI2PD@ApsQmpw?%DbYbNg%jlfJrC*WKyz)F!Td_PH#v{@hQKr!>*I*iC-(+V9DD(+%^F z8`8Z=&_OB5nFo%Nj~!tJK|(Mj=uM%E`u%pghW#t_B>lhBg9u}4gicons/folder_map_opened.ico icons/folder_map.ico icons/folder.ico + icons/lock_edit.ico + icons/unlock_edit.ico icons/map_edited.ico icons/map_opened.ico icons/map.ico diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1c7da36c6..b609be59c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1179,11 +1179,12 @@ bool MainWindow::populateMapList() { ui->layoutList->setModel(layoutListProxyModel); /// !TODO - ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); - ui->mapList->setDragEnabled(true); - ui->mapList->setAcceptDrops(true); - ui->mapList->setDropIndicatorShown(true); - ui->mapList->setDragDropMode(QAbstractItemView::InternalMove); + // ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); + // ui->mapList->setDragEnabled(true); + // ui->mapList->setAcceptDrops(true); + // ui->mapList->setDropIndicatorShown(true); + // ui->mapList->setDragDropMode(QAbstractItemView::InternalMove); + on_toolButton_EnableDisable_EditGroups_clicked(); return success; } @@ -2852,6 +2853,24 @@ void MainWindow::on_toolButton_CollapseAll_Groups_clicked() { } } +void MainWindow::on_toolButton_EnableDisable_EditGroups_clicked() { + if (this->ui->toolButton_EnableDisable_EditGroups->isChecked()) { + ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); + ui->mapList->setDragEnabled(true); + ui->mapList->setAcceptDrops(true); + ui->mapList->setDropIndicatorShown(true); + ui->mapList->setDragDropMode(QAbstractItemView::InternalMove); + ui->mapList->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed); + } else { + ui->mapList->setSelectionMode(QAbstractItemView::NoSelection); + ui->mapList->setDragEnabled(false); + ui->mapList->setAcceptDrops(false); + ui->mapList->setDropIndicatorShown(false); + ui->mapList->setDragDropMode(QAbstractItemView::NoDragDrop); + ui->mapList->setEditTriggers(QAbstractItemView::NoEditTriggers); + } +} + void MainWindow::on_toolButton_HideShow_Areas_clicked() { if (ui->areaList) { this->areaListProxyModel->toggleHideEmpty(); From 858c8078563afce2f279d1e26a877a052cc5ba39 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 12 Jan 2024 19:22:54 -0500 Subject: [PATCH 37/70] fix bad merge --- src/project.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/project.cpp b/src/project.cpp index 32b1acfa0..41f9ccf99 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -35,9 +35,7 @@ int Project::default_map_size = 20; int Project::max_object_events = 64; Project::Project(QObject *parent) : - QObject(parent), - eventScriptLabelModel(this), - eventScriptLabelCompleter(this) + QObject(parent) { initSignals(); } From 23b55a1074572520856ef150d178fe88da6c5ccf Mon Sep 17 00:00:00 2001 From: garak Date: Sun, 4 Feb 2024 12:58:41 -0500 Subject: [PATCH 38/70] fix bug disabling map edits after tab switches --- src/editor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/editor.cpp b/src/editor.cpp index 123320511..5ed977824 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -129,6 +129,7 @@ void Editor::setEditorView() { switch (this->editMode) { case EditMode::Metatiles: case EditMode::Collision: + map_item->setEditsEnabled(true); this->editGroup.setActiveStack(&this->layout->editHistory); break; case EditMode::Events: From ad1b651f96ace3735ddea7ef2704b5bc7fc7aaf3 Mon Sep 17 00:00:00 2001 From: garak Date: Sun, 4 Feb 2024 14:59:03 -0500 Subject: [PATCH 39/70] clear selection sticking when edits toggled for map list --- src/mainwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b609be59c..61265135b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2854,6 +2854,7 @@ void MainWindow::on_toolButton_CollapseAll_Groups_clicked() { } void MainWindow::on_toolButton_EnableDisable_EditGroups_clicked() { + this->ui->mapList->clearSelection(); if (this->ui->toolButton_EnableDisable_EditGroups->isChecked()) { ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); ui->mapList->setDragEnabled(true); From 963b09c86612cf6ed917c662978a04573294d625 Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 13 Feb 2024 20:23:23 -0500 Subject: [PATCH 40/70] create buttons to add items to map trees --- include/mainwindow.h | 5 +++ include/ui/maplistmodels.h | 2 + src/mainwindow.cpp | 76 +++++++++++++++++++++++++++++++++++--- src/ui/maplistmodels.cpp | 40 +++++++++++++++----- 4 files changed, 108 insertions(+), 15 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 536f659cb..0c3bd4ee0 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -389,6 +389,11 @@ private slots: void refreshRecentProjectsMenu(); void updateMapList(); + void mapListAddItem(); + void mapListRemoveItem(); + void mapListAddGroup(); + void mapListAddLayout(); + void mapListAddArea(); void displayMapProperties(); void checkToolButtons(); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 10270a13e..a2babda6e 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -75,6 +75,7 @@ class MapGroupModel : public QStandardItemModel { QStandardItem *createGroupItem(QString groupName, int groupIndex, QStandardItem *fromItem = nullptr); QStandardItem *createMapItem(QString mapName, QStandardItem *fromItem = nullptr); + QStandardItem *insertGroupItem(QString groupName); QStandardItem *insertMapItem(QString mapName, QString groupName); QStandardItem *getItem(const QModelIndex &index) const; @@ -83,6 +84,7 @@ class MapGroupModel : public QStandardItemModel { void initialize(); private: + friend class MapTree; void updateProject(); private: diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 61265135b..4d31fb6c1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -210,6 +210,24 @@ void MainWindow::initCustomUI() { WheelFilter *wheelFilter = new WheelFilter(this); ui->mainTabBar->installEventFilter(wheelFilter); this->ui->mapListContainer->tabBar()->installEventFilter(wheelFilter); + + // Create buttons for adding and removing items from the mapList + QFrame *frame = new QFrame(this->ui->mapListContainer); + frame->setFrameShape(QFrame::NoFrame); + QHBoxLayout *layout = new QHBoxLayout(frame); + + QPushButton *buttonAdd = new QPushButton(QIcon(":/icons/add.ico"), ""); + connect(buttonAdd, &QPushButton::clicked, [this]() { this->mapListAddItem(); }); + QPushButton *buttonRemove = new QPushButton(QIcon(":/icons/delete.ico"), ""); + connect(buttonRemove, &QPushButton::clicked, [this]() { this->mapListRemoveItem(); }); + + layout->addWidget(buttonAdd); + layout->addWidget(buttonRemove); + + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + + this->ui->mapListContainer->setCornerWidget(frame, Qt::TopRightCorner); } void MainWindow::initExtraSignals() { @@ -1178,12 +1196,6 @@ bool MainWindow::populateMapList() { this->layoutListProxyModel->setSourceModel(this->layoutTreeModel); ui->layoutList->setModel(layoutListProxyModel); - /// !TODO - // ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); - // ui->mapList->setDragEnabled(true); - // ui->mapList->setAcceptDrops(true); - // ui->mapList->setDropIndicatorShown(true); - // ui->mapList->setDragDropMode(QAbstractItemView::InternalMove); on_toolButton_EnableDisable_EditGroups_clicked(); return success; @@ -1270,6 +1282,58 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) { (this->*addFunction)(menu.exec(QCursor::pos())); } +void MainWindow::mapListAddGroup() { + QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint); + dialog.setWindowModality(Qt::ApplicationModal); + QDialogButtonBox newItemButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); + connect(&newItemButtonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + connect(&newItemButtonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + + QLineEdit *newNameEdit = new QLineEdit(&dialog); + newNameEdit->setClearButtonEnabled(true); + + static const QRegularExpression re_validChars("[_A-Za-z0-9]*$"); + QRegularExpressionValidator *validator = new QRegularExpressionValidator(re_validChars); + newNameEdit->setValidator(validator); + + QFormLayout form(&dialog); + + form.addRow("New Group Name", newNameEdit); + form.addRow(&newItemButtonBox); + + if (dialog.exec() == QDialog::Accepted) { + QString newFieldName = newNameEdit->text(); + if (newFieldName.isEmpty()) return; + this->mapGroupModel->insertGroupItem(newFieldName); + } +} + +void MainWindow::mapListAddLayout() { + // this->layoutTreeModel->insertMapItem(newMapName, newMap->layout->id); +} + +void MainWindow::mapListAddArea() { + // this->mapAreaModel->insertMapItem(newMapName, newMap->location, newMapGroup); +} + +void MainWindow::mapListAddItem() { + switch (this->ui->mapListContainer->currentIndex()) { + case 0: + this->mapListAddGroup(); + break; + case 1: + this->mapListAddLayout(); + break; + case 2: + this->mapListAddArea(); + break; + } +} + +void MainWindow::mapListRemoveItem() { + // !TODO +} + void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) { if (!triggeredAction) return; diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index d22f2af63..ee60affc3 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -156,15 +156,26 @@ bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i rowCount++; } - this->insertRows(firstRow, rowCount, parentIndex); - - int newItemIndex = 0; - for (QString mapName : droppedMaps) { - QModelIndex mapIndex = index(firstRow, 0, parentIndex); - QStandardItem *mapItem = this->itemFromIndex(mapIndex); - createMapItem(mapName, mapItem); - firstRow++; + QStandardItem *groupItem = this->itemFromIndex(parentIndex); + if (groupItem->hasChildren()) { + this->insertRows(firstRow, rowCount, parentIndex); + for (QString mapName : droppedMaps) { + QModelIndex mapIndex = index(firstRow, 0, parentIndex); + QStandardItem *mapItem = this->itemFromIndex(mapIndex); + createMapItem(mapName, mapItem); + firstRow++; + } + } + // for whatever reason insertRows doesn't work as I expected with childless items + // so just append all the new maps instead + else { + for (QString mapName : droppedMaps) { + QStandardItem *mapItem = createMapItem(mapName); + groupItem->appendRow(mapItem); + firstRow++; + } } + } emit dragMoveCompleted(); @@ -189,6 +200,10 @@ void MapGroupModel::updateProject() { QStringList mapsInGroup; for (int m = 0; m < groupItem->rowCount(); m++) { QStandardItem *mapItem = groupItem->child(m); + if (!mapItem) { + logError("An error occured while trying to apply updates to map group structure."); + return; + } QString mapName = mapItem->data(Qt::UserRole).toString(); mapsInGroup.append(mapName); mapNames.append(mapName); @@ -222,10 +237,17 @@ QStandardItem *MapGroupModel::createMapItem(QString mapName, QStandardItem *map) return map; } +QStandardItem *MapGroupModel::insertGroupItem(QString groupName) { + QStandardItem *group = createGroupItem(groupName, this->groupItems.size()); + this->root->appendRow(group); + this->updateProject(); + return group; +} + QStandardItem *MapGroupModel::insertMapItem(QString mapName, QString groupName) { QStandardItem *group = this->groupItems[groupName]; if (!group) { - return nullptr; + group = insertGroupItem(groupName); } QStandardItem *map = createMapItem(mapName); group->appendRow(map); From 22b4108a7f11afb3edcb132059f9373a5052d677 Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 15 Feb 2024 22:19:49 -0500 Subject: [PATCH 41/70] create 'add layout' button --- include/core/maplayout.h | 11 ++++ include/project.h | 5 +- include/ui/maplistmodels.h | 1 + src/editor.cpp | 1 + src/mainwindow.cpp | 120 ++++++++++++++++++++++++++++++++++++- src/project.cpp | 88 +++++++++++++++++++++------ src/ui/maplistmodels.cpp | 9 +++ 7 files changed, 213 insertions(+), 22 deletions(-) diff --git a/include/core/maplayout.h b/include/core/maplayout.h index 7ec240b6e..cdd3b5d6b 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -69,6 +69,17 @@ class Layout : public QObject { QUndoStack editHistory; + // to simplify new layout settings transfer between functions + struct SimpleSettings { + QString id; + QString name; + int width; + int height; + QString tileset_primary_label; + QString tileset_secondary_label; + QString from_id = QString(); + }; + public: Layout *copy(); void copyFrom(Layout *other); diff --git a/include/project.h b/include/project.h index 85c8e3de5..49bcd6aac 100644 --- a/include/project.h +++ b/include/project.h @@ -139,6 +139,7 @@ class Project : public QObject bool loadMapData(Map*); bool readMapLayouts(); Layout *loadLayout(QString layoutId); + Layout *createNewLayout(Layout::SimpleSettings &layoutSettings); bool loadLayout(Layout *); bool loadMapLayout(Map*); bool loadLayoutTilesets(Layout *); @@ -235,8 +236,8 @@ class Project : public QObject private: void updateLayout(Layout *); - void setNewMapBlockdata(Map* map); - void setNewMapBorder(Map *map); + void setNewLayoutBlockdata(Layout *layout); + void setNewLayoutBorder(Layout *layout); void setNewMapEvents(Map *map); void setNewMapConnections(Map *map); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index a2babda6e..bb2fd07ad 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -155,6 +155,7 @@ class LayoutTreeModel : public QStandardItemModel { QStandardItem *createLayoutItem(QString layoutId); QStandardItem *createMapItem(QString mapName); + QStandardItem *insertLayoutItem(QString layoutId); QStandardItem *insertMapItem(QString mapName, QString layoutId); QStandardItem *getItem(const QModelIndex &index) const; diff --git a/src/editor.cpp b/src/editor.cpp index 5ed977824..aaad47db5 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -74,6 +74,7 @@ void Editor::save() { } else if (this->project && this->layout) { this->project->saveLayout(this->layout); + this->project->saveAllDataStructures(); } } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4d31fb6c1..8a9f95b55 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1309,7 +1309,121 @@ void MainWindow::mapListAddGroup() { } void MainWindow::mapListAddLayout() { - // this->layoutTreeModel->insertMapItem(newMapName, newMap->layout->id); + if (!editor || !editor->project) return; + + QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint); + dialog.setWindowModality(Qt::ApplicationModal); + QDialogButtonBox newItemButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); + connect(&newItemButtonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + + QLineEdit *newNameEdit = new QLineEdit(&dialog); + newNameEdit->setClearButtonEnabled(true); + + static const QRegularExpression re_validChars("[_A-Za-z0-9]*$"); + QRegularExpressionValidator *validator = new QRegularExpressionValidator(re_validChars); + newNameEdit->setValidator(validator); + + QLabel *newId = new QLabel("LAYOUT_", &dialog); + connect(newNameEdit, &QLineEdit::textChanged, [&](QString text){ + newId->setText(Layout::layoutConstantFromName(text.remove("_Layout"))); + }); + + NoScrollComboBox *useExistingCombo = new NoScrollComboBox(&dialog); + useExistingCombo->addItems(this->editor->project->mapLayoutsTable); + useExistingCombo->setEnabled(false); + + QCheckBox *useExistingCheck = new QCheckBox(&dialog); + + QLabel *errorMessageLabel = new QLabel(&dialog); + errorMessageLabel->setVisible(false); + errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }"); + QString errorMessage; + + QComboBox *primaryCombo = new QComboBox(&dialog); + primaryCombo->addItems(this->editor->project->primaryTilesetLabels); + QComboBox *secondaryCombo = new QComboBox(&dialog); + secondaryCombo->addItems(this->editor->project->secondaryTilesetLabels); + + QSpinBox *widthSpin = new QSpinBox(&dialog); + QSpinBox *heightSpin = new QSpinBox(&dialog); + + widthSpin->setMinimum(1); + heightSpin->setMinimum(1); + widthSpin->setMaximum(this->editor->project->getMaxMapWidth()); + heightSpin->setMaximum(this->editor->project->getMaxMapHeight()); + + connect(useExistingCheck, &QCheckBox::stateChanged, [&](int state){ + bool useExisting = (state == Qt::Checked); + useExistingCombo->setEnabled(useExisting); + primaryCombo->setEnabled(!useExisting); + secondaryCombo->setEnabled(!useExisting); + widthSpin->setEnabled(!useExisting); + heightSpin->setEnabled(!useExisting); + }); + + QFormLayout form(&dialog); + form.addRow("New Layout Name", newNameEdit); + form.addRow("New Layout ID", newId); + form.addRow("Copy Existing Layout", useExistingCheck); + form.addRow("", useExistingCombo); + form.addRow("Primary Tileset", primaryCombo); + form.addRow("Secondary Tileset", secondaryCombo); + form.addRow("Layout Width", widthSpin); + form.addRow("Layout Height", heightSpin); + form.addRow("", errorMessageLabel); + + connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ + // verify some things + bool issue = false; + QString tryLayoutName = newNameEdit->text(); + // name not empty + if (tryLayoutName.isEmpty()) { + errorMessage = "Name cannot be empty"; + issue = true; + } + // unique layout name & id + else if (this->editor->project->mapLayoutsTable.contains(newId->text()) + || this->editor->project->layoutIdsToNames.find(tryLayoutName) != this->editor->project->layoutIdsToNames.end()) { + errorMessage = "Layout Name / ID is not unique"; + issue = true; + } + // from id is existing value + else if (useExistingCheck->isChecked()) { + if (!this->editor->project->mapLayoutsTable.contains(useExistingCombo->currentText())) { + errorMessage = "Existing layout ID is not valid"; + issue = true; + } + } + + if (issue) { + // show error + errorMessageLabel->setText(errorMessage); + errorMessageLabel->setVisible(true); + } + else { + dialog.accept(); + } + }); + + form.addRow(&newItemButtonBox); + + if (dialog.exec() == QDialog::Accepted) { + Layout::SimpleSettings layoutSettings; + QString layoutName = newNameEdit->text(); + layoutSettings.name = layoutName; + layoutSettings.id = Layout::layoutConstantFromName(layoutName.remove("_Layout")); + if (useExistingCheck->isChecked()) { + layoutSettings.from_id = useExistingCombo->currentText(); + } else { + layoutSettings.width = widthSpin->value(); + layoutSettings.height = heightSpin->value(); + layoutSettings.tileset_primary_label = primaryCombo->currentText(); + layoutSettings.tileset_secondary_label = secondaryCombo->currentText(); + } + Layout *newLayout = this->editor->project->createNewLayout(layoutSettings); + QStandardItem *item = this->layoutTreeModel->insertLayoutItem(newLayout->id); + setLayout(newLayout->id); + } } void MainWindow::mapListAddArea() { @@ -1322,10 +1436,10 @@ void MainWindow::mapListAddItem() { this->mapListAddGroup(); break; case 1: - this->mapListAddLayout(); + this->mapListAddArea(); break; case 2: - this->mapListAddArea(); + this->mapListAddLayout(); break; } } diff --git a/src/project.cpp b/src/project.cpp index 41f9ccf99..81f472ed1 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -385,6 +385,60 @@ QString Project::readMapLocation(QString map_name) { return ParseUtil::jsonToQString(mapObj["region_map_section"]); } +Layout *Project::createNewLayout(Layout::SimpleSettings &layoutSettings) { + QString basePath = projectConfig.getFilePath(ProjectFilePath::data_layouts_folders); + Layout *layout; + + // Handle the case where we are copying from an existing layout first. + if (!layoutSettings.from_id.isEmpty()) { + // load from layout + loadLayout(mapLayouts[layoutSettings.from_id]); + + layout = mapLayouts[layoutSettings.from_id]->copy(); + layout->name = layoutSettings.name; + layout->id = layoutSettings.id; + layout->border_path = QString("%1%2/border.bin").arg(basePath, layoutSettings.name); + layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, layoutSettings.name); + } + else { + layout = new Layout; + + layout->name = layoutSettings.name; + layout->id = layoutSettings.id; + layout->width = layoutSettings.width; + layout->height = layoutSettings.height; + layout->border_width = DEFAULT_BORDER_WIDTH; + layout->border_height = DEFAULT_BORDER_HEIGHT; + layout->tileset_primary_label = layoutSettings.tileset_primary_label; + layout->tileset_secondary_label = layoutSettings.tileset_secondary_label; + layout->border_path = QString("%1%2/border.bin").arg(basePath, layoutSettings.name); + layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, layoutSettings.name); + + setNewLayoutBlockdata(layout); + setNewLayoutBorder(layout); + } + + // Create a new directory for the layout + QString newLayoutDir = QString(root + "/%1%2").arg(projectConfig.getFilePath(ProjectFilePath::data_layouts_folders), layout->name); + if (!QDir::root().mkdir(newLayoutDir)) { + logError(QString("Error: failed to create directory for new layout: '%1'").arg(newLayoutDir)); + delete layout; + return nullptr; + } + + mapLayouts.insert(layout->id, layout); + mapLayoutsMaster.insert(layout->id, layout->copy()); + mapLayoutsTable.append(layout->id); + mapLayoutsTableMaster.append(layout->id); + layoutIdsToNames.insert(layout->id, layout->name); + + saveLayout(layout); + + this->loadLayout(layout); + + return layout; +} + bool Project::loadLayout(Layout *layout) { // !TODO: make sure this doesn't break anything, maybe do something better. new layouts work too? if (!layout->loaded) { @@ -1119,16 +1173,16 @@ bool Project::loadBlockdata(Layout *layout) { return true; } -void Project::setNewMapBlockdata(Map *map) { - map->layout->blockdata.clear(); - int width = map->getWidth(); - int height = map->getHeight(); +void Project::setNewLayoutBlockdata(Layout *layout) { + layout->blockdata.clear(); + int width = layout->getWidth(); + int height = layout->getHeight(); Block block(projectConfig.getDefaultMetatileId(), projectConfig.getDefaultCollision(), projectConfig.getDefaultElevation()); for (int i = 0; i < width * height; i++) { - map->layout->blockdata.append(block); + layout->blockdata.append(block); } - map->layout->lastCommitBlocks.blocks = map->layout->blockdata; - map->layout->lastCommitBlocks.layoutDimensions = QSize(width, height); + layout->lastCommitBlocks.blocks = layout->blockdata; + layout->lastCommitBlocks.layoutDimensions = QSize(width, height); } bool Project::loadLayoutBorder(Layout *layout) { @@ -1147,27 +1201,27 @@ bool Project::loadLayoutBorder(Layout *layout) { return true; } -void Project::setNewMapBorder(Map *map) { - map->layout->border.clear(); - int width = map->getBorderWidth(); - int height = map->getBorderHeight(); +void Project::setNewLayoutBorder(Layout *layout) { + layout->border.clear(); + int width = layout->getBorderWidth(); + int height = layout->getBorderHeight(); const QList configMetatileIds = projectConfig.getNewMapBorderMetatileIds(); if (configMetatileIds.length() != width * height) { // Border size doesn't match the number of default border metatiles. // Fill the border with empty metatiles. for (int i = 0; i < width * height; i++) { - map->layout->border.append(0); + layout->border.append(0); } } else { // Fill the border with the default metatiles from the config. for (int i = 0; i < width * height; i++) { - map->layout->border.append(configMetatileIds.at(i)); + layout->border.append(configMetatileIds.at(i)); } } - map->layout->lastCommitBlocks.border = map->layout->border; - map->layout->lastCommitBlocks.borderDimensions = QSize(width, height); + layout->lastCommitBlocks.border = layout->border; + layout->lastCommitBlocks.borderDimensions = QSize(width, height); } void Project::saveLayoutBorder(Layout *layout) { @@ -1809,10 +1863,10 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool mapLayoutsTable.append(newMap->layoutId); layoutIdsToNames.insert(newMap->layout->id, newMap->layout->name); if (!importedMap) { - setNewMapBlockdata(newMap); + setNewLayoutBlockdata(newMap->layout); } if (newMap->layout->border.isEmpty()) { - setNewMapBorder(newMap); + setNewLayoutBorder(newMap->layout); } } diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index ee60affc3..a572c7eb1 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -535,6 +535,11 @@ QStandardItem *LayoutTreeModel::createMapItem(QString mapName) { return map; } +QStandardItem *LayoutTreeModel::insertLayoutItem(QString layoutId) { + QStandardItem *layoutItem = this->createLayoutItem(layoutId); + this->root->appendRow(layoutItem); +} + QStandardItem *LayoutTreeModel::insertMapItem(QString mapName, QString layoutId) { QStandardItem *layout = nullptr; if (this->layoutItems.contains(layoutId)) { @@ -591,6 +596,7 @@ QVariant LayoutTreeModel::data(const QModelIndex &index, int role) const { int col = index.column(); if (role == Qt::DecorationRole) { + static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico")); static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico")); static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico")); static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico")); @@ -607,6 +613,9 @@ QVariant LayoutTreeModel::data(const QModelIndex &index, int role) const { if (this->project->mapLayouts.value(layoutId)->hasUnsavedChanges()) { return mapEditedIcon; } + else if (!this->project->mapLayouts[layoutId]->loaded) { + return mapGrayIcon; + } } return mapIcon; } From 74e4e2647c280998a51c3a7118da73aab36adce5 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 16 Feb 2024 19:17:56 -0500 Subject: [PATCH 42/70] add new area (map section) functionality --- include/project.h | 6 ++++ include/ui/maplistmodels.h | 1 + src/mainwindow.cpp | 30 ++++++++++++++++- src/project.cpp | 66 ++++++++++++++++++++++++++++++++++++++ src/ui/maplistmodels.cpp | 8 +++++ 5 files changed, 110 insertions(+), 1 deletion(-) diff --git a/include/project.h b/include/project.h index 49bcd6aac..b84264537 100644 --- a/include/project.h +++ b/include/project.h @@ -80,6 +80,9 @@ class Project : public QObject QString importExportPath; QSet disabledSettingsNames; + // For files that are read and could contain extra text + QMap extraFileText; + void set_root(QString); void initSignals(); @@ -135,6 +138,8 @@ class Project : public QObject bool readSpeciesIconPaths(); QMap speciesToIconPath; + int appendMapsec(QString name); + QSet getTopLevelMapFields(); bool loadMapData(Map*); bool readMapLayouts(); @@ -159,6 +164,7 @@ class Project : public QObject void saveAllDataStructures(); void saveMapLayouts(); void saveMapGroups(); + void saveMapSections(); void saveWildMonData(); void saveMapConstantsHeader(); void saveHealLocations(Map*); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index bb2fd07ad..5787a6226 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -117,6 +117,7 @@ class MapAreaModel : public QStandardItemModel { QStandardItem *createAreaItem(QString areaName, int areaIndex); QStandardItem *createMapItem(QString mapName, int areaIndex, int mapIndex); + QStandardItem *insertAreaItem(QString areaName); QStandardItem *insertMapItem(QString mapName, QString areaName, int groupIndex); QStandardItem *getItem(const QModelIndex &index) const; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8a9f95b55..dc0ac54f7 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1427,7 +1427,35 @@ void MainWindow::mapListAddLayout() { } void MainWindow::mapListAddArea() { - // this->mapAreaModel->insertMapItem(newMapName, newMap->location, newMapGroup); + // Note: there is no checking here for the limits on map section count + QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint); + dialog.setWindowModality(Qt::ApplicationModal); + QDialogButtonBox newItemButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); + connect(&newItemButtonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + + QLineEdit *newNameEdit = new QLineEdit(&dialog); + newNameEdit->setText(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix)); + newNameEdit->setClearButtonEnabled(false); + + QRegularExpression re_validChars(QString("%1[_A-Za-z0-9]+$").arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))); + QRegularExpressionValidator *validator = new QRegularExpressionValidator(re_validChars); + newNameEdit->setValidator(validator); + + connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ + if (!this->editor->project->mapSectionNameToValue.contains(newNameEdit->text())) + dialog.accept(); + }); + + QFormLayout form(&dialog); + + form.addRow("New Map Section Name", newNameEdit); + form.addRow(&newItemButtonBox); + + if (dialog.exec() == QDialog::Accepted) { + QString newFieldName = newNameEdit->text(); + if (newFieldName.isEmpty()) return; + this->mapAreaModel->insertAreaItem(newFieldName); + } } void MainWindow::mapListAddItem() { diff --git a/src/project.cpp b/src/project.cpp index 81f472ed1..6ee185516 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -700,6 +700,34 @@ void Project::saveMapGroups() { mapGroupsFile.close(); } +void Project::saveMapSections() { + QString filepath = root + "/" + projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections); + + QString text = QString("#ifndef GUARD_REGIONMAPSEC_H\n"); + text += QString("#define GUARD_REGIONMAPSEC_H\n\n"); + + int longestLength = 0; + for (QString label : this->mapSectionNameToValue.keys()) { + if (label.size() > longestLength) + longestLength = label.size(); + } + + // mapSectionValueToName + for (int value : this->mapSectionValueToName.keys()) { + QString line = QString("#define %1 0x%2\n") + .arg(this->mapSectionValueToName[value], -1 * longestLength) + .arg(QString("%1").arg(value, 2, 16, QLatin1Char('0')).toUpper()); + text += line; + } + + text += "\n" + this->extraFileText[projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections)] + "\n"; + + text += QString("#endif // GUARD_REGIONMAPSEC_H\n"); + + ignoreWatchedFileTemporarily(filepath); + saveTextFile(filepath, text); +} + void Project::saveWildMonData() { if (!userConfig.getEncounterJsonActive()) return; @@ -1421,6 +1449,7 @@ void Project::updateLayout(Layout *layout) { void Project::saveAllDataStructures() { saveMapLayouts(); saveMapGroups(); + saveMapSections(); saveMapConstantsHeader(); saveWildMonData(); } @@ -2158,9 +2187,46 @@ bool Project::readRegionMapSections() { for (QString defineName : this->mapSectionNameToValue.keys()) { this->mapSectionValueToName.insert(this->mapSectionNameToValue[defineName], defineName); } + + // extra text + QString extraText; + QString fileText = ParseUtil::readTextFile(root + "/" + filename); + QTextStream stream(&fileText); + QString currentLine; + while (stream.readLineInto(¤tLine)) { + // is this line something that porymap will output again? + if (currentLine.isEmpty()) { + continue; + } + // include guards + else if (currentLine.contains("GUARD_REGIONMAPSEC_H")) { + continue; + } + // defines captured (not considering comments) + else if (currentLine.contains("#define " + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))) { + continue; + } + // everything else should be kept here + else { + extraText += currentLine + "\n"; + } + } + stream.seek(0); + this->extraFileText[filename] = extraText; return true; } +int Project::appendMapsec(QString name) { + // This function assumes a valid and unique name. + // Will return the new index. + int noneBefore = this->mapSectionNameToValue[projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + "NONE"]; + this->mapSectionNameToValue[name] = noneBefore; + this->mapSectionValueToName[noneBefore] = name; + this->mapSectionNameToValue[projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + "NONE"] = noneBefore + 1; + this->mapSectionValueToName[noneBefore + 1] = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + "NONE"; + return noneBefore; +} + // Read the constants to preserve any "unused" heal locations when writing the file later bool Project::readHealLocationConstants() { this->healLocationNameToValue.clear(); diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index a572c7eb1..8dbc24b87 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -392,6 +392,14 @@ QStandardItem *MapAreaModel::createMapItem(QString mapName, int groupIndex, int return map; } +QStandardItem *MapAreaModel::insertAreaItem(QString areaName) { + int newAreaIndex = this->project->appendMapsec(areaName); + QStandardItem *item = createAreaItem(areaName, newAreaIndex); + this->root->insertRow(newAreaIndex, item); + this->areaItems["MAPSEC_NONE"]->setData(newAreaIndex + 1, MapListRoles::GroupRole); + return item; +} + QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, int groupIndex) { // int areaIndex = this->project->mapSectionNameToValue[areaName]; QStandardItem *area = this->areaItems[areaName]; From 879bb44bc0abd9a574fa269a39fb583a582ca2ca Mon Sep 17 00:00:00 2001 From: garak Date: Sat, 17 Feb 2024 22:47:48 -0500 Subject: [PATCH 43/70] functions to remove map groups and map sections --- include/mainwindow.h | 3 ++ include/ui/maplistmodels.h | 2 ++ src/mainwindow.cpp | 57 +++++++++++++++++++++++++++++++++++++- src/project.cpp | 2 ++ src/ui/maplistmodels.cpp | 14 ++++++++++ 5 files changed, 77 insertions(+), 1 deletion(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 0c3bd4ee0..73d16a917 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -394,6 +394,9 @@ private slots: void mapListAddGroup(); void mapListAddLayout(); void mapListAddArea(); + void mapListRemoveGroup(); + void mapListRemoveArea(); + void mapListRemoveLayout(); void displayMapProperties(); void checkToolButtons(); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 5787a6226..7d56da17d 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -77,6 +77,7 @@ class MapGroupModel : public QStandardItemModel { QStandardItem *insertGroupItem(QString groupName); QStandardItem *insertMapItem(QString mapName, QString groupName); + void removeGroup(int groupIndex); QStandardItem *getItem(const QModelIndex &index) const; QModelIndex indexOfMap(QString mapName); @@ -119,6 +120,7 @@ class MapAreaModel : public QStandardItemModel { QStandardItem *insertAreaItem(QString areaName); QStandardItem *insertMapItem(QString mapName, QString areaName, int groupIndex); + void removeArea(int groupIndex); QStandardItem *getItem(const QModelIndex &index) const; QModelIndex indexOfMap(QString mapName); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index dc0ac54f7..b96003a98 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1459,6 +1459,8 @@ void MainWindow::mapListAddArea() { } void MainWindow::mapListAddItem() { + if (!this->editor || !this->editor->project) return; + switch (this->ui->mapListContainer->currentIndex()) { case 0: this->mapListAddGroup(); @@ -1472,8 +1474,61 @@ void MainWindow::mapListAddItem() { } } +void MainWindow::mapListRemoveGroup() { + QItemSelectionModel *selectionModel = this->ui->mapList->selectionModel(); + if (selectionModel->hasSelection()) { + QModelIndexList selectedIndexes = selectionModel->selectedRows(); + for (QModelIndex proxyIndex : selectedIndexes) { + QModelIndex index = this->groupListProxyModel->mapToSource(proxyIndex); + QStandardItem *item = this->mapGroupModel->getItem(index)->child(index.row(), index.column()); + if (!item) continue; + QString type = item->data(MapListRoles::TypeRole).toString(); + if (type == "map_group" && !item->hasChildren()) { + QString groupName = item->data(Qt::UserRole).toString(); + // delete empty group + this->mapGroupModel->removeGroup(index.row()); + } + } + } +} + +void MainWindow::mapListRemoveArea() { + QItemSelectionModel *selectionModel = this->ui->areaList->selectionModel(); + if (selectionModel->hasSelection()) { + QModelIndexList selectedIndexes = selectionModel->selectedRows(); + for (QModelIndex proxyIndex : selectedIndexes) { + QModelIndex index = this->areaListProxyModel->mapToSource(proxyIndex); + QStandardItem *item = this->mapAreaModel->getItem(index)->child(index.row(), index.column()); + if (!item) continue; + QString type = item->data(MapListRoles::TypeRole).toString(); + if (type == "map_section" && !item->hasChildren()) { + QString groupName = item->data(Qt::UserRole).toString(); + // delete empty section + this->mapAreaModel->removeArea(index.row()); + } + } + } +} + +void MainWindow::mapListRemoveLayout() { + // TODO: consider this + // do nothing, for now at least +} + void MainWindow::mapListRemoveItem() { - // !TODO + if (!this->editor || !this->editor->project) return; + + switch (this->ui->mapListContainer->currentIndex()) { + case 0: + this->mapListRemoveGroup(); + break; + case 1: + this->mapListRemoveArea(); + break; + case 2: + this->mapListRemoveLayout(); + break; + } } void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) { diff --git a/src/project.cpp b/src/project.cpp index 6ee185516..0f641c91b 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -712,6 +712,8 @@ void Project::saveMapSections() { longestLength = label.size(); } + longestLength += 1; + // mapSectionValueToName for (int value : this->mapSectionValueToName.keys()) { QString line = QString("#define %1 0x%2\n") diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 8dbc24b87..880a98cae 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -244,6 +244,11 @@ QStandardItem *MapGroupModel::insertGroupItem(QString groupName) { return group; } +void MapGroupModel::removeGroup(int groupIndex) { + this->removeRow(groupIndex); + this->updateProject(); +} + QStandardItem *MapGroupModel::insertMapItem(QString mapName, QString groupName) { QStandardItem *group = this->groupItems[groupName]; if (!group) { @@ -412,6 +417,11 @@ QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, in return map; } +void MapAreaModel::removeArea(int areaIndex) { + this->removeRow(areaIndex); + this->project->mapSectionNameToValue.remove(this->project->mapSectionValueToName.take(areaIndex)); +} + void MapAreaModel::initialize() { this->areaItems.clear(); this->mapItems.clear(); @@ -454,6 +464,8 @@ QModelIndex MapAreaModel::indexOfMap(QString mapName) { } QVariant MapAreaModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) return QVariant(); + int row = index.row(); int col = index.column(); @@ -600,6 +612,8 @@ QModelIndex LayoutTreeModel::indexOfLayout(QString layoutName) { } QVariant LayoutTreeModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) return QVariant(); + int row = index.row(); int col = index.column(); From 05beed21cada72ff095ce31b9c453fe614ce75a6 Mon Sep 17 00:00:00 2001 From: garak Date: Sun, 18 Feb 2024 19:56:52 -0500 Subject: [PATCH 44/70] disable deletion of map sections and layouts --- src/mainwindow.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b96003a98..d6e8ece22 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1511,8 +1511,7 @@ void MainWindow::mapListRemoveArea() { } void MainWindow::mapListRemoveLayout() { - // TODO: consider this - // do nothing, for now at least + // TODO: consider this in the future } void MainWindow::mapListRemoveItem() { @@ -1523,10 +1522,12 @@ void MainWindow::mapListRemoveItem() { this->mapListRemoveGroup(); break; case 1: - this->mapListRemoveArea(); + // Disabled + // this->mapListRemoveArea(); break; case 2: - this->mapListRemoveLayout(); + // Disabled + // this->mapListRemoveLayout(); break; } } @@ -1758,7 +1759,6 @@ void MainWindow::currentMetatilesSelectionChanged() // !TODO void MainWindow::on_mapListContainer_currentChanged(int index) { - // switch (index) { case MapListTab::Groups: this->mapSortOrder = MapSortOrder::SortByGroup; From 70c6e414f118acb9d6f13ef938846f5aa95041a6 Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 28 Mar 2024 10:21:35 -0400 Subject: [PATCH 45/70] reopen porymap on layout view when applicable --- include/mainwindow.h | 1 + src/mainwindow.cpp | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 04c04cef0..177196bb6 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -387,6 +387,7 @@ private slots: void setRecentMapConfig(QString map_name); void setRecentLayoutConfig(QString layoutId); bool setInitialMap(); + bool setInitialLayout(); void setRecentMap(QString map_name); QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum); void refreshRecentProjectsMenu(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4ff36eef7..842f9fb37 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -617,7 +617,7 @@ bool MainWindow::openProject(const QString &dir, bool initial) { this->projectOpenFailure = !(loadDataStructures() && populateMapList() - && setInitialMap()); + && (this->mapSortOrder == MapSortOrder::SortByLayout ? setInitialLayout() : setInitialMap())); if (this->projectOpenFailure) { this->statusBar()->showMessage(QString("Failed to open %1").arg(projectString)); @@ -713,6 +713,26 @@ bool MainWindow::setInitialMap() { return false; } +bool MainWindow::setInitialLayout() { + QStringList names; + if (editor && editor->project) + names = editor->project->mapLayoutsTable; + + // Try to set most recently-opened layout, if it's still in the list. + QString recentLayout = userConfig.getRecentLayout(); + if (!recentLayout.isEmpty() && names.contains(recentLayout) && setLayout(recentLayout)) + return true; + + // Failing that, try loading maps in the map list sequentially. + for (auto name : names) { + if (name != recentLayout && setLayout(name)) + return true; + } + + logError("Failed to load any layouts."); + return false; +} + void MainWindow::refreshRecentProjectsMenu() { ui->menuOpen_Recent_Project->clear(); QStringList recentProjects = porymapConfig.getRecentProjects(); @@ -980,10 +1000,12 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_ void MainWindow::setRecentMapConfig(QString mapName) { userConfig.setRecentMap(mapName); + userConfig.setRecentLayout(""); } void MainWindow::setRecentLayoutConfig(QString layoutId) { userConfig.setRecentLayout(layoutId); + userConfig.setRecentMap(""); } void MainWindow::displayMapProperties() { From 89fb4019a527acb0afb13ed38390685812f0bbba Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 18 Apr 2024 12:21:09 -0400 Subject: [PATCH 46/70] cleanup shortcuts --- include/mainwindow.h | 3 +++ src/core/map.cpp | 1 - src/editor.cpp | 4 +-- src/mainwindow.cpp | 62 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 177196bb6..12af3585b 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -280,6 +280,9 @@ private slots: void on_horizontalSlider_CollisionTransparency_valueChanged(int value); + void on_toolButton_HideShow_clicked(); + void on_toolButton_ExpandAll_clicked(); + void on_toolButton_CollapseAll_clicked(); void on_toolButton_HideShow_Groups_clicked(); void on_toolButton_ExpandAll_Groups_clicked(); void on_toolButton_CollapseAll_Groups_clicked(); diff --git a/src/core/map.cpp b/src/core/map.cpp index f9782266a..1d52a0ba4 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -186,6 +186,5 @@ void Map::clean() { } bool Map::hasUnsavedChanges() { - // !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/editor.cpp b/src/editor.cpp index aaad47db5..1ae94b409 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -139,7 +139,7 @@ void Editor::setEditorView() { } break; case EditMode::Connections: - populateConnectionMapPickers(); // !TODO: move to setmap or sumn/ displaymapconnections type ish + populateConnectionMapPickers(); ui->label_NumConnections->setText(QString::number(map->connections.length())); setDiveEmergeControls(); @@ -155,7 +155,7 @@ void Editor::setEditorView() { setConnectionItemsVisible(true); setConnectionsEditable(true); this->cursorMapTileRect->setActive(false); - map_item->setEditsEnabled(false); // !TODO + map_item->setEditsEnabled(false); case EditMode::Header: case EditMode::Encounters: default: diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 842f9fb37..5675d79e5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -162,14 +162,17 @@ void MainWindow::initExtraShortcuts() { shortcutToggle_Smart_Paths->setObjectName("shortcutToggle_Smart_Paths"); shortcutToggle_Smart_Paths->setWhatsThis("Toggle Smart Paths"); - /// !TODO - // auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_ExpandAll_clicked())); - // shortcutExpand_All->setObjectName("shortcutExpand_All"); - // shortcutExpand_All->setWhatsThis("Map List: Expand all folders"); + auto *shortcutHide_Show = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_HideShow_clicked())); + shortcutHide_Show->setObjectName("shortcutHide_Show"); + shortcutHide_Show->setWhatsThis("Map List: Hide/Show Empty Folders"); + + auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_ExpandAll_clicked())); + shortcutExpand_All->setObjectName("shortcutExpand_All"); + shortcutExpand_All->setWhatsThis("Map List: Expand all folders"); - // auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_CollapseAll_clicked())); - // shortcutCollapse_All->setObjectName("shortcutCollapse_All"); - // shortcutCollapse_All->setWhatsThis("Map List: Collapse all folders"); + auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_CollapseAll_clicked())); + shortcutCollapse_All->setObjectName("shortcutCollapse_All"); + shortcutCollapse_All->setWhatsThis("Map List: Collapse all folders"); auto *shortcut_Open_Scripts = new Shortcut(QKeySequence(), ui->toolButton_Open_Scripts, SLOT(click())); shortcut_Open_Scripts->setObjectName("shortcut_Open_Scripts"); @@ -905,8 +908,7 @@ bool MainWindow::setLayout(QString layoutId) { updateMapList(); // !TODO: make sure these connections are not duplicated / cleared later - connect(editor->layout, &Layout::layoutChanged, [this]() { onMapChanged(nullptr); }); - connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing); + connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing, Qt::UniqueConnection); // connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); updateTilesetEditor(); @@ -3178,6 +3180,48 @@ void MainWindow::initTilesetEditor() { connect(this->tilesetEditor, &TilesetEditor::tilesetsSaved, this, &MainWindow::onTilesetsSaved); } +void MainWindow::on_toolButton_ExpandAll_clicked() { + switch (ui->mapListContainer->currentIndex()) { + case MapListTab::Groups: + this->on_toolButton_ExpandAll_Groups_clicked(); + break; + case MapListTab::Areas: + this->on_toolButton_ExpandAll_Areas_clicked(); + break; + case MapListTab::Layouts: + this->on_toolButton_ExpandAll_Layouts_clicked(); + break; + } +} + +void MainWindow::on_toolButton_CollapseAll_clicked() { + switch (ui->mapListContainer->currentIndex()) { + case MapListTab::Groups: + this->on_toolButton_CollapseAll_Groups_clicked(); + break; + case MapListTab::Areas: + this->on_toolButton_CollapseAll_Areas_clicked(); + break; + case MapListTab::Layouts: + this->on_toolButton_CollapseAll_Layouts_clicked(); + break; + } +} + +void MainWindow::on_toolButton_HideShow_clicked() { + switch (ui->mapListContainer->currentIndex()) { + case MapListTab::Groups: + this->on_toolButton_HideShow_Groups_clicked(); + break; + case MapListTab::Areas: + this->on_toolButton_HideShow_Areas_clicked(); + break; + case MapListTab::Layouts: + this->on_toolButton_HideShow_Layouts_clicked(); + break; + } +} + void MainWindow::on_toolButton_HideShow_Groups_clicked() { if (ui->mapList) { this->groupListProxyModel->toggleHideEmpty(); From 5bb0983c3319a7e4d71e89546ffe705eb82c41e1 Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 18 Apr 2024 13:25:06 -0400 Subject: [PATCH 47/70] cleanup: resolve map list scrolling --- include/mainwindow.h | 1 - src/mainwindow.cpp | 20 ++++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 12af3585b..d2350d727 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -379,7 +379,6 @@ private slots: bool loadDataStructures(); bool loadProjectCombos(); bool populateMapList(); - void sortMapList(); void openSubWindow(QWidget * window); void scrollTreeView(QString itemName); QString getExistingDirectory(QString); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5675d79e5..6afeca146 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -250,7 +250,6 @@ void MainWindow::initCustomUI() { } void MainWindow::initExtraSignals() { - /// !TODO // Right-clicking on items in the map list tree view brings up a context menu. ui->mapList->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->mapList, &QTreeView::customContextMenuRequested, @@ -402,17 +401,12 @@ void MainWindow::initMiscHeapObjects() { ui->tabWidget_EventType->clear(); } -// !TODO: scroll view on first showing void MainWindow::initMapSortOrder() { mapSortOrder = porymapConfig.getMapSortOrder(); - // if (mapSortOrder == MapSortOrder::SortByLayout) - // mapSortOrder = MapSortOrder::SortByGroup; - this->ui->mapListContainer->setCurrentIndex(static_cast(this->mapSortOrder)); } void MainWindow::showWindowTitle() { - // !TODO, check editor editmode if (editor->map) { setWindowTitle(QString("%1%2 - %3") .arg(editor->map->hasUnsavedChanges() ? "* " : "") @@ -490,18 +484,22 @@ void MainWindow::on_lineEdit_filterBox_Layouts_textChanged(const QString &text) void MainWindow::applyMapListFilter(QString filterText) { FilterChildrenProxyModel *proxy; QTreeView *list; + QModelIndex sourceIndex; switch (this->mapSortOrder) { case MapSortOrder::SortByGroup: proxy = this->groupListProxyModel; list = this->ui->mapList; + sourceIndex = mapGroupModel->indexOfMap(editor->map->name); break; case MapSortOrder::SortByArea: proxy = this->areaListProxyModel; list = this->ui->areaList; + sourceIndex = mapAreaModel->indexOfMap(editor->map->name); break; case MapSortOrder::SortByLayout: proxy = this->layoutListProxyModel; list = this->ui->layoutList; + sourceIndex = layoutTreeModel->indexOfLayout(editor->layout->id); break; } @@ -512,10 +510,8 @@ void MainWindow::applyMapListFilter(QString filterText) { list->expandToDepth(0); } - /// !TODO - // ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(map_name)), false); - // ui->mapList->setExpanded(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), true); - // ui->mapList->scrollTo(mapListProxyModel->mapFromSource(mapListIndexes.value(editor->map->name)), QAbstractItemView::PositionAtCenter); + list->setExpanded(proxy->mapFromSource(sourceIndex), true); + list->scrollTo(proxy->mapFromSource(sourceIndex), QAbstractItemView::PositionAtCenter); } void MainWindow::loadUserSettings() { @@ -1285,10 +1281,6 @@ void MainWindow::scrollTreeView(QString itemName) { } } -// !TODO: remove this? -void MainWindow::sortMapList() { -} - void MainWindow::onOpenMapListContextMenu(const QPoint &point) { QStandardItemModel *model; int dataRole; From f46ac36a94d7bee7aefdabbfad5929295ce4be50 Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 18 Apr 2024 14:38:15 -0400 Subject: [PATCH 48/70] cleanup: shortcuts, setLayout --- include/mainwindow.h | 7 ++++--- src/core/maplayout.cpp | 47 ++---------------------------------------- src/mainwindow.cpp | 34 ++++++++++++++---------------- 3 files changed, 21 insertions(+), 67 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index d2350d727..7ee2786c3 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -185,6 +185,7 @@ private slots: void onLoadMapRequested(QString, QString); void onMapChanged(Map *map); + void onLayoutChanged(Layout *layout); void onMapNeedsRedrawing(); void onLayoutNeedsRedrawing(); void onTilesetsSaved(QString, QString); @@ -280,9 +281,9 @@ private slots: void on_horizontalSlider_CollisionTransparency_valueChanged(int value); - void on_toolButton_HideShow_clicked(); - void on_toolButton_ExpandAll_clicked(); - void on_toolButton_CollapseAll_clicked(); + void do_HideShow(); + void do_ExpandAll(); + void do_CollapseAll(); void on_toolButton_HideShow_Groups_clicked(); void on_toolButton_ExpandAll_Groups_clicked(); void on_toolButton_CollapseAll_Groups_clicked(); diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 4f6393730..9e283e264 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -5,51 +5,8 @@ #include "scripting.h" #include "imageproviders.h" - // QString id; - // QString name; - - // int width; - // int height; - // int border_width; - // int border_height; - - // QString border_path; - // QString blockdata_path; - - // QString tileset_primary_label; - // QString tileset_secondary_label; - - // Tileset *tileset_primary = nullptr; - // Tileset *tileset_secondary = nullptr; - - // Blockdata blockdata; - - // QImage image; - // QPixmap pixmap; - // QImage border_image; - // QPixmap border_pixmap; - // QImage collision_image; - // QPixmap collision_pixmap; - - // Blockdata border; - // Blockdata cached_blockdata; - // Blockdata cached_collision; - // Blockdata cached_border; - // struct { - // Blockdata blocks; - // QSize mapDimensions; - // Blockdata border; - // QSize borderDimensions; - // } lastCommitBlocks; // to track map changes - - // QList metatileLayerOrder; - // QList metatileLayerOpacity; - - // LayoutPixmapItem *layoutItem = nullptr; - // CollisionPixmapItem *collisionItem = nullptr; - // BorderMetatilesPixmapItem *borderItem = nullptr; - - // QUndoStack editHistory; + + Layout *Layout::copy() { Layout *layout = new Layout; layout->copyFrom(this); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6afeca146..f7884ad63 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -162,15 +162,15 @@ void MainWindow::initExtraShortcuts() { shortcutToggle_Smart_Paths->setObjectName("shortcutToggle_Smart_Paths"); shortcutToggle_Smart_Paths->setWhatsThis("Toggle Smart Paths"); - auto *shortcutHide_Show = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_HideShow_clicked())); + auto *shortcutHide_Show = new Shortcut(QKeySequence(), this, SLOT(do_HideShow())); shortcutHide_Show->setObjectName("shortcutHide_Show"); shortcutHide_Show->setWhatsThis("Map List: Hide/Show Empty Folders"); - auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_ExpandAll_clicked())); + auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(do_ExpandAll())); shortcutExpand_All->setObjectName("shortcutExpand_All"); shortcutExpand_All->setWhatsThis("Map List: Expand all folders"); - auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(on_toolButton_CollapseAll_clicked())); + auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(do_CollapseAll())); shortcutCollapse_All->setObjectName("shortcutCollapse_All"); shortcutCollapse_All->setWhatsThis("Map List: Collapse all folders"); @@ -847,7 +847,6 @@ bool MainWindow::setMap(QString map_name, bool scroll) { } if (editor->map && !editor->map->name.isNull()) { - // !TODO: function to act on current view? or that does all the views ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(map_name)), false); } @@ -869,12 +868,12 @@ bool MainWindow::setMap(QString map_name, bool scroll) { showWindowTitle(); - connect(editor->map, &Map::mapChanged, this, &MainWindow::onMapChanged); - connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); - connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); + connect(editor->map, &Map::mapChanged, this, &MainWindow::onMapChanged, Qt::UniqueConnection); + connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing, Qt::UniqueConnection); + connect(editor->map, &Map::modified, this, &MainWindow::markMapEdited, Qt::UniqueConnection); - connect(editor->layout, &Layout::layoutChanged, [this]() { onMapChanged(nullptr); }); - connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing); + connect(editor->layout, &Layout::layoutChanged, this, &MainWindow::onLayoutChanged, Qt::UniqueConnection); + connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing, Qt::UniqueConnection); setRecentMapConfig(map_name); updateMapList(); @@ -903,9 +902,7 @@ bool MainWindow::setLayout(QString layoutId) { showWindowTitle(); updateMapList(); - // !TODO: make sure these connections are not duplicated / cleared later connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing, Qt::UniqueConnection); - // connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); }); updateTilesetEditor(); @@ -1064,12 +1061,9 @@ void MainWindow::displayMapProperties() { } void MainWindow::on_comboBox_LayoutSelector_currentTextChanged(const QString &text) { - // if (editor && editor->project && editor->map) { if (editor->project->mapLayouts.contains(text)) { editor->map->setLayout(editor->project->loadLayout(text)); - // !TODO: method to setMapLayout instead of having to do whole setMap thing, - // also edit history and bug fixes setMap(editor->map->name); markMapEdited(); } @@ -1834,7 +1828,6 @@ void MainWindow::currentMetatilesSelectionChanged() { scrollMetatileSelectorToSelection(); } -// !TODO void MainWindow::on_mapListContainer_currentChanged(int index) { switch (index) { case MapListTab::Groups: @@ -1853,7 +1846,6 @@ void MainWindow::on_mapListContainer_currentChanged(int index) { porymapConfig.setMapSortOrder(this->mapSortOrder); } -/// !TODO void MainWindow::on_mapList_activated(const QModelIndex &index) { QVariant data = index.data(Qt::UserRole); if (index.data(MapListRoles::TypeRole) == "map_name" && !data.isNull()) { @@ -2844,6 +2836,10 @@ void MainWindow::onMapChanged(Map *) { updateMapList(); } +void MainWindow::onLayoutChanged(Layout *) { + updateMapList(); +} + void MainWindow::onMapNeedsRedrawing() { redrawMapScene(); } @@ -3172,7 +3168,7 @@ void MainWindow::initTilesetEditor() { connect(this->tilesetEditor, &TilesetEditor::tilesetsSaved, this, &MainWindow::onTilesetsSaved); } -void MainWindow::on_toolButton_ExpandAll_clicked() { +void MainWindow::do_ExpandAll() { switch (ui->mapListContainer->currentIndex()) { case MapListTab::Groups: this->on_toolButton_ExpandAll_Groups_clicked(); @@ -3186,7 +3182,7 @@ void MainWindow::on_toolButton_ExpandAll_clicked() { } } -void MainWindow::on_toolButton_CollapseAll_clicked() { +void MainWindow::do_CollapseAll() { switch (ui->mapListContainer->currentIndex()) { case MapListTab::Groups: this->on_toolButton_CollapseAll_Groups_clicked(); @@ -3200,7 +3196,7 @@ void MainWindow::on_toolButton_CollapseAll_clicked() { } } -void MainWindow::on_toolButton_HideShow_clicked() { +void MainWindow::do_HideShow() { switch (ui->mapListContainer->currentIndex()) { case MapListTab::Groups: this->on_toolButton_HideShow_Groups_clicked(); From 34478e69d9745df151a1b7e123540c750f81df74 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 19 Apr 2024 18:41:52 -0400 Subject: [PATCH 49/70] cleanup: resolve remaining (outdated) TODOs --- src/project.cpp | 1 - src/ui/collisionpixmapitem.cpp | 1 - src/ui/mapimageexporter.cpp | 5 +++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/project.cpp b/src/project.cpp index af5e2f2fb..f74eaffea 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -440,7 +440,6 @@ Layout *Project::createNewLayout(Layout::SimpleSettings &layoutSettings) { } bool Project::loadLayout(Layout *layout) { - // !TODO: make sure this doesn't break anything, maybe do something better. new layouts work too? if (!layout->loaded) { // Force these to run even if one fails bool loadedTilesets = loadLayoutTilesets(layout); diff --git a/src/ui/collisionpixmapitem.cpp b/src/ui/collisionpixmapitem.cpp index f72e496fd..e0587b081 100644 --- a/src/ui/collisionpixmapitem.cpp +++ b/src/ui/collisionpixmapitem.cpp @@ -50,7 +50,6 @@ void CollisionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::draw(bool ignoreCache) { if (this->layout) { - // !TODO this->layout->setCollisionItem(this); setPixmap(this->layout->renderCollision(ignoreCache)); setOpacity(*this->opacity); diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index 44d41f19e..f649ce353 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -93,13 +93,14 @@ void MapImageExporter::saveImage() { break; } case ImageExporterMode::Timelapse: - // !TODO: also need layout editHistory! + // Timelapse will play in order of layout changes then map changes (events) + // TODO: potentially update in the future? QGifImage timelapseImg; timelapseImg.setDefaultDelay(timelapseDelayMs); timelapseImg.setDefaultTransparentColor(QColor(0, 0, 0)); + // lambda to avoid redundancy auto generateTimelapseFromHistory = [=, this, &timelapseImg](QString progressText, QUndoStack &historyStack){ - // QProgressDialog progress(progressText, "Cancel", 0, 1, this); progress.setAutoClose(true); progress.setWindowModality(Qt::WindowModal); From bc454d6b132c38958b8cd888e1a9fb4323545371 Mon Sep 17 00:00:00 2001 From: garak Date: Fri, 19 Apr 2024 18:57:27 -0400 Subject: [PATCH 50/70] fix some map combos not being populated with new items --- src/mainwindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f7884ad63..e311eb21f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1617,6 +1617,8 @@ void MainWindow::onNewMapCreated() { editor->project->saveMap(newMap); editor->project->saveAllDataStructures(); + loadProjectCombos(); // need to maybe repopulate layout combo + // Add new Map / Layout to the mapList models this->mapGroupModel->insertMapItem(newMapName, editor->project->groupNames[newMapGroup]); this->mapAreaModel->insertMapItem(newMapName, newMap->location, newMapGroup); @@ -1760,6 +1762,8 @@ void MainWindow::on_actionNew_Tileset_triggered() { } insertTilesetLabel(&editor->project->tilesetLabelsOrdered, createTilesetDialog->fullSymbolName); + loadProjectCombos(); // need to reload tileset combos + QMessageBox msgBox(this); msgBox.setText("Successfully created tileset."); QString message = QString("Tileset \"%1\" was created successfully.").arg(createTilesetDialog->friendlyName); From 6d39d3afd439f9a47251f5e909098a0e7ec74323 Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 24 Sep 2024 11:59:44 -0400 Subject: [PATCH 51/70] fix project close order and clear new layout combo --- src/mainwindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3df6b0e15..0f123149c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1304,6 +1304,7 @@ void MainWindow::clearProjectUI() { const QSignalBlocker blocker8(ui->comboBox_DiveMap); const QSignalBlocker blocker9(ui->comboBox_EmergeMap); const QSignalBlocker blockerA(ui->lineEdit_filterBox); + const QSignalBlocker blockerB(ui->comboBox_LayoutSelector); ui->comboBox_Song->clear(); ui->comboBox_Location->clear(); @@ -1315,6 +1316,7 @@ void MainWindow::clearProjectUI() { ui->comboBox_DiveMap->clear(); ui->comboBox_EmergeMap->clear(); ui->lineEdit_filterBox->clear(); + ui->comboBox_LayoutSelector->clear(); // Clear map models if (this->mapGroupModel) { @@ -3676,8 +3678,8 @@ bool MainWindow::closeProject() { return false; } } - clearProjectUI(); editor->closeProject(); + clearProjectUI(); setWindowDisabled(true); setWindowTitle(QCoreApplication::applicationName()); From 7bfb064e80bd47380237f8bde17f6e5cba428d85 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 2 Oct 2024 02:50:41 -0400 Subject: [PATCH 52/70] fix main tab icon initialization --- src/editor.cpp | 1 + src/mainwindow.cpp | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/editor.cpp b/src/editor.cpp index 1e4791b38..56c82aafe 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1247,6 +1247,7 @@ void Editor::unsetMap() { for (auto connection : map->getConnections()) disconnectMapConnection(connection); } + clearMapConnections(); this->map = nullptr; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e1122c7f5..6666196f8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -220,23 +220,23 @@ void MainWindow::applyUserShortcuts() { shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut)); } -static const QMap mainTabNames = { - {MainTab::Map, "Map"}, - {MainTab::Events, "Events"}, - {MainTab::Header, "Header"}, - {MainTab::Connections, "Connections"}, - {MainTab::WildPokemon, "Wild Pokemon"}, -}; - -static const QMap mainTabIcons = { - {MainTab::Map, QIcon(QStringLiteral(":/icons/minimap.ico"))}, - {MainTab::Events, QIcon(QStringLiteral(":/icons/viewsprites.ico"))}, - {MainTab::Header, QIcon(QStringLiteral(":/icons/application_form_edit.ico"))}, - {MainTab::Connections, QIcon(QStringLiteral(":/icons/connections.ico"))}, - {MainTab::WildPokemon, QIcon(QStringLiteral(":/icons/tall_grass.ico"))}, -}; - void MainWindow::initCustomUI() { + static const QMap mainTabNames = { + {MainTab::Map, "Map"}, + {MainTab::Events, "Events"}, + {MainTab::Header, "Header"}, + {MainTab::Connections, "Connections"}, + {MainTab::WildPokemon, "Wild Pokemon"}, + }; + + static const QMap mainTabIcons = { + {MainTab::Map, QIcon(QStringLiteral(":/icons/minimap.ico"))}, + {MainTab::Events, QIcon(QStringLiteral(":/icons/viewsprites.ico"))}, + {MainTab::Header, QIcon(QStringLiteral(":/icons/application_form_edit.ico"))}, + {MainTab::Connections, QIcon(QStringLiteral(":/icons/connections.ico"))}, + {MainTab::WildPokemon, QIcon(QStringLiteral(":/icons/tall_grass.ico"))}, + }; + // Set up the tab bar while (ui->mainTabBar->count()) ui->mainTabBar->removeTab(0); From eed641f5ffd7e2a75ff3185a37463b6cbe180ae2 Mon Sep 17 00:00:00 2001 From: garak Date: Thu, 3 Oct 2024 11:06:40 -0400 Subject: [PATCH 53/70] fix connection mask in layout display --- src/editor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/editor.cpp b/src/editor.cpp index 56c82aafe..a032ab7ed 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1568,6 +1568,7 @@ bool Editor::displayLayout() { scene->installEventFilter(this->map_ruler); } + clearConnectionMask(); displayMetatileSelector(); displayMapMetatiles(); displayMovementPermissionSelector(); From 5e9ab4c7c7736effea1ab35722efe7677ed2426b Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 17 Oct 2024 11:46:47 -0400 Subject: [PATCH 54/70] Reopen Porymap to last-opened map/layout --- include/config.h | 6 +-- include/mainwindow.h | 8 --- src/config.cpp | 27 ++++------ src/editor.cpp | 4 +- src/mainwindow.cpp | 121 +++++++++---------------------------------- 5 files changed, 38 insertions(+), 128 deletions(-) diff --git a/include/config.h b/include/config.h index 79e7e56e0..01a7b09c5 100644 --- a/include/config.h +++ b/include/config.h @@ -406,8 +406,7 @@ class UserConfig: public KeyValueConfigBase reset(); } virtual void reset() override { - this->recentMap = QString(); - this->recentLayout = QString(); + this->recentMapOrLayout = QString(); this->useEncounterJson = true; this->customScripts.clear(); this->readKeys.clear(); @@ -419,8 +418,7 @@ class UserConfig: public KeyValueConfigBase QList getCustomScriptsEnabled(); QString projectDir; - QString recentMap; - QString recentLayout; + QString recentMapOrLayout; bool useEncounterJson; protected: diff --git a/include/mainwindow.h b/include/mainwindow.h index 194cc52c6..fc2771938 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -373,8 +373,6 @@ private slots: bool tilesetNeedsRedraw = false; - bool setDefaultView(); - bool setRecentView(); bool setLayout(QString layoutId); bool setMap(QString, bool scroll = false); void unsetMap(); @@ -398,12 +396,6 @@ private slots: QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum); bool setInitialMap(); - bool setInitialLayout(); - QString getDefaultMap(); - QString getDefaultLayout(); - - void setRecentMapConfig(QString map_name); - void setRecentLayoutConfig(QString layoutId); void saveGlobalConfigs(); void refreshRecentProjectsMenu(); diff --git a/src/config.cpp b/src/config.cpp index ef543327d..0d72542d8 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -278,13 +278,7 @@ uint32_t KeyValueConfigBase::getConfigUint32(QString key, QString value, uint32_ return qMin(max, qMax(min, result)); } -const QMap mapSortOrderMap = { - {MapSortOrder::SortByGroup, "group"}, - {MapSortOrder::SortByLayout, "layout"}, - {MapSortOrder::SortByArea, "area"}, -}; - -const QMap mapSortOrderReverseMap = { +const QMap mapSortOrderMap = { {"group", MapSortOrder::SortByGroup}, {"layout", MapSortOrder::SortByLayout}, {"area", MapSortOrder::SortByArea}, @@ -316,8 +310,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->prettyCursors = getConfigBool(key, value); } else if (key == "map_sort_order") { QString sortOrder = value.toLower(); - if (mapSortOrderReverseMap.contains(sortOrder)) { - this->mapSortOrder = mapSortOrderReverseMap.value(sortOrder); + if (mapSortOrderMap.contains(sortOrder)) { + this->mapSortOrder = mapSortOrderMap.value(sortOrder); } else { this->mapSortOrder = MapSortOrder::SortByGroup; logWarn(QString("Invalid config value for map_sort_order: '%1'. Must be 'group', 'area', or 'layout'.").arg(value)); @@ -438,7 +432,7 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("project_manually_closed", this->projectManuallyClosed ? "1" : "0"); map.insert("reopen_on_launch", this->reopenOnLaunch ? "1" : "0"); map.insert("pretty_cursors", this->prettyCursors ? "1" : "0"); - map.insert("map_sort_order", mapSortOrderMap.value(this->mapSortOrder)); + map.insert("map_sort_order", mapSortOrderMap.key(this->mapSortOrder)); map.insert("main_window_geometry", stringFromByteArray(this->mainWindowGeometry)); map.insert("main_window_state", stringFromByteArray(this->mainWindowState)); map.insert("map_splitter_state", stringFromByteArray(this->mapSplitterState)); @@ -740,8 +734,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { } else if (key == "enable_map_allow_flags") { this->mapAllowFlagsEnabled = getConfigBool(key, value); #ifdef CONFIG_BACKWARDS_COMPATABILITY - } else if (key == "recent_map") { - userConfig.recentMap = value; + } else if (key == "recent_map_or_layout") { + userConfig.recentMapOrLayout = value; } else if (key == "use_encounter_json") { userConfig.useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { @@ -1035,10 +1029,8 @@ QString UserConfig::getConfigFilepath() { } void UserConfig::parseConfigKeyValue(QString key, QString value) { - if (key == "recent_map") { - this->recentMap = value; - } else if (key == "recent_layout") { - this->recentLayout = value; + if (key == "recent_map_or_layout") { + this->recentMapOrLayout = value; } else if (key == "use_encounter_json") { this->useEncounterJson = getConfigBool(key, value); } else if (key == "custom_scripts") { @@ -1054,8 +1046,7 @@ void UserConfig::setUnreadKeys() { QMap UserConfig::getKeyValueMap() { QMap map; - map.insert("recent_map", this->recentMap); - map.insert("recent_layout", this->recentLayout); + map.insert("recent_map_or_layout", this->recentMapOrLayout); map.insert("use_encounter_json", QString::number(this->useEncounterJson)); map.insert("custom_scripts", this->outputCustomScripts()); return map; diff --git a/src/editor.cpp b/src/editor.cpp index f674e864e..681694321 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1319,7 +1319,7 @@ bool Editor::setLayout(QString layoutId) { return true; } -void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) { +void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *) { if (!this->getEditingLayout()) { return; } @@ -1332,7 +1332,7 @@ void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem * } } -void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *item) { +void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *) { if (!this->getEditingLayout()) { return; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 21d2b348c..4d3a72e7f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -696,83 +696,29 @@ bool MainWindow::isProjectOpen() { return editor && editor->project; } -bool MainWindow::setDefaultView() { - if (porymapConfig.mapSortOrder == MapSortOrder::SortByLayout) { - return setLayout(getDefaultLayout()); - } else { - return setMap(getDefaultMap(), true); - } -} - -bool MainWindow::setRecentView() { - if (porymapConfig.mapSortOrder == MapSortOrder::SortByLayout) { - return setLayout(userConfig.recentLayout); - } else { - return setMap(userConfig.recentMap, true); - } -} - -QString MainWindow::getDefaultMap() { - if (editor && editor->project) { - QList names = editor->project->groupedMapNames; - if (!names.isEmpty()) { - QString recentMap = userConfig.recentMap; - if (!recentMap.isNull() && recentMap.length() > 0) { - for (int i = 0; i < names.length(); i++) { - if (names.value(i).contains(recentMap)) { - return recentMap; - } - } - } - // Failing that, just get the first map in the list. - for (int i = 0; i < names.length(); i++) { - QStringList list = names.value(i); - if (list.length()) { - return list.value(0); - } - } - } - } - return QString(); -} - bool MainWindow::setInitialMap() { - QStringList names; - if (editor && editor->project) - names = editor->project->mapNames; - - // Try to set most recently-opened map, if it's still in the list. - QString recentMap = userConfig.recentMap; - if (!recentMap.isEmpty() && names.contains(recentMap) && setMap(recentMap, true)) - return true; - - // Failing that, try loading maps in the map list sequentially. - for (auto name : names) { - if (name != recentMap && setMap(name, true)) + const QString recent = userConfig.recentMapOrLayout; + if (editor->project->mapNames.contains(recent)) { + // User recently had a map open that still exists. + if (setMap(recent, true)) + return true; + } else if (editor->project->mapLayoutsTable.contains(recent)) { + // User recently had a layout open that still exists. + if (setLayout(recent)) return true; } - logError("Failed to load any maps."); - return false; -} - -bool MainWindow::setInitialLayout() { - QStringList names; - if (editor && editor->project) - names = editor->project->mapLayoutsTable; - - // Try to set most recently-opened layout, if it's still in the list. - QString recentLayout = userConfig.recentLayout; - if (!recentLayout.isEmpty() && names.contains(recentLayout) && setLayout(recentLayout)) - return true; - - // Failing that, try loading maps in the map list sequentially. - for (auto name : names) { - if (name != recentLayout && setLayout(name)) + // Failed to open recent map/layout, or no recent map/layout. Try opening maps then layouts sequentially. + for (const auto &name : editor->project->mapNames) { + if (name != recent && setMap(name, true)) + return true; + } + for (const auto &id : editor->project->mapLayoutsTable) { + if (id != recent && setLayout(id)) return true; } - logError("Failed to load any layouts."); + logError("Failed to load any maps or layouts."); return false; } @@ -824,25 +770,13 @@ void MainWindow::openSubWindow(QWidget * window) { } } -QString MainWindow::getDefaultLayout() { - if (editor && editor->project) { - QString recentLayout = userConfig.recentLayout; - if (!recentLayout.isEmpty() && editor->project->mapLayoutsTable.contains(recentLayout)) { - return recentLayout; - } else if (!editor->project->mapLayoutsTable.isEmpty()) { - return editor->project->mapLayoutsTable.first(); - } - } - return QString(); -} - QString MainWindow::getExistingDirectory(QString dir) { return FileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly); } void MainWindow::on_action_Open_Project_triggered() { - QString dir = getExistingDirectory(!userConfig.recentMap.isEmpty() ? userConfig.recentMap : "."); + QString dir = getExistingDirectory(!projectConfig.projectDir.isEmpty() ? userConfig.projectDir : "."); if (!dir.isEmpty()) openProject(dir); } @@ -904,11 +838,16 @@ bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) { bool MainWindow::setMap(QString map_name, bool scroll) { // if map name is empty, clear & disable map ui - if (map_name.isEmpty() || map_name == DYNAMIC_MAP_NAME) { + if (map_name.isEmpty()) { unsetMap(); return false; } + if (map_name == DYNAMIC_MAP_NAME) { + logInfo(QString("Cannot set map to '%1'").arg(DYNAMIC_MAP_NAME)); + return false; + } + logInfo(QString("Setting map to '%1'").arg(map_name)); if (!editor || !editor->setMap(map_name)) { @@ -944,7 +883,7 @@ bool MainWindow::setMap(QString map_name, bool scroll) { connect(editor->layout, &Layout::layoutChanged, this, &MainWindow::onLayoutChanged, Qt::UniqueConnection); connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing, Qt::UniqueConnection); - userConfig.recentMap = map_name; + userConfig.recentMapOrLayout = map_name; Scripting::cb_MapOpened(map_name); prefab.updatePrefabUi(editor->layout); @@ -974,7 +913,7 @@ bool MainWindow::setLayout(QString layoutId) { updateTilesetEditor(); - setRecentLayoutConfig(layoutId); + userConfig.recentMapOrLayout = layoutId; return true; } @@ -1050,16 +989,6 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_ } } -void MainWindow::setRecentMapConfig(QString mapName) { - userConfig.recentMap = mapName; - userConfig.recentLayout = ""; -} - -void MainWindow::setRecentLayoutConfig(QString layoutId) { - userConfig.recentLayout = layoutId; - userConfig.recentMap = ""; -} - void MainWindow::displayMapProperties() { // Block signals to the comboboxes while they are being modified const QSignalBlocker blocker1(ui->comboBox_Song); From 728355d202b2c9495f83af86410b10c7e81f1476 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 17 Oct 2024 12:12:33 -0400 Subject: [PATCH 55/70] Fix some missing constant usage --- include/mainwindow.h | 1 + src/mainwindow.cpp | 37 +++++++++++++++++++------------------ src/project.cpp | 9 ++++++--- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index fc2771938..677bd89fe 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -380,6 +380,7 @@ private slots: void redrawMapScene(); void redrawLayoutScene(); void refreshMapScene(); + void setLayoutOnlyMode(bool layoutOnly); bool checkProjectSanity(); bool loadProjectData(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4d3a72e7f..dea3d2104 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -425,12 +425,14 @@ void MainWindow::showWindowTitle() { ); } if (editor && editor->layout) { - ui->mainTabBar->setTabIcon(0, QIcon()); + // For some reason (perhaps on Qt < 6?) we had to clear the icon first here or mainTabBar wouldn't display correctly. + ui->mainTabBar->setTabIcon(MainTab::Map, QIcon()); + QPixmap pixmap = editor->layout->pixmap; if (!pixmap.isNull()) { - ui->mainTabBar->setTabIcon(0, QIcon(pixmap)); + ui->mainTabBar->setTabIcon(MainTab::Map, QIcon(pixmap)); } else { - ui->mainTabBar->setTabIcon(0, QIcon(QStringLiteral(":/icons/map.ico"))); + ui->mainTabBar->setTabIcon(MainTab::Map, QIcon(QStringLiteral(":/icons/map.ico"))); } } updateMapList(); @@ -801,14 +803,7 @@ void MainWindow::on_action_Close_Project_triggered() { void MainWindow::unsetMap() { this->editor->unsetMap(); - - // disable other tabs - this->ui->mainTabBar->setTabEnabled(1, false); - this->ui->mainTabBar->setTabEnabled(2, false); - this->ui->mainTabBar->setTabEnabled(3, false); - this->ui->mainTabBar->setTabEnabled(4, false); - - this->ui->comboBox_LayoutSelector->setEnabled(false); + setLayoutOnlyMode(true); } // setMap, but with a visible error message in case of failure. @@ -859,13 +854,7 @@ bool MainWindow::setMap(QString map_name, bool scroll) { ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(map_name)), false); } - this->ui->mainTabBar->setTabEnabled(1, true); - this->ui->mainTabBar->setTabEnabled(2, true); - this->ui->mainTabBar->setTabEnabled(3, true); - this->ui->mainTabBar->setTabEnabled(4, true); - - this->ui->comboBox_LayoutSelector->setEnabled(true); - + setLayoutOnlyMode(false); this->lastSelectedEvent.clear(); refreshMapScene(); @@ -891,6 +880,18 @@ bool MainWindow::setMap(QString map_name, bool scroll) { return true; } +// These parts of the UI only make sense when editing maps. +// When editing in layout-only mode they are disabled. +void MainWindow::setLayoutOnlyMode(bool layoutOnly) { + bool mapEditingEnabled = !layoutOnly; + this->ui->mainTabBar->setTabEnabled(MainTab::Events, mapEditingEnabled); + this->ui->mainTabBar->setTabEnabled(MainTab::Header, mapEditingEnabled); + this->ui->mainTabBar->setTabEnabled(MainTab::Connections, mapEditingEnabled); + this->ui->mainTabBar->setTabEnabled(MainTab::WildPokemon, mapEditingEnabled); + + this->ui->comboBox_LayoutSelector->setEnabled(mapEditingEnabled); +} + bool MainWindow::setLayout(QString layoutId) { if (this->editor->map) logInfo("Switching to a layout-only editing mode. Disabling map-related edits."); diff --git a/src/project.cpp b/src/project.cpp index 194f2ecdb..32c61fedc 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -2327,11 +2327,14 @@ bool Project::readRegionMapSections() { int Project::appendMapsec(QString name) { // This function assumes a valid and unique name. // Will return the new index. - int noneBefore = this->mapSectionNameToValue[projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + "NONE"]; + const QString emptyMapsecName = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty); + + int noneBefore = this->mapSectionNameToValue[emptyMapsecName]; this->mapSectionNameToValue[name] = noneBefore; this->mapSectionValueToName[noneBefore] = name; - this->mapSectionNameToValue[projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + "NONE"] = noneBefore + 1; - this->mapSectionValueToName[noneBefore + 1] = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + "NONE"; + this->mapSectionNameToValue[emptyMapsecName] = noneBefore + 1; + this->mapSectionValueToName[noneBefore + 1] = emptyMapsecName; return noneBefore; } From 10aa6f6c3f6872a904e65368979ca356bad0d411 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 17 Oct 2024 14:01:27 -0400 Subject: [PATCH 56/70] Fix new name regexes, some assumptions about MAPSEC_NONE, memory leak --- include/project.h | 2 +- src/mainwindow.cpp | 58 +++++++++++++++++++++--------------- src/project.cpp | 46 +++++++++++++++++----------- src/scriptapi/apiutility.cpp | 3 -- src/ui/maplistmodels.cpp | 13 +++++--- 5 files changed, 73 insertions(+), 49 deletions(-) diff --git a/include/project.h b/include/project.h index d93f56018..6782769be 100644 --- a/include/project.h +++ b/include/project.h @@ -132,7 +132,6 @@ class Project : public QObject QString getProjectTitle(); QString readMapLayoutId(QString map_name); - QString readMapLayoutName(QString mapName); QString readMapLocation(QString map_name); bool readWildMonData(); @@ -243,6 +242,7 @@ class Project : public QObject static bool mapDimensionsValid(int width, int height); bool calculateDefaultMapSize(); static int getMaxObjectEvents(); + static QString getEmptyMapsecName(); private: void updateLayout(Layout *); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index dea3d2104..2946dbeb9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1370,9 +1370,13 @@ void MainWindow::mapListAddGroup() { QLineEdit *newNameEdit = new QLineEdit(&dialog); newNameEdit->setClearButtonEnabled(true); - static const QRegularExpression re_validChars("[_A-Za-z0-9]*$"); - QRegularExpressionValidator *validator = new QRegularExpressionValidator(re_validChars); - newNameEdit->setValidator(validator); + static const QRegularExpression re_validChars("[A-Za-z_]+[\\w]*"); + newNameEdit->setValidator(new QRegularExpressionValidator(re_validChars, newNameEdit)); + + connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ + if (!this->editor->project->groupNames.contains(newNameEdit->text())) + dialog.accept(); + }); QFormLayout form(&dialog); @@ -1397,10 +1401,10 @@ void MainWindow::mapListAddLayout() { QLineEdit *newNameEdit = new QLineEdit(&dialog); newNameEdit->setClearButtonEnabled(true); - static const QRegularExpression re_validChars("[_A-Za-z0-9]*$"); - QRegularExpressionValidator *validator = new QRegularExpressionValidator(re_validChars); - newNameEdit->setValidator(validator); + static const QRegularExpression re_validChars("[A-Za-z_]+[\\w]*"); + newNameEdit->setValidator(new QRegularExpressionValidator(re_validChars, newNameEdit)); + // TODO: Support arbitrary LAYOUT_ ID names (Note from GriffinR: This is already handled in an unopened PR) QLabel *newId = new QLabel("LAYOUT_", &dialog); connect(newNameEdit, &QLineEdit::textChanged, [&](QString text){ newId->setText(Layout::layoutConstantFromName(text.remove("_Layout"))); @@ -1499,7 +1503,7 @@ void MainWindow::mapListAddLayout() { layoutSettings.tileset_secondary_label = secondaryCombo->currentText(); } Layout *newLayout = this->editor->project->createNewLayout(layoutSettings); - QStandardItem *item = this->layoutTreeModel->insertLayoutItem(newLayout->id); + this->layoutTreeModel->insertLayoutItem(newLayout->id); setLayout(newLayout->id); } } @@ -1511,13 +1515,18 @@ void MainWindow::mapListAddArea() { QDialogButtonBox newItemButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); connect(&newItemButtonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix); QLineEdit *newNameEdit = new QLineEdit(&dialog); - newNameEdit->setText(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix)); - newNameEdit->setClearButtonEnabled(false); + QLineEdit *newNameDisplay = new QLineEdit(&dialog); + newNameDisplay->setText(prefix); + newNameDisplay->setEnabled(false); + connect(newNameEdit, &QLineEdit::textEdited, [newNameDisplay, prefix] (const QString &text) { + // As the user types a name, update the label to show the name with the prefix. + newNameDisplay->setText(prefix + text); + }); - QRegularExpression re_validChars(QString("%1[_A-Za-z0-9]+$").arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))); - QRegularExpressionValidator *validator = new QRegularExpressionValidator(re_validChars); - newNameEdit->setValidator(validator); + static const QRegularExpression re_validChars("[A-Za-z_]+[\\w]*"); + newNameEdit->setValidator(new QRegularExpressionValidator(re_validChars, newNameEdit)); connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ if (!this->editor->project->mapSectionNameToValue.contains(newNameEdit->text())) @@ -1527,12 +1536,12 @@ void MainWindow::mapListAddArea() { QFormLayout form(&dialog); form.addRow("New Map Section Name", newNameEdit); + form.addRow("Constant Name", newNameDisplay); form.addRow(&newItemButtonBox); if (dialog.exec() == QDialog::Accepted) { - QString newFieldName = newNameEdit->text(); - if (newFieldName.isEmpty()) return; - this->mapAreaModel->insertAreaItem(newFieldName); + if (newNameEdit->text().isEmpty()) return; + this->mapAreaModel->insertAreaItem(newNameDisplay->text()); } } @@ -1540,13 +1549,13 @@ void MainWindow::mapListAddItem() { if (!this->editor || !this->editor->project) return; switch (this->ui->mapListContainer->currentIndex()) { - case 0: + case MapListTab::Groups: this->mapListAddGroup(); break; - case 1: + case MapListTab::Areas: this->mapListAddArea(); break; - case 2: + case MapListTab::Layouts: this->mapListAddLayout(); break; } @@ -1596,14 +1605,14 @@ void MainWindow::mapListRemoveItem() { if (!this->editor || !this->editor->project) return; switch (this->ui->mapListContainer->currentIndex()) { - case 0: + case MapListTab::Groups: this->mapListRemoveGroup(); break; - case 1: + case MapListTab::Areas: // Disabled // this->mapListRemoveArea(); break; - case 2: + case MapListTab::Layouts: // Disabled // this->mapListRemoveLayout(); break; @@ -2913,10 +2922,8 @@ void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryT } else { this->editor->project->getTileset(secondaryTilesetLabel, true); } - if (updated) { - this->editor->layout->clearBorderCache(); + if (updated) redrawMapScene(); - } } void MainWindow::onMapRulerStatusChanged(const QString &status) { @@ -3232,6 +3239,7 @@ void MainWindow::do_CollapseAll() { } } +// TODO: Save this state in porymapConfig void MainWindow::do_HideShow() { switch (ui->mapListContainer->currentIndex()) { case MapListTab::Groups: @@ -3265,6 +3273,7 @@ void MainWindow::on_toolButton_CollapseAll_Groups_clicked() { } } +// TODO: Save this state in porymapConfig void MainWindow::on_toolButton_EnableDisable_EditGroups_clicked() { this->ui->mapList->clearSelection(); if (this->ui->toolButton_EnableDisable_EditGroups->isChecked()) { @@ -3607,6 +3616,7 @@ bool MainWindow::closeProject() { return true; // Check loaded maps for unsaved changes + // TODO: This needs to check for unsaved changes in layouts too. bool unsavedChanges = false; for (auto map : editor->project->mapCache.values()) { if (map && map->hasUnsavedChanges()) { diff --git a/src/project.cpp b/src/project.cpp index 32c61fedc..e6cd7a8e3 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -412,10 +412,6 @@ QString Project::readMapLayoutId(QString map_name) { return ParseUtil::jsonToQString(mapObj["layout"]); } -QString Project::readMapLayoutName(QString mapName) { - return this->layoutIdsToNames[readMapLayoutId(mapName)]; -} - QString Project::readMapLocation(QString map_name) { if (mapCache.contains(map_name)) { return mapCache.value(map_name)->location; @@ -537,6 +533,8 @@ bool Project::loadMapLayout(Map* map) { void Project::clearMapLayouts() { qDeleteAll(mapLayouts); mapLayouts.clear(); + qDeleteAll(mapLayoutsMaster); + mapLayoutsMaster.clear(); mapLayoutsTable.clear(); layoutIdsToNames.clear(); } @@ -763,7 +761,7 @@ void Project::saveMapSections() { longestLength += 1; - // mapSectionValueToName + // TODO: Maybe print as an enum now that we can? for (int value : this->mapSectionValueToName.keys()) { QString line = QString("#define %1 0x%2\n") .arg(this->mapSectionValueToName[value], -1 * longestLength) @@ -771,6 +769,8 @@ void Project::saveMapSections() { text += line; } + // TODO: We should maybe consider another way to update MAPSEC values in this file, in case we break anything by relocating it to the bottom of the file. + // (or alternatively keep separate strings for text before/after the MAPSEC values) text += "\n" + this->extraFileText[projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections)] + "\n"; text += QString("#endif // GUARD_REGIONMAPSEC_H\n"); @@ -2307,10 +2307,12 @@ bool Project::readRegionMapSections() { continue; } // include guards + // TODO: Assuming guard name is the same across projects (it isn't) else if (currentLine.contains("GUARD_REGIONMAPSEC_H")) { continue; } - // defines captured (not considering comments) + // defines captured + // TODO: Regex to consider comments/extra space else if (currentLine.contains("#define " + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))) { continue; } @@ -2324,18 +2326,28 @@ bool Project::readRegionMapSections() { return true; } +QString Project::getEmptyMapsecName() { + return projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty); +} + +// This function assumes a valid and unique name. +// Will return the new index. +// TODO: We're not currently tracking map/layout agonstic changes like this as unsaved, so there's no warning if you close the project after doing this. int Project::appendMapsec(QString name) { - // This function assumes a valid and unique name. - // Will return the new index. - const QString emptyMapsecName = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) - + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty); - - int noneBefore = this->mapSectionNameToValue[emptyMapsecName]; - this->mapSectionNameToValue[name] = noneBefore; - this->mapSectionValueToName[noneBefore] = name; - this->mapSectionNameToValue[emptyMapsecName] = noneBefore + 1; - this->mapSectionValueToName[noneBefore + 1] = emptyMapsecName; - return noneBefore; + const QString emptyMapsecName = getEmptyMapsecName(); + int newMapsecValue = mapSectionValueToName.isEmpty() ? 0 : mapSectionValueToName.lastKey(); + + // If the user has the 'empty' MAPSEC value defined last in the list we'll shift it so that it stays last in the list. + if (this->mapSectionNameToValue.contains(emptyMapsecName) && this->mapSectionNameToValue.value(emptyMapsecName) == newMapsecValue) { + this->mapSectionNameToValue.insert(emptyMapsecName, newMapsecValue + 1); + this->mapSectionValueToName.insert(newMapsecValue + 1, emptyMapsecName); + } + + // TODO: Update 'define_map_section_count'? + + this->mapSectionNameToValue[name] = newMapsecValue; + this->mapSectionValueToName[newMapsecValue] = name; + return newMapsecValue; } // Read the constants to preserve any "unused" heal locations when writing the file later diff --git a/src/scriptapi/apiutility.cpp b/src/scriptapi/apiutility.cpp index c12db39a2..27bd56770 100644 --- a/src/scriptapi/apiutility.cpp +++ b/src/scriptapi/apiutility.cpp @@ -154,9 +154,6 @@ void ScriptUtility::setMainTab(int index) { // Can't select tab if it's disabled if (!window->ui->mainTabBar->isTabEnabled(index)) return; - // don't change tab when not editing a map - if (!window->editor || !window->editor->map) - return; window->on_mainTabBar_tabBarClicked(index); } diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index f5835357c..7e0d7e62e 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -19,10 +19,9 @@ void MapTree::removeSelected() { QWidget *GroupNameDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { QLineEdit *editor = new QLineEdit(parent); - static const QRegularExpression expression("[A-Za-z0-9_]+"); + static const QRegularExpression expression("[A-Za-z_]+[\\w]*"); editor->setPlaceholderText("gMapGroup_"); - QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression, parent); - editor->setValidator(validator); + editor->setValidator(new QRegularExpressionValidator(expression, parent)); editor->setFrame(false); return editor; } @@ -401,7 +400,12 @@ QStandardItem *MapAreaModel::insertAreaItem(QString areaName) { int newAreaIndex = this->project->appendMapsec(areaName); QStandardItem *item = createAreaItem(areaName, newAreaIndex); this->root->insertRow(newAreaIndex, item); - this->areaItems["MAPSEC_NONE"]->setData(newAreaIndex + 1, MapListUserRoles::GroupRole); + + // MAPSEC_NONE may have shifted to accomodate the new item, update it in the list. + const QString emptyMapsecName = Project::getEmptyMapsecName(); + if (this->areaItems.contains(emptyMapsecName)) + this->areaItems[emptyMapsecName]->setData(this->project->mapSectionNameToValue.value(emptyMapsecName), MapListUserRoles::GroupRole); + return item; } @@ -427,6 +431,7 @@ void MapAreaModel::initialize() { this->mapItems.clear(); this->setSortRole(MapListUserRoles::GroupRole); + // TODO: Ignore 'define_map_section_count' and/or 'define_map_section_empty'? for (int i : this->project->mapSectionNameToValue) { QString mapsecName = project->mapSectionValueToName.value(i); QStandardItem *areaItem = createAreaItem(mapsecName, i); From 7da23759988be15c8abec5aa6d34a758ca1adb83 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 18 Oct 2024 14:22:34 -0400 Subject: [PATCH 57/70] Refactor map list buttons --- forms/mainwindow.ui | 663 ++++++-------------------- forms/maplisttoolbar.ui | 172 +++++++ include/mainwindow.h | 58 +-- include/ui/filterchildrenproxymodel.h | 2 +- include/ui/maplistmodels.h | 22 +- include/ui/maplisttoolbar.h | 49 ++ porymap.pro | 3 + resources/icons/collapse_all.ico | Bin 318 -> 1871 bytes resources/icons/expand_all.ico | Bin 318 -> 2142 bytes resources/icons/folder_add.ico | Bin 0 -> 1572 bytes resources/icons/folder_closed_map.ico | Bin 1150 -> 5558 bytes resources/images.qrc | 1 + src/core/map.cpp | 2 +- src/mainwindow.cpp | 566 +++++++++------------- src/ui/maplistmodels.cpp | 12 +- src/ui/maplisttoolbar.cpp | 121 +++++ 16 files changed, 772 insertions(+), 899 deletions(-) create mode 100644 forms/maplisttoolbar.ui create mode 100644 include/ui/maplisttoolbar.h create mode 100755 resources/icons/folder_add.ico create mode 100644 src/ui/maplisttoolbar.cpp diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index bc03f823b..44d69d307 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 1287 - 936 + 1298 + 963 @@ -30,7 +30,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -45,7 +45,7 @@ 0 - + Groups @@ -66,140 +66,7 @@ 0 - - - 0 - - - 3 - - - 3 - - - 3 - - - - - <html><head/><body><p>Toggle hide all empty map folders</p></body></html> - - - - - - - :/icons/folder_eye_open.ico - :/icons/folder_eye_closed.ico:/icons/folder_eye_open.ico - - - true - - - QToolButton::InstantPopup - - - true - - - - - - - <html><head/><body><p>Expand all map folders</p></body></html> - - - - - - - :/icons/expand_all.ico:/icons/expand_all.ico - - - QToolButton::InstantPopup - - - true - - - - - - - <html><head/><body><p>Collapse all map list folders</p></body></html> - - - - - - - :/icons/collapse_all.ico:/icons/collapse_all.ico - - - QToolButton::InstantPopup - - - true - - - - - - - <html><head/><body><p>Toggle editability of group folders</p></body></html> - - - - - - - :/icons/lock_edit.ico - :/icons/unlock_edit.ico:/icons/lock_edit.ico - - - true - - - QToolButton::InstantPopup - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 12 - 20 - - - - - - - - true - - - - - - Filter... - - - true - - - - + @@ -216,10 +83,10 @@ - QAbstractItemView::SingleSelection + QAbstractItemView::SelectionMode::SingleSelection - QAbstractItemView::SelectItems + QAbstractItemView::SelectionBehavior::SelectItems false @@ -228,7 +95,7 @@
- + Areas @@ -249,116 +116,7 @@ 0 - - - 0 - - - 3 - - - 3 - - - 3 - - - - - <html><head/><body><p>Toggle hide all empty mapsection folders</p></body></html> - - - - - - - :/icons/folder_eye_open.ico - :/icons/folder_eye_closed.ico:/icons/folder_eye_open.ico - - - true - - - QToolButton::InstantPopup - - - true - - - - - - - <html><head/><body><p>Expand all map folders</p></body></html> - - - - - - - :/icons/expand_all.ico:/icons/expand_all.ico - - - QToolButton::InstantPopup - - - true - - - - - - - <html><head/><body><p>Collapse all map list folders</p></body></html> - - - - - - - :/icons/collapse_all.ico:/icons/collapse_all.ico - - - QToolButton::InstantPopup - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 12 - 20 - - - - - - - - true - - - - - - Filter... - - - true - - - - + @@ -375,10 +133,10 @@ - QAbstractItemView::SingleSelection + QAbstractItemView::SelectionMode::SingleSelection - QAbstractItemView::SelectItems + QAbstractItemView::SelectionBehavior::SelectItems false @@ -387,7 +145,7 @@ - + Layouts @@ -408,116 +166,7 @@ 0 - - - 0 - - - 3 - - - 3 - - - 3 - - - - - <html><head/><body><p>Toggle hide all unused layouts</p></body></html> - - - - - - - :/icons/folder_eye_open.ico - :/icons/folder_eye_closed.ico:/icons/folder_eye_open.ico - - - true - - - QToolButton::InstantPopup - - - true - - - - - - - <html><head/><body><p>Expand all layout folders</p></body></html> - - - - - - - :/icons/expand_all.ico:/icons/expand_all.ico - - - QToolButton::InstantPopup - - - true - - - - - - - <html><head/><body><p>Collapse all layout folders</p></body></html> - - - - - - - :/icons/collapse_all.ico:/icons/collapse_all.ico - - - QToolButton::InstantPopup - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 12 - 20 - - - - - - - - true - - - - - - Filter... - - - true - - - - + @@ -534,10 +183,10 @@ - QAbstractItemView::SingleSelection + QAbstractItemView::SelectionMode::SingleSelection - QAbstractItemView::SelectItems + QAbstractItemView::SelectionBehavior::SelectItems false @@ -581,7 +230,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -633,7 +282,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -643,10 +292,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised 1 @@ -670,10 +319,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -722,10 +371,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -746,10 +395,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised @@ -930,7 +579,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -953,10 +602,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -1004,7 +653,7 @@ - QLayout::SetNoConstraint + QLayout::SizeConstraint::SetNoConstraint 3 @@ -1033,17 +682,17 @@ 30 - Qt::Horizontal + Qt::Orientation::Horizontal - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain @@ -1067,7 +716,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1104,10 +753,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain true @@ -1117,8 +766,8 @@ 0 0 - 420 - 77 + 424 + 79 @@ -1140,7 +789,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1162,17 +811,17 @@ <html><head/><body><p>The border is a 2x2 metatile which is repeated outside of the map layout's boundary. Draw on this border area to modify it.</p></body></html> - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1223,10 +872,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain true @@ -1236,8 +885,8 @@ 0 0 - 420 - 78 + 424 + 79 @@ -1259,7 +908,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1284,17 +933,17 @@ - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1318,19 +967,19 @@ - Qt::ScrollBarAlwaysOn + Qt::ScrollBarPolicy::ScrollBarAlwaysOn - Qt::ScrollBarAsNeeded + Qt::ScrollBarPolicy::ScrollBarAsNeeded - QAbstractScrollArea::AdjustIgnored + QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored true - Qt::AlignHCenter|Qt::AlignTop + Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop @@ -1338,10 +987,10 @@ - 0 + 8 0 - 409 - 440 + 412 + 446 @@ -1369,7 +1018,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1391,20 +1040,20 @@ - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - QAbstractScrollArea::AdjustIgnored + QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1417,7 +1066,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1444,10 +1093,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -1460,7 +1109,7 @@ - Qt::StrongFocus + Qt::FocusPolicy::StrongFocus <html><head/><body><p>Primary Tileset</p><p>Defines the first 0x200 metatiles available for the map.</p></body></html> @@ -1480,7 +1129,7 @@ - Qt::StrongFocus + Qt::FocusPolicy::StrongFocus <html><head/><body><p>Secondary Tileset</p><p>Defines the second 0x200 metatiles available for the map.</p></body></html> @@ -1493,10 +1142,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised @@ -1538,7 +1187,7 @@ - QLayout::SetDefaultConstraint + QLayout::SizeConstraint::SetDefaultConstraint 3 @@ -1569,8 +1218,8 @@ 0 0 - 424 - 627 + 428 + 633 @@ -1592,7 +1241,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1617,17 +1266,17 @@ - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1640,7 +1289,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -1666,7 +1315,7 @@ 30 - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1682,17 +1331,17 @@ 50 - Qt::Horizontal + Qt::Orientation::Horizontal - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -1718,7 +1367,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1779,7 +1428,7 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true @@ -1789,8 +1438,8 @@ 0 0 - 379 - 732 + 383 + 744 @@ -1812,10 +1461,10 @@ <html><head/><body><p>No prefabs have been created for the currently-used tilesets. Create some by using the button above!</p><p>Prefabs are &quot;prefabricated&quot; metatile selections that are used for easy selecting of complicated map structures. For example, a useful prefab could be a building or tree formation, which would otherwise be annoying to paint with the regular metatile picker.</p></body></html> - Qt::RichText + Qt::TextFormat::RichText - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop true @@ -1888,10 +1537,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised 0 @@ -1928,7 +1577,7 @@ :/icons/add.ico:/icons/add.ico - Qt::ToolButtonTextBesideIcon + Qt::ToolButtonStyle::ToolButtonTextBesideIcon @@ -1951,7 +1600,7 @@ :/icons/delete.ico:/icons/delete.ico - Qt::ToolButtonTextBesideIcon + Qt::ToolButtonStyle::ToolButtonTextBesideIcon false @@ -1961,7 +1610,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -1996,7 +1645,7 @@ There are no events on the current map. - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter
@@ -2062,7 +1711,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2077,13 +1726,13 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop @@ -2091,7 +1740,7 @@ 0 0 100 - 30 + 16 @@ -2156,7 +1805,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2171,13 +1820,13 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop @@ -2185,7 +1834,7 @@ 0 0 100 - 30 + 16 @@ -2250,7 +1899,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2265,13 +1914,13 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop @@ -2279,7 +1928,7 @@ 0 0 100 - 30 + 16 @@ -2350,7 +1999,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2365,13 +2014,13 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop @@ -2379,7 +2028,7 @@ 0 0 100 - 30 + 16 @@ -2444,7 +2093,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2459,13 +2108,13 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop @@ -2473,7 +2122,7 @@ 0 0 100 - 30 + 16 @@ -2513,13 +2162,13 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop @@ -2582,14 +2231,14 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised - QFormLayout::FieldsStayAtSizeHint + QFormLayout::FieldGrowthPolicy::FieldsStayAtSizeHint 12 @@ -2793,10 +2442,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -2809,10 +2458,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain @@ -2844,7 +2493,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -2925,10 +2574,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -2940,10 +2589,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -3008,7 +2657,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -3093,7 +2742,7 @@ 30 - Qt::Horizontal + Qt::Orientation::Horizontal @@ -3109,7 +2758,7 @@ 30 - Qt::Horizontal + Qt::Orientation::Horizontal @@ -3141,7 +2790,7 @@ 30 - Qt::Horizontal + Qt::Orientation::Horizontal @@ -3172,7 +2821,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -3188,22 +2837,22 @@ false - Qt::ScrollBarAsNeeded + Qt::ScrollBarPolicy::ScrollBarAsNeeded - Qt::ScrollBarAsNeeded + Qt::ScrollBarPolicy::ScrollBarAsNeeded - QAbstractScrollArea::AdjustIgnored + QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored - QGraphicsView::NoDrag + QGraphicsView::DragMode::NoDrag - QGraphicsView::AnchorUnderMouse + QGraphicsView::ViewportAnchor::AnchorUnderMouse - QGraphicsView::AnchorUnderMouse + QGraphicsView::ViewportAnchor::AnchorUnderMouse @@ -3214,10 +2863,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -3234,10 +2883,10 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff true @@ -3247,8 +2896,8 @@ 0 0 - 365 - 651 + 204 + 16 @@ -3270,7 +2919,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -3298,19 +2947,19 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain @@ -3323,7 +2972,7 @@ - QComboBox::AdjustToContents + QComboBox::SizeAdjustPolicy::AdjustToContents @@ -3364,7 +3013,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -3416,8 +3065,8 @@ 0 0 - 1287 - 22 + 1298 + 37 @@ -3788,7 +3437,7 @@ Check for Updates... - QAction::ApplicationSpecificRole + QAction::MenuRole::ApplicationSpecificRole @@ -3868,6 +3517,12 @@ QGraphicsView
mapview.h
+ + MapListToolBar + QFrame +
maplisttoolbar.h
+ 1 +
diff --git a/forms/maplisttoolbar.ui b/forms/maplisttoolbar.ui new file mode 100644 index 000000000..6f753ea8b --- /dev/null +++ b/forms/maplisttoolbar.ui @@ -0,0 +1,172 @@ + + + MapListToolBar + + + + 0 + 0 + 274 + 32 + + + + Form + + + + 0 + + + 3 + + + 3 + + + 0 + + + 3 + + + + + Add a folder to the list. + + + + :/icons/folder_add.ico:/icons/folder_add.ico + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true + + + + + + + Hide empty folders in the list. + + + + :/icons/folder_eye_open.ico + :/icons/folder_eye_closed.ico:/icons/folder_eye_open.ico + + + true + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true + + + + + + + Expand all folders in the list. + + + + + + + :/icons/expand_all.ico:/icons/expand_all.ico + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true + + + + + + + Collapse all folders in the list. + + + + + + + :/icons/collapse_all.ico:/icons/collapse_all.ico + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true + + + + + + + Toggle editability of folders in the list. + + + + + + + :/icons/lock_edit.ico + :/icons/unlock_edit.ico:/icons/lock_edit.ico + + + true + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true + + + + + + + Qt::Orientation::Horizontal + + + QSizePolicy::Policy::Preferred + + + + 12 + 19 + + + + + + + + true + + + + + + Filter... + + + true + + + + + + + + + + diff --git a/include/mainwindow.h b/include/mainwindow.h index 06b9bf780..e0bf7177f 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -173,11 +173,6 @@ private slots: void on_action_Open_Project_triggered(); void on_action_Reload_Project_triggered(); void on_action_Close_Project_triggered(); - - void on_mapList_activated(const QModelIndex &index); - void on_areaList_activated(const QModelIndex &index); - void on_layoutList_activated(const QModelIndex &index); - void on_action_Save_Project_triggered(); void openWarpMap(QString map_name, int event_id, Event::Group event_group); @@ -275,10 +270,6 @@ private slots: void on_actionTileset_Editor_triggered(); - void on_lineEdit_filterBox_textChanged(const QString &arg1); - void on_lineEdit_filterBox_Areas_textChanged(const QString &arg1); - void on_lineEdit_filterBox_Layouts_textChanged(const QString &arg1); - void moveEvent(QMoveEvent *event); void closeEvent(QCloseEvent *); @@ -292,19 +283,9 @@ private slots: void on_slider_EmergeMapOpacity_valueChanged(int value); void on_horizontalSlider_CollisionTransparency_valueChanged(int value); - void do_HideShow(); - void do_ExpandAll(); - void do_CollapseAll(); - void on_toolButton_HideShow_Groups_clicked(); - void on_toolButton_ExpandAll_Groups_clicked(); - void on_toolButton_CollapseAll_Groups_clicked(); - void on_toolButton_EnableDisable_EditGroups_clicked(); - void on_toolButton_HideShow_Areas_clicked(); - void on_toolButton_ExpandAll_Areas_clicked(); - void on_toolButton_CollapseAll_Areas_clicked(); - void on_toolButton_HideShow_Layouts_clicked(); - void on_toolButton_ExpandAll_Layouts_clicked(); - void on_toolButton_CollapseAll_Layouts_clicked(); + void mapListShortcut_ToggleEmptyFolders(); + void mapListShortcut_ExpandAll(); + void mapListShortcut_CollapseAll(); void on_actionAbout_Porymap_triggered(); void on_actionOpen_Log_File_triggered(); @@ -347,14 +328,12 @@ private slots: QPointer gridSettingsDialog = nullptr; QPointer customScriptsEditor = nullptr; - FilterChildrenProxyModel *groupListProxyModel; - MapGroupModel *mapGroupModel; - - FilterChildrenProxyModel *areaListProxyModel; - MapAreaModel *mapAreaModel; - - FilterChildrenProxyModel *layoutListProxyModel; - LayoutTreeModel *layoutTreeModel; + QPointer groupListProxyModel = nullptr; + QPointer mapGroupModel = nullptr; + QPointer areaListProxyModel = nullptr; + QPointer mapAreaModel = nullptr; + QPointer layoutListProxyModel = nullptr; + QPointer layoutTreeModel = nullptr; QPointer updatePromoter = nullptr; QPointer networkAccessManager = nullptr; @@ -375,9 +354,10 @@ private slots: bool tilesetNeedsRedraw = false; bool setLayout(QString layoutId); - bool setMap(QString, bool scroll = false); + bool setMap(QString); void unsetMap(); - bool userSetMap(QString, bool scrollTreeView = false); + bool userSetLayout(QString layoutId); + bool userSetMap(QString); void redrawMapScene(); void redrawLayoutScene(); void refreshMapScene(); @@ -389,7 +369,10 @@ private slots: void clearProjectUI(); void openSubWindow(QWidget * window); - void scrollTreeView(QString itemName); + void scrollMapList(MapTree *list, QString itemName); + void scrollMapListToCurrentMap(MapTree *list); + void scrollMapListToCurrentLayout(MapTree *list); + void resetMapListFilters(); QString getExistingDirectory(QString); bool openProject(QString dir, bool initial = false); bool closeProject(); @@ -403,31 +386,29 @@ private slots: void refreshRecentProjectsMenu(); void updateMapList(); - void mapListAddItem(); - void mapListRemoveItem(); void mapListAddGroup(); void mapListAddLayout(); void mapListAddArea(); void mapListRemoveGroup(); void mapListRemoveArea(); void mapListRemoveLayout(); + void openMapListItem(const QModelIndex &index); void displayMapProperties(); void checkToolButtons(); void clickToolButtonFromEditAction(Editor::EditAction editAction); - void showWindowTitle(); + void updateWindowTitle(); void initWindow(); void initCustomUI(); void initExtraSignals(); void initEditor(); void initMiscHeapObjects(); - void initMapSortOrder(); + void initMapList(); void initShortcuts(); void initExtraShortcuts(); void loadUserSettings(); - void applyMapListFilter(QString filterText); void restoreWindowState(); void setTheme(QString); void updateTilesetEditor(); @@ -447,6 +428,7 @@ private slots: double getMetatilesZoomScale(); void redrawMetatileSelection(); void scrollMetatileSelectorToSelection(); + MapListToolBar* getCurrentMapListToolBar(); QObjectList shortcutableObjects() const; void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false); diff --git a/include/ui/filterchildrenproxymodel.h b/include/ui/filterchildrenproxymodel.h index 5853d6257..d9eed7af9 100644 --- a/include/ui/filterchildrenproxymodel.h +++ b/include/ui/filterchildrenproxymodel.h @@ -9,7 +9,7 @@ class FilterChildrenProxyModel : public QSortFilterProxyModel public: explicit FilterChildrenProxyModel(QObject *parent = nullptr); - void toggleHideEmpty() { this->hideEmpty = !this->hideEmpty; } + bool toggleHideEmpty() { return this->hideEmpty = !this->hideEmpty; } protected: bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const; private: diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index d99c88151..8d00c4927 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -53,7 +53,17 @@ class GroupNameDelegate : public QStyledItemDelegate { class QRegularExpressionValidator; -class MapGroupModel : public QStandardItemModel { +class MapListModel : public QStandardItemModel { + Q_OBJECT + +public: + MapListModel(QObject *parent = nullptr) : QStandardItemModel(parent) {}; + ~MapListModel() { } + + virtual QModelIndex indexOf(QString id) const = 0; +}; + +class MapGroupModel : public MapListModel { Q_OBJECT public: @@ -80,7 +90,7 @@ class MapGroupModel : public QStandardItemModel { void removeGroup(int groupIndex); QStandardItem *getItem(const QModelIndex &index) const; - QModelIndex indexOfMap(QString mapName); + virtual QModelIndex indexOf(QString mapName) const override; void initialize(); @@ -103,7 +113,7 @@ class MapGroupModel : public QStandardItemModel { -class MapAreaModel : public QStandardItemModel { +class MapAreaModel : public MapListModel { Q_OBJECT public: @@ -123,7 +133,7 @@ class MapAreaModel : public QStandardItemModel { void removeArea(int groupIndex); QStandardItem *getItem(const QModelIndex &index) const; - QModelIndex indexOfMap(QString mapName); + virtual QModelIndex indexOf(QString mapName) const override; void initialize(); @@ -143,7 +153,7 @@ class MapAreaModel : public QStandardItemModel { -class LayoutTreeModel : public QStandardItemModel { +class LayoutTreeModel : public MapListModel { Q_OBJECT public: @@ -162,7 +172,7 @@ class LayoutTreeModel : public QStandardItemModel { QStandardItem *insertMapItem(QString mapName, QString layoutId); QStandardItem *getItem(const QModelIndex &index) const; - QModelIndex indexOfLayout(QString layoutName); + virtual QModelIndex indexOf(QString layoutName) const override; void initialize(); diff --git a/include/ui/maplisttoolbar.h b/include/ui/maplisttoolbar.h new file mode 100644 index 000000000..c66b0d80d --- /dev/null +++ b/include/ui/maplisttoolbar.h @@ -0,0 +1,49 @@ +#ifndef MAPLISTTOOLBAR_H +#define MAPLISTTOOLBAR_H + +#include "maplistmodels.h" +#include "filterchildrenproxymodel.h" + +#include +#include + +namespace Ui { +class MapListToolBar; +} + +class MapListToolBar : public QFrame +{ + Q_OBJECT + +public: + explicit MapListToolBar(QWidget *parent = nullptr); + ~MapListToolBar(); + + MapTree* list() const { return m_list; } + void setList(MapTree *list); + + void setEditsAllowedButtonHidden(bool hidden); + + void toggleEmptyFolders(); + void expandList(); + void collapseList(); + void toggleEditsAllowed(); + + void applyFilter(const QString &filterText); + void clearFilter(); + void setFilterLocked(bool locked) { m_filterLocked = locked; } + bool isFilterLocked() const { return m_filterLocked; } + +signals: + void filterCleared(MapTree*); + void addFolderClicked(); + +private: + Ui::MapListToolBar *ui; + QPointer m_list; + bool m_filterLocked = false; + + void setEditsAllowed(bool allowed); +}; + +#endif // MAPLISTTOOLBAR_H diff --git a/porymap.pro b/porymap.pro index d65bdf071..1b1c693e3 100644 --- a/porymap.pro +++ b/porymap.pro @@ -75,6 +75,7 @@ SOURCES += src/core/block.cpp \ src/ui/eventfilters.cpp \ src/ui/filterchildrenproxymodel.cpp \ src/ui/maplistmodels.cpp \ + src/ui/maplisttoolbar.cpp \ src/ui/graphicsview.cpp \ src/ui/imageproviders.cpp \ src/ui/layoutpixmapitem.cpp \ @@ -174,6 +175,7 @@ HEADERS += include/core/block.h \ include/ui/eventfilters.h \ include/ui/filterchildrenproxymodel.h \ include/ui/maplistmodels.h \ + include/ui/maplisttoolbar.h \ include/ui/graphicsview.h \ include/ui/imageproviders.h \ include/ui/layoutpixmapitem.h \ @@ -229,6 +231,7 @@ FORMS += forms/mainwindow.ui \ forms/colorinputwidget.ui \ forms/connectionslistitem.ui \ forms/gridsettingsdialog.ui \ + forms/maplisttoolbar.ui \ forms/newmapconnectiondialog.ui \ forms/prefabcreationdialog.ui \ forms/prefabframe.ui \ diff --git a/resources/icons/collapse_all.ico b/resources/icons/collapse_all.ico index f6c7f315826bdea6dc03fe387720105362368e68..806f2435f3d3cd6ecec97362dc3eaba5627bd310 100644 GIT binary patch literal 1871 zcmZ`)3p|r+7=O2^u_el-a=NT_a*JIkmo>{}h1xQdE#_p_uwv6T4HZKU(d{G^DnjWV zDXExsq1Gu;x~NdUh7hG9iFUrxDZkU{{eIu~KHu~I|DWf1pZER!-mQ$~?z$)w6aYZi z(}U^*%^1zAJs$dsV`D!;lUAq;-35S>o#-LXI1R}4@Sy_`YYKpD3jl+VOZFOoC;|YT zK>(2U1284>z-4bT1Tc6k&k#BtSVFcofWsyO1Z2UW2c+|| zl}d3^Tbxi7iYGccI^qd7cpDpQh+!>`5lA@E)&lXI(IEfEq4LCB5kFGG7YZ<%xSU{N zl*9>()g<~pM(gB7^M7O#h`%ihS|DD7;E6Z_{{LhWe#kFm8e~*9vaZo|WKA#WYac_hnEz>hk|2wA@pjsgBFbQ6XPMZS?7E{{U|mTQb_3|mt*$xFoN zK@HWkO+)|5_l-}+YkE4S$D=$NPB)VtzG9`} z*PfimSr(ZXocYy4RxrE4!^mS`>%!|xxpn2Qmz;J%B$d}2S+OU_u>m@}#`EEmsSRPN z^+xC@F2f+mD%CjIE)2UzLVIfJaPZTi7HLaGZC4j5 zW2d0kva)LmUxNguztI3?QIZLTNZ5hMxNW>q9J)|R2uM19WbVEqQelPktv&iYq>^?v(?Mdn!j{B#iwZ_w%^K32bg=8yERQ;4+itQ zru$RkdZo1Ha;1^!y3_2|<$?Lg>1Ig#QdcXnu^(9>j8zn}+kzG#4Rxvmj0kZr?K}I5 zdFqs*)yk(<@MOi}mrak`IOjnj7-~QIVE(C27|eX%=550S6bTks+2w8Gw4~|1vlvVe zSJ&fF&XDF8)UyxeZ_G?v9Mj1u>I}L$0lTk@l6l=s`@*}VT>Q-$xF17EvuPkT6PC4Lb8}8l#b-N zhE|s%D$N`FfPTW-CI=}@wnw~WcNSL%b<#QgO`;Sni&dUFYkV(+i3YY>4DIPhNc=`u zeg9dpvNBTo7TMi{cK%R%jD+=_aLF)8_r(&j=JFiR| zv=qx&4ioU(s*xFB{Qr-VC!{>L9}a124*NiHiNl z(Mi|manEHR>dYr?x@iBk0yC=y8&Gt5P`m;N{mg}{& zKOVkrin~$VUeYnm_U=QPs=&d$^n>4fccO)ey?P=z-L~^gO;$Y2+#uj|dl4%_bKiI_ LUQRvZ8kG1CNBinz literal 318 zcmah@$qm3D40C7)2%o+yUW~!$9jO~oheYLtFmfys=KzFHRT)oI0WJWQRPrV*zd~yb yz4ujln=i#JAt>BG5Gqq8XWqzTL)|v(i+?txuq8GV`mcN0^#sR&U9dsM!}$R)WC;%d diff --git a/resources/icons/expand_all.ico b/resources/icons/expand_all.ico index 0707936c59da83addeb3911acd285a97cf4119dd..ca913a1322074b24f0642be85334412725e89c4b 100644 GIT binary patch literal 2142 zcmZ`)3p|s1AODZ#vdAUg$|Y;nQrI&KWo=3p>dZAK>*VA*&SIOkITp&w%4I}}crzTS zQ=Q1<_L5vma$Jf|F_)AghQq;oToUg_Z~46EJ^$zPJpbSG`+mQ_+yD7|o>*r`J5_`Z z0sx?T(4OQf-I20eNkRH#hlNc^H+X=xgEau6#MSfOt7M?By{iKNVQ2t&d;sR8F5Vyj zAy@z;UI5_J09Y5CQSL&J0?t&*L4OAautRDq0Xdi^ke6C8=>?)`0KQ}cAdMtl^4YMj zXtvxJ6qzmm)s_(-9wUzeAcv*7Q8*L_GTxU-$9VfOeW(~NJy=En1TJ1`(y1J8B$pn< zVB@(&)DiH=9)0ro0o(9Hx7x)_GQt6IW#5% zDU0jv!wlgNQ7BoWFKf9@Dwp;(6NCM^Eop<041r8BSm^)BI5hvik;#x{*-~H2=?Jo5 zcxM`y8g!IIqf;4dX=zqFafGETe*wPMxk5H0CW3|+Rpph*z1Ju_$CA zhLLBhc-%l7&L)-yh_(Sekuv#1UTRIQ7D8~*Z*Y&-45_o@-~F|c&JYa!nmFB%^5@2k zh5ehfkM=i$YOS^H%DliM%6^`QHsgA79sL{vqVREgku;-Nv8bq5e3J$^-dh_$)O$F# zs}#|cY-);2{Z=GSMH8ZWidx5AUTiiWmZZ9^w`!)mWKGz0c48Dhl|s>HAJkw);8hd~87$UTSTrzu8^kU{1XWxA>+SA6Q73Xs*}N5Cv2eFpE>T$* z?^+X8u-o)TIZ61cXH?*OeEhZhMbWTg>pXROR|F~_+#<-b30mJ^<9^u~CCu0-8PL!k zw}=_K{PdFBX;x`AgIG~-c;1rQ_sVMwYmQU9iBlPDK_V0xIU}(lk1a@LxDD)tfsu#7 z(G8(_>oDj~d*8L~_^0T zwbY3@v~TY(BU@GOPtIzr$*55yzP0Ig77Lzihru2*;G%*Dm+k5XXzAn^5PEiNO5yn1 zd?czB?v$4vpflBaX-(c>`k(Z!SHbJ&P=?NG zF>(j)_PmEcS4XF${T1feA9Ja;9tL{l!uS?V$Rtups6VO%SJ*PMrc<%3Rx=4YtKLGD zG`Yk1zZFGH4m2A;CZ6SUFB4Q_wq^M5ikH(PMy$7~`RRpFC>(2ZJeSBypKM5b)~^NI zWPHTTf+0TY;X2X%&9JA-h5CzU1om54cPcAS7tl1iSW)n{m} zq4z#(FYBfFNC*n=KcET?$fuGsJ<@FGzwc|YZ+iyeG?5}rp6Yw<=FAnOtYIG+H|GFW CWC>FM diff --git a/resources/icons/folder_add.ico b/resources/icons/folder_add.ico new file mode 100755 index 0000000000000000000000000000000000000000..d881adf8e9202901244af1bafbc1c39dc939a9a7 GIT binary patch literal 1572 zcmV+<2HW|GP)4k@LZHNm0kuIuj3$~G9|=D&_$DD3O;BSn$`7eQK@(63(eMuu8kGhRsSlvl zMZ?1a-FE51w%gY(ZMVDk;mkSPeUxptC5_%>a_^mc?wy%$zL_&uv27dw=b@13jXRbd z&|s{zEsJjLjLQ^Ng$eyo)r-g0lERoQ2XvAgHa>s-9{MbO*H%VxQ-f#c^N;X)lJI0Y z;1-dS@#y)j6u%a?n0lCSl|KVxD1xTi#UVveCI+*rF?xpyy+=o)rzfmg25i+ycMg&i z1Dp}tgf$dI)rPNc_ARS*`he~r^qyUr2|Yb&h#XVtR?*WD5SJ=q!Q(*Z(Ft0&>2(v% z%8iixf_roa5T(FX#w$Y#Sg)l(lJG1GAhtx@3JtGRGI2oatr*$SMsXlhUa2w^MV!Y* zfWB!Bq^C7A0){9x5p5O+*r=+h@HRE0yY(6qXmkMB38jIus}X^h1fyZ^WW2TUA`lzGf|vFR0%NR(ri}2)L8RQZPLML00y`%1tgvXBL@YzvI0Emf z3&dFyW%DZ#y|@jdH?Wb11ud@}D6BzmIC`2CPCd2ORYE}39PpkwhhR%Pna=c46@_Ib zD8FY8EXx+C3EE_Hz?PM!PMM3~<P}q$N-GMfpk(1r-VyV z$;cAPkvLZp3v8wc1>-7(88y*;wYlSuOMOAE{UidaA>a%Jf|z;la`LU6?w#@aSH@yh z;?O7;oW?{s50{>8$wrqq3td+{IPdMTjpS2KM_=eE58)Rjb^g#j3bb3 zOQmY(R1km81)A~IU-dXb<*6pY$BOb|tgC(<1^zZ1_jK1W{ONr_HPL%DfP#uUgfj|v zFICUp6Zln*Sa;#$-@d_jEoZT2!BePxU@>x>xnj*=bO0XjFL=3bGnOc&`10tre@H!q zM0hf3=xOt#a84y|A3D;cM2NY<(XaYTiQe^t|Wp+lVEIH-3S@jcb17&n_1o&1Qax2(>Xq zp{jwyg*~3{@z|oLarXKb=pOJvSJPWRU$d@@p8e_Hjhd<_;V#5hdgPD@5P`b9tpxu( zy6Y#~1g#^xfW_%T{S_a|O7hVjJ`aORZirYHP1zp!nsxll7e0s5>3O{CS0`FAr=Zu{ zhKh%&Jr5E2^t|zoI^;x-h^`}YMzDR`gEx1?ovV_%&GiZbgQth7EnBf^D`CyynCkg# z7qwSw+~WqZ0C}pLs}KEA34PXgXw8jiTcWk`xqxKuhSl?`BT;igGrCEWS}1J9I@VtO zyk;rYJ3~!-T8z#S>O0#XlAn9^2L*0jCfwzaeE7KmsM~}RT_hdwesb_~=eWAg&0EaW z>g8zc>PFR!=`upoO5Y-KsZw(t@)>P6=pakf>6`d{c7S|F4@uvxI?&}oZA&rs&MKCz z!{D}`vWTN*zOr$iQ7^Xu?Ty&Z{G8~Fo9WctCX7%@sg%#;hLy9)=H zrN7b?(BZ|w;~(M`()hJWaDZ8Bc^lAFbSKI>L%2PM!q1;Zu+t3ecFLC55dfMzG+4Ld z@K4+DCaJD-m!1p+WI>Qkl3A52u(WIu);p)+?$iM~8p7GO-?6Lt2u_lwJ)UxNvK$z8 zf*VL7NfF7ExK55+RDC2o19ZoUZ)P9sZ|!H-5&r{nB5fq09}hVL#Kt*5{x`?J0t^7^ WWe&kFMnG%;0000e6r<%oD&DDM{_ScOGMf<*{M zN4qF$WsW7KX5p<81a@IrWMM%r3R;?(DSJEr{?A@)S4a>>RkFlDC^t;{YoE z0=AC<=~sOxeBTPTf5iDh*$p76!VC(J(oZy+VEhyK@G4O90Hn{h-yYCU+BMka1QMvF zrC)j-C>jC`m(>SSe8tyS`iEj*UE#1cpNvqyTwA~Rcc9>ssuFA&^hAUL&Qr+w43~ZD z{EYhXVe}2Omwr%H3GxR#k%9Vp*$?%L2OQXQTU$SgXHr0$=Jk72f)D!K5h0KBy8*X7v0G1^I&uD2)??dz5irm3vvg6jXiFaV1wNi zF*f$Nu&GyY;v2q~@#QV|JpU=w-_);SZMREZ*X_dEE@wnp*UkCJ(Qx_|Em+^HVwKIM zuC}?bs?#}UR6njxh1(rC`rsag9&Yy-!fMGMwyFw6~9FR%IPzWj46zaQ@kbbr7qAe~<&e*N#Se*l&E@Oc0L delta 230 zcmdm{{f|SKfq@YS1q48}0z(E11B2LPZ$ar0VQvNn5Qc&O|Nk>kf`R53Os*4Do;+7j ylErb_#gCJB30i;|o4*O}VPbQhacP6|jLAPl?3^gE2BLSOqZtR|e+Hm~85jT*rh9q- diff --git a/resources/images.qrc b/resources/images.qrc index 15650a659..a89535a90 100644 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -10,6 +10,7 @@ icons/file_put.ico icons/fill_color_cursor.ico icons/fill_color.ico + icons/folder_add.ico icons/folder_closed_map.ico icons/folder_closed.ico icons/folder_eye_closed.ico diff --git a/src/core/map.cpp b/src/core/map.cpp index 01ab95b0e..8067b9a74 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -257,7 +257,7 @@ void Map::clean() { } bool Map::hasUnsavedChanges() { - return !editHistory.isClean() || !this->layout->editHistory.isClean() || hasUnsavedDataChanges || !isPersistedToFile; + return !editHistory.isClean() || this->layout->hasUnsavedChanges() || hasUnsavedDataChanges || !isPersistedToFile; } void Map::pruneEditHistory() { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 08cdaf8cb..14a255c2e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -119,7 +119,7 @@ void MainWindow::initWindow() { this->initExtraSignals(); this->initEditor(); this->initMiscHeapObjects(); - this->initMapSortOrder(); + this->initMapList(); this->initShortcuts(); this->restoreWindowState(); @@ -166,15 +166,15 @@ void MainWindow::initExtraShortcuts() { shortcutToggle_Smart_Paths->setObjectName("shortcutToggle_Smart_Paths"); shortcutToggle_Smart_Paths->setWhatsThis("Toggle Smart Paths"); - auto *shortcutHide_Show = new Shortcut(QKeySequence(), this, SLOT(do_HideShow())); + auto *shortcutHide_Show = new Shortcut(QKeySequence(), this, SLOT(mapListShortcut_ToggleEmptyFolders())); shortcutHide_Show->setObjectName("shortcutHide_Show"); shortcutHide_Show->setWhatsThis("Map List: Hide/Show Empty Folders"); - auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(do_ExpandAll())); + auto *shortcutExpand_All = new Shortcut(QKeySequence(), this, SLOT(mapListShortcut_ExpandAll())); shortcutExpand_All->setObjectName("shortcutExpand_All"); shortcutExpand_All->setWhatsThis("Map List: Expand all folders"); - auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(do_CollapseAll())); + auto *shortcutCollapse_All = new Shortcut(QKeySequence(), this, SLOT(mapListShortcut_CollapseAll())); shortcutCollapse_All->setObjectName("shortcutCollapse_All"); shortcutCollapse_All->setWhatsThis("Map List: Collapse all folders"); @@ -240,44 +240,9 @@ void MainWindow::initCustomUI() { ui->mainTabBar->addTab(mainTabNames.value(i)); ui->mainTabBar->setTabIcon(i, mainTabIcons.value(i)); } - - WheelFilter *wheelFilter = new WheelFilter(this); - ui->mainTabBar->installEventFilter(wheelFilter); - this->ui->mapListContainer->tabBar()->installEventFilter(wheelFilter); - - // Create buttons for adding and removing items from the mapList - QFrame *frame = new QFrame(this->ui->mapListContainer); - frame->setFrameShape(QFrame::NoFrame); - QHBoxLayout *layout = new QHBoxLayout(frame); - - QPushButton *buttonAdd = new QPushButton(QIcon(":/icons/add.ico"), ""); - connect(buttonAdd, &QPushButton::clicked, [this]() { this->mapListAddItem(); }); - QPushButton *buttonRemove = new QPushButton(QIcon(":/icons/delete.ico"), ""); - connect(buttonRemove, &QPushButton::clicked, [this]() { this->mapListRemoveItem(); }); - - layout->addWidget(buttonAdd); - layout->addWidget(buttonRemove); - - layout->setSpacing(0); - layout->setContentsMargins(0, 0, 0, 0); - - this->ui->mapListContainer->setCornerWidget(frame, Qt::TopRightCorner); } void MainWindow::initExtraSignals() { - // Right-clicking on items in the map list tree view brings up a context menu. - ui->mapList->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->mapList, &QTreeView::customContextMenuRequested, - this, &MainWindow::onOpenMapListContextMenu); - - ui->areaList->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->areaList, &QTreeView::customContextMenuRequested, - this, &MainWindow::onOpenMapListContextMenu); - - ui->layoutList->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->layoutList, &QTreeView::customContextMenuRequested, - this, &MainWindow::onOpenMapListContextMenu); - // other signals connect(ui->newEventToolButton, &NewEventToolButton::newEventAdded, this, &MainWindow::addNewEvent); connect(ui->tabWidget_EventType, &QTabWidget::currentChanged, this, &MainWindow::eventTabChanged); @@ -381,7 +346,7 @@ void MainWindow::initEditor() { ui->menuEdit->addAction(showHistory); // Toggle an asterisk in the window title when the undo state is changed - connect(&editor->editGroup, &QUndoGroup::indexChanged, this, &MainWindow::showWindowTitle); + connect(&editor->editGroup, &QUndoGroup::indexChanged, this, &MainWindow::updateWindowTitle); // selecting objects from the spinners connect(this->ui->spinner_ObjectID, QOverload::of(&QSpinBox::valueChanged), [this](int value) { @@ -405,37 +370,104 @@ void MainWindow::initMiscHeapObjects() { ui->tabWidget_EventType->clear(); } -void MainWindow::initMapSortOrder() { - this->ui->mapListContainer->setCurrentIndex(static_cast(porymapConfig.mapSortOrder)); +void MainWindow::initMapList() { + ui->mapListContainer->setCurrentIndex(static_cast(porymapConfig.mapSortOrder)); + + WheelFilter *wheelFilter = new WheelFilter(this); + ui->mainTabBar->installEventFilter(wheelFilter); + ui->mapListContainer->tabBar()->installEventFilter(wheelFilter); + + // Create buttons for adding and removing items from the mapList + QFrame *buttonFrame = new QFrame(this->ui->mapListContainer); + buttonFrame->setFrameShape(QFrame::NoFrame); + + QHBoxLayout *layout = new QHBoxLayout(buttonFrame); + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + + // Create add map/layout button + QPushButton *buttonAdd = new QPushButton(QIcon(":/icons/add.ico"), ""); + connect(buttonAdd, &QPushButton::clicked, this, &MainWindow::on_action_NewMap_triggered); + layout->addWidget(buttonAdd); + + /* TODO: Remove button disabled, no current support for deleting maps/layouts + // Create remove map/layout button + QPushButton *buttonRemove = new QPushButton(QIcon(":/icons/delete.ico"), ""); + connect(buttonRemove, &QPushButton::clicked, this, &MainWindow::deleteCurrentMapOrLayout); + layout->addWidget(buttonRemove); + */ + + ui->mapListContainer->setCornerWidget(buttonFrame, Qt::TopRightCorner); + + // Connect tool bars to lists + ui->mapListToolBar_Groups->setList(ui->mapList); + ui->mapListToolBar_Areas->setList(ui->areaList); + ui->mapListToolBar_Layouts->setList(ui->layoutList); + + // Left-clicking on items in the map list opens the corresponding map/layout. + connect(ui->mapList, &QAbstractItemView::activated, this, &MainWindow::openMapListItem); + connect(ui->areaList, &QAbstractItemView::activated, this, &MainWindow::openMapListItem); + connect(ui->layoutList, &QAbstractItemView::activated, this, &MainWindow::openMapListItem); + + // Right-clicking on items in the map list brings up a context menu. + ui->mapList->setContextMenuPolicy(Qt::CustomContextMenu); + ui->areaList->setContextMenuPolicy(Qt::CustomContextMenu); + ui->layoutList->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->mapList, &QTreeView::customContextMenuRequested, this, &MainWindow::onOpenMapListContextMenu); + connect(ui->areaList, &QTreeView::customContextMenuRequested, this, &MainWindow::onOpenMapListContextMenu); + connect(ui->layoutList, &QTreeView::customContextMenuRequested, this, &MainWindow::onOpenMapListContextMenu); + + // Only the groups list allows reorganizing folder contents, editing folder names, etc. + ui->mapListToolBar_Areas->setEditsAllowedButtonHidden(true); + ui->mapListToolBar_Layouts->setEditsAllowedButtonHidden(true); + + // When map list search filter is cleared we want the current map/layout in the editor to be visible in the list. + connect(ui->mapListToolBar_Groups, &MapListToolBar::filterCleared, this, &MainWindow::scrollMapListToCurrentMap); + connect(ui->mapListToolBar_Areas, &MapListToolBar::filterCleared, this, &MainWindow::scrollMapListToCurrentMap); + connect(ui->mapListToolBar_Layouts, &MapListToolBar::filterCleared, this, &MainWindow::scrollMapListToCurrentLayout); + + // Connect the "add folder" button in each of the map lists + connect(ui->mapListToolBar_Groups, &MapListToolBar::addFolderClicked, this, &MainWindow::mapListAddGroup); + connect(ui->mapListToolBar_Areas, &MapListToolBar::addFolderClicked, this, &MainWindow::mapListAddArea); + connect(ui->mapListToolBar_Layouts, &MapListToolBar::addFolderClicked, this, &MainWindow::mapListAddLayout); } -void MainWindow::showWindowTitle() { +void MainWindow::updateWindowTitle() { + if (!editor || !editor->project) { + setWindowTitle(QCoreApplication::applicationName()); + return; + } + + const QString projectName = editor->project->getProjectTitle(); + if (!editor->layout) { + setWindowTitle(projectName); + return; + } + if (editor->map) { setWindowTitle(QString("%1%2 - %3") .arg(editor->map->hasUnsavedChanges() ? "* " : "") .arg(editor->map->name) - .arg(editor->project->getProjectTitle()) + .arg(projectName) ); - } - else if (editor->layout) { + } else { setWindowTitle(QString("%1%2 - %3") .arg(editor->layout->hasUnsavedChanges() ? "* " : "") .arg(editor->layout->name) - .arg(editor->project->getProjectTitle()) + .arg(projectName) ); } - if (editor && editor->layout) { - // For some reason (perhaps on Qt < 6?) we had to clear the icon first here or mainTabBar wouldn't display correctly. - ui->mainTabBar->setTabIcon(MainTab::Map, QIcon()); - QPixmap pixmap = editor->layout->pixmap; - if (!pixmap.isNull()) { - ui->mainTabBar->setTabIcon(MainTab::Map, QIcon(pixmap)); - } else { - ui->mainTabBar->setTabIcon(MainTab::Map, QIcon(QStringLiteral(":/icons/map.ico"))); - } + // For some reason (perhaps on Qt < 6?) we had to clear the icon first here or mainTabBar wouldn't display correctly. + ui->mainTabBar->setTabIcon(MainTab::Map, QIcon()); + + QPixmap pixmap = editor->layout->pixmap; + if (!pixmap.isNull()) { + ui->mainTabBar->setTabIcon(MainTab::Map, QIcon(pixmap)); + } else { + ui->mainTabBar->setTabIcon(MainTab::Map, QIcon(QStringLiteral(":/icons/map.ico"))); } - updateMapList(); + updateMapList(); // TODO: Why is this function responsible for this } void MainWindow::markMapEdited() { @@ -448,52 +480,7 @@ void MainWindow::markSpecificMapEdited(Map* map) { map->hasUnsavedDataChanges = true; if (editor && editor->map == map) - showWindowTitle(); -} - -void MainWindow::on_lineEdit_filterBox_textChanged(const QString &text) { - this->applyMapListFilter(text); -} - -void MainWindow::on_lineEdit_filterBox_Areas_textChanged(const QString &text) { - this->applyMapListFilter(text); -} - -void MainWindow::on_lineEdit_filterBox_Layouts_textChanged(const QString &text) { - this->applyMapListFilter(text); -} - -void MainWindow::applyMapListFilter(QString filterText) { - FilterChildrenProxyModel *proxy; - QTreeView *list; - QModelIndex sourceIndex; - switch (porymapConfig.mapSortOrder) { - case MapSortOrder::SortByGroup: - proxy = this->groupListProxyModel; - list = this->ui->mapList; - sourceIndex = mapGroupModel->indexOfMap(editor->map->name); - break; - case MapSortOrder::SortByArea: - proxy = this->areaListProxyModel; - list = this->ui->areaList; - sourceIndex = mapAreaModel->indexOfMap(editor->map->name); - break; - case MapSortOrder::SortByLayout: - proxy = this->layoutListProxyModel; - list = this->ui->layoutList; - sourceIndex = layoutTreeModel->indexOfLayout(editor->layout->id); - break; - } - - proxy->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption)); - if (filterText.isEmpty()) { - list->collapseAll(); - } else { - list->expandToDepth(0); - } - - list->setExpanded(proxy->mapFromSource(sourceIndex), true); - list->scrollTo(proxy->mapFromSource(sourceIndex), QAbstractItemView::PositionAtCenter); + updateWindowTitle(); } void MainWindow::loadUserSettings() { @@ -640,7 +627,7 @@ bool MainWindow::openProject(QString dir, bool initial) { // Only create the config files once the project has opened successfully in case the user selected an invalid directory this->editor->project->saveConfig(); - showWindowTitle(); + updateWindowTitle(); this->statusBar()->showMessage(QString("Opened %1").arg(projectString)); porymapConfig.projectManuallyClosed = false; @@ -702,7 +689,7 @@ bool MainWindow::setInitialMap() { const QString recent = userConfig.recentMapOrLayout; if (editor->project->mapNames.contains(recent)) { // User recently had a map open that still exists. - if (setMap(recent, true)) + if (setMap(recent)) return true; } else if (editor->project->mapLayoutsTable.contains(recent)) { // User recently had a layout open that still exists. @@ -712,7 +699,7 @@ bool MainWindow::setInitialMap() { // Failed to open recent map/layout, or no recent map/layout. Try opening maps then layouts sequentially. for (const auto &name : editor->project->mapNames) { - if (name != recent && setMap(name, true)) + if (name != recent && setMap(name)) return true; } for (const auto &id : editor->project->mapLayoutsTable) { @@ -808,7 +795,7 @@ void MainWindow::unsetMap() { // setMap, but with a visible error message in case of failure. // Use when the user is specifically requesting a map to open. -bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) { +bool MainWindow::userSetMap(QString map_name) { if (editor->map && editor->map->name == map_name) return true; // Already set @@ -819,7 +806,7 @@ bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) { return false; } - if (!setMap(map_name, scrollTreeView)) { + if (!setMap(map_name)) { QMessageBox msgBox(this); QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n\n%3") .arg(map_name) @@ -831,7 +818,7 @@ bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) { return true; } -bool MainWindow::setMap(QString map_name, bool scroll) { +bool MainWindow::setMap(QString map_name) { // if map name is empty, clear & disable map ui if (map_name.isEmpty()) { unsetMap(); @@ -851,7 +838,7 @@ bool MainWindow::setMap(QString map_name, bool scroll) { } if (editor->map && !editor->map->name.isNull()) { - ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(map_name)), false); + ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOf(map_name)), false); } setLayoutOnlyMode(false); @@ -859,12 +846,8 @@ bool MainWindow::setMap(QString map_name, bool scroll) { refreshMapScene(); displayMapProperties(); - - if (scroll) { - scrollTreeView(map_name); - } - - showWindowTitle(); + updateWindowTitle(); + resetMapListFilters(); connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing, Qt::UniqueConnection); connect(editor->map, &Map::modified, this, &MainWindow::markMapEdited, Qt::UniqueConnection); @@ -892,12 +875,28 @@ void MainWindow::setLayoutOnlyMode(bool layoutOnly) { this->ui->comboBox_LayoutSelector->setEnabled(mapEditingEnabled); } +// setLayout, but with a visible error message in case of failure. +// Use when the user is specifically requesting a layout to open. +bool MainWindow::userSetLayout(QString 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); + return false; + } + return true; +} + bool MainWindow::setLayout(QString layoutId) { if (this->editor->map) logInfo("Switching to a layout-only editing mode. Disabling map-related edits."); - setMap(QString()); + unsetMap(); + // TODO: Using the 'id' instead of the layout name here is inconsistent with how we treat maps. logInfo(QString("Setting layout to '%1'").arg(layoutId)); if (!this->editor->setLayout(layoutId)) { @@ -907,8 +906,8 @@ bool MainWindow::setLayout(QString layoutId) { layoutTreeModel->setLayout(layoutId); refreshMapScene(); - showWindowTitle(); - updateMapList(); + updateWindowTitle(); + resetMapListFilters(); connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing, Qt::UniqueConnection); @@ -969,7 +968,7 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_ } // Open the destination map. - if (!userSetMap(map_name, true)) + if (!userSetMap(map_name)) return; // Select the target event. @@ -1229,7 +1228,7 @@ bool MainWindow::setProjectUI() { this->layoutListProxyModel->setSourceModel(this->layoutTreeModel); ui->layoutList->setModel(layoutListProxyModel); - on_toolButton_EnableDisable_EditGroups_clicked(); + //on_toolButton_EnableDisable_EditGroups_clicked();//TODO return true; } @@ -1245,8 +1244,7 @@ void MainWindow::clearProjectUI() { const QSignalBlocker blocker7(ui->comboBox_Type); const QSignalBlocker blocker8(ui->comboBox_DiveMap); const QSignalBlocker blocker9(ui->comboBox_EmergeMap); - const QSignalBlocker blockerA(ui->lineEdit_filterBox); - const QSignalBlocker blockerB(ui->comboBox_LayoutSelector); + const QSignalBlocker blockerA(ui->comboBox_LayoutSelector); ui->comboBox_Song->clear(); ui->comboBox_Location->clear(); @@ -1257,49 +1255,51 @@ void MainWindow::clearProjectUI() { ui->comboBox_Type->clear(); ui->comboBox_DiveMap->clear(); ui->comboBox_EmergeMap->clear(); - ui->lineEdit_filterBox->clear(); ui->comboBox_LayoutSelector->clear(); // Clear map models - if (this->mapGroupModel) { - delete this->mapGroupModel; - this->mapGroupModel = nullptr; - delete this->groupListProxyModel; - this->groupListProxyModel = nullptr; - } - if (this->mapAreaModel) { - delete this->mapAreaModel; - this->mapAreaModel = nullptr; - delete this->areaListProxyModel; - this->areaListProxyModel = nullptr; - } - if (this->layoutTreeModel) { - delete this->layoutTreeModel; - this->layoutTreeModel = nullptr; - delete this->layoutListProxyModel; - this->layoutListProxyModel = nullptr; - } + delete this->mapGroupModel; + delete this->groupListProxyModel; + delete this->mapAreaModel; + delete this->areaListProxyModel; + delete this->layoutTreeModel; + delete this->layoutListProxyModel; + resetMapListFilters(); Event::clearIcons(); } -void MainWindow::scrollTreeView(QString itemName) { - switch (ui->mapListContainer->currentIndex()) { - case MapListTab::Groups: - groupListProxyModel->setFilterRegularExpression(QString()); - ui->mapList->setCurrentIndex(groupListProxyModel->mapFromSource(mapGroupModel->indexOfMap(itemName))); - ui->mapList->scrollTo(ui->mapList->currentIndex(), QAbstractItemView::PositionAtCenter); - break; - case MapListTab::Areas: - areaListProxyModel->setFilterRegularExpression(QString()); - ui->areaList->setCurrentIndex(areaListProxyModel->mapFromSource(mapAreaModel->indexOfMap(itemName))); - ui->areaList->scrollTo(ui->areaList->currentIndex(), QAbstractItemView::PositionAtCenter); - break; - case MapListTab::Layouts: - layoutListProxyModel->setFilterRegularExpression(QString()); - ui->layoutList->setCurrentIndex(layoutListProxyModel->mapFromSource(layoutTreeModel->indexOfLayout(itemName))); - ui->layoutList->scrollTo(ui->layoutList->currentIndex(), QAbstractItemView::PositionAtCenter); - break; +void MainWindow::scrollMapList(MapTree *list, QString itemName) { + if (!list || itemName.isEmpty()) + return; + auto model = static_cast(list->model()); + if (!model) + return; + auto sourceModel = static_cast(model->sourceModel()); + if (!sourceModel) + return; + QModelIndex sourceIndex = sourceModel->indexOf(itemName); + if (!sourceIndex.isValid()) + return; + QModelIndex index = model->mapFromSource(sourceIndex); + if (!index.isValid()) + return; + + list->setCurrentIndex(index); + list->setExpanded(index, true); + list->scrollTo(index, QAbstractItemView::PositionAtCenter); +} + +void MainWindow::scrollMapListToCurrentMap(MapTree *list) { + if (this->editor->map) { + scrollMapList(list, this->editor->map->name); + } +} + +// TODO: Initial scrolling doesn't center the layout on launch if it's not the current tab. +void MainWindow::scrollMapListToCurrentLayout(MapTree *list) { + if (this->editor->layout) { + scrollMapList(list, this->editor->layout->id); } } @@ -1346,6 +1346,7 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) { QStandardItem *selectedItem = model->itemFromIndex(index); if (selectedItem->parent()) { + // TODO: Right-click delete on maps? return; } @@ -1376,6 +1377,7 @@ void MainWindow::mapListAddGroup() { connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ if (!this->editor->project->groupNames.contains(newNameEdit->text())) dialog.accept(); + // TODO: Else display error? }); QFormLayout form(&dialog); @@ -1390,6 +1392,8 @@ void MainWindow::mapListAddGroup() { } } +// TODO: Pull this all out into a custom window. Connect that to an action in the main menu as well. +// (or, re-use the new map dialog with some tweaks) void MainWindow::mapListAddLayout() { if (!editor || !editor->project) return; @@ -1421,6 +1425,7 @@ void MainWindow::mapListAddLayout() { errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }"); QString errorMessage; + // TODO: Select default tilesets QComboBox *primaryCombo = new QComboBox(&dialog); primaryCombo->addItems(this->editor->project->primaryTilesetLabels); QComboBox *secondaryCombo = new QComboBox(&dialog); @@ -1529,14 +1534,19 @@ void MainWindow::mapListAddArea() { newNameEdit->setValidator(new QRegularExpressionValidator(re_validChars, newNameEdit)); connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ - if (!this->editor->project->mapSectionNameToValue.contains(newNameEdit->text())) + if (!this->editor->project->mapSectionNameToValue.contains(newNameDisplay->text())) dialog.accept(); + // TODO: Else display error? }); + QLabel *newNameEditLabel = new QLabel("New Map Section Name", &dialog); + QLabel *newNameDisplayLabel = new QLabel("Constant Name", &dialog); + newNameDisplayLabel->setEnabled(false); + QFormLayout form(&dialog); - form.addRow("New Map Section Name", newNameEdit); - form.addRow("Constant Name", newNameDisplay); + form.addRow(newNameEditLabel, newNameEdit); + form.addRow(newNameDisplayLabel, newNameDisplay); form.addRow(&newItemButtonBox); if (dialog.exec() == QDialog::Accepted) { @@ -1545,22 +1555,7 @@ void MainWindow::mapListAddArea() { } } -void MainWindow::mapListAddItem() { - if (!this->editor || !this->editor->project) return; - - switch (this->ui->mapListContainer->currentIndex()) { - case MapListTab::Groups: - this->mapListAddGroup(); - break; - case MapListTab::Areas: - this->mapListAddArea(); - break; - case MapListTab::Layouts: - this->mapListAddLayout(); - break; - } -} - +// TODO: Connect to right-click on map group folder in list void MainWindow::mapListRemoveGroup() { QItemSelectionModel *selectionModel = this->ui->mapList->selectionModel(); if (selectionModel->hasSelection()) { @@ -1579,6 +1574,7 @@ void MainWindow::mapListRemoveGroup() { } } +// TODO: Decide what to do about this. Currently unused. void MainWindow::mapListRemoveArea() { QItemSelectionModel *selectionModel = this->ui->areaList->selectionModel(); if (selectionModel->hasSelection()) { @@ -1597,27 +1593,11 @@ void MainWindow::mapListRemoveArea() { } } +// TODO: Connect to right-click on layout void MainWindow::mapListRemoveLayout() { // TODO: consider this in the future } -void MainWindow::mapListRemoveItem() { - if (!this->editor || !this->editor->project) return; - - switch (this->ui->mapListContainer->currentIndex()) { - case MapListTab::Groups: - this->mapListRemoveGroup(); - break; - case MapListTab::Areas: - // Disabled - // this->mapListRemoveArea(); - break; - case MapListTab::Layouts: - // Disabled - // this->mapListRemoveLayout(); - break; - } -} void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) { if (!triggeredAction) return; @@ -1661,7 +1641,7 @@ void MainWindow::onNewMapCreated() { this->mapAreaModel->insertMapItem(newMapName, newMap->location, newMapGroup); this->layoutTreeModel->insertMapItem(newMapName, newMap->layout->id); - setMap(newMapName, true); + setMap(newMapName); // Refresh any combo box that displays map names and persists between maps // (other combo boxes like for warp destinations are repopulated when the map changes). @@ -1877,51 +1857,42 @@ void MainWindow::currentMetatilesSelectionChanged() { scrollMetatileSelectorToSelection(); } +// TODO: Redundant. Remove void MainWindow::on_mapListContainer_currentChanged(int index) { switch (index) { case MapListTab::Groups: porymapConfig.mapSortOrder = MapSortOrder::SortByGroup; - if (this->editor && this->editor->map) scrollTreeView(this->editor->map->name); break; case MapListTab::Areas: porymapConfig.mapSortOrder = MapSortOrder::SortByArea; - if (this->editor && this->editor->map) scrollTreeView(this->editor->map->name); break; case MapListTab::Layouts: porymapConfig.mapSortOrder = MapSortOrder::SortByLayout; - if (this->editor && this->editor->layout) scrollTreeView(this->editor->layout->id); break; } } -void MainWindow::on_mapList_activated(const QModelIndex &index) { - QVariant data = index.data(Qt::UserRole); - if (index.data(MapListUserRoles::TypeRole) == "map_name" && !data.isNull()) { - QString mapName = data.toString(); - userSetMap(mapName); - } -} - -void MainWindow::on_areaList_activated(const QModelIndex &index) { - on_mapList_activated(index); -} - -void MainWindow::on_layoutList_activated(const QModelIndex &index) { - if (!index.isValid()) return; +void MainWindow::openMapListItem(const QModelIndex &index) { + if (!index.isValid()) + return; QVariant data = index.data(Qt::UserRole); - if (index.data(MapListUserRoles::TypeRole) == "map_layout" && !data.isNull()) { - QString layoutId = data.toString(); + if (data.isNull()) + return; - 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); - } + // Normally when a new map/layout is opened the search filters are cleared and the lists will scroll to display that map/layout in the list. + // We don't want to do this when the user interacts with a list directly, so we temporarily prevent changes to the search filter. + auto toolbar = getCurrentMapListToolBar(); + if (toolbar) toolbar->setFilterLocked(true); + + QString type = index.data(MapListUserRoles::TypeRole).toString(); + if (type == "map_name") { + userSetMap(data.toString()); + } else if (type == "map_layout") { + userSetLayout(data.toString()); } + + if (toolbar) toolbar->setFilterLocked(false); } void MainWindow::updateMapList() { @@ -1930,8 +1901,7 @@ void MainWindow::updateMapList() { this->groupListProxyModel->layoutChanged(); this->mapAreaModel->setMap(this->editor->map->name); this->areaListProxyModel->layoutChanged(); - } - else { + } else { this->mapGroupModel->setMap(QString()); this->groupListProxyModel->layoutChanged(); this->ui->mapList->clearSelection(); @@ -1943,8 +1913,7 @@ void MainWindow::updateMapList() { if (this->editor->layout) { this->layoutTreeModel->setLayout(this->editor->layout->id); this->layoutListProxyModel->layoutChanged(); - } - else { + } else { this->layoutTreeModel->setLayout(QString()); this->layoutListProxyModel->layoutChanged(); this->ui->layoutList->clearSelection(); @@ -1953,14 +1922,12 @@ void MainWindow::updateMapList() { void MainWindow::on_action_Save_Project_triggered() { editor->saveProject(); - updateMapList(); - showWindowTitle(); + updateWindowTitle(); } void MainWindow::on_action_Save_triggered() { editor->save(); - updateMapList(); - showWindowTitle(); + updateWindowTitle(); } void MainWindow::duplicate() { @@ -2884,7 +2851,7 @@ void MainWindow::clickToolButtonFromEditAction(Editor::EditAction editAction) { void MainWindow::onOpenConnectedMap(MapConnection *connection) { if (!connection) return; - if (userSetMap(connection->targetMapName(), true)) + if (userSetMap(connection->targetMapName())) editor->setSelectedConnection(connection->findMirror()); } @@ -2904,6 +2871,7 @@ void MainWindow::onMapLoaded(Map *map) { connect(map, &Map::modified, [this, map] { this->markSpecificMapEdited(map); }); } +// TODO: editor->layout below? and redrawLayoutScene? void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) { // If saved tilesets are currently in-use, update them and redraw // Otherwise overwrite the cache for the saved tileset @@ -3042,13 +3010,13 @@ void MainWindow::on_pushButton_ConfigureEncountersJSON_clicked() { void MainWindow::on_button_OpenDiveMap_clicked() { const QString mapName = ui->comboBox_DiveMap->currentText(); if (editor->project->mapNames.contains(mapName)) - userSetMap(mapName, true); + userSetMap(mapName); } void MainWindow::on_button_OpenEmergeMap_clicked() { const QString mapName = ui->comboBox_EmergeMap->currentText(); if (editor->project->mapNames.contains(mapName)) - userSetMap(mapName, true); + userSetMap(mapName); } void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) { @@ -3211,124 +3179,36 @@ void MainWindow::initTilesetEditor() { connect(this->tilesetEditor, &TilesetEditor::tilesetsSaved, this, &MainWindow::onTilesetsSaved); } -void MainWindow::do_ExpandAll() { +MapListToolBar* MainWindow::getCurrentMapListToolBar() { switch (ui->mapListContainer->currentIndex()) { - case MapListTab::Groups: - this->on_toolButton_ExpandAll_Groups_clicked(); - break; - case MapListTab::Areas: - this->on_toolButton_ExpandAll_Areas_clicked(); - break; - case MapListTab::Layouts: - this->on_toolButton_ExpandAll_Layouts_clicked(); - break; + case MapListTab::Groups: return ui->mapListToolBar_Groups; + case MapListTab::Areas: return ui->mapListToolBar_Areas; + case MapListTab::Layouts: return ui->mapListToolBar_Layouts; + default: return nullptr; } } -void MainWindow::do_CollapseAll() { - switch (ui->mapListContainer->currentIndex()) { - case MapListTab::Groups: - this->on_toolButton_CollapseAll_Groups_clicked(); - break; - case MapListTab::Areas: - this->on_toolButton_CollapseAll_Areas_clicked(); - break; - case MapListTab::Layouts: - this->on_toolButton_CollapseAll_Layouts_clicked(); - break; - } +// Clear the search filters on all the map lists. +// When the search filter is cleared the map lists will (if possible) display the currently-selected map/layout. +void MainWindow::resetMapListFilters() { + ui->mapListToolBar_Groups->clearFilter(); + ui->mapListToolBar_Areas->clearFilter(); + ui->mapListToolBar_Layouts->clearFilter(); } -// TODO: Save this state in porymapConfig -void MainWindow::do_HideShow() { - switch (ui->mapListContainer->currentIndex()) { - case MapListTab::Groups: - this->on_toolButton_HideShow_Groups_clicked(); - break; - case MapListTab::Areas: - this->on_toolButton_HideShow_Areas_clicked(); - break; - case MapListTab::Layouts: - this->on_toolButton_HideShow_Layouts_clicked(); - break; - } +void MainWindow::mapListShortcut_ExpandAll() { + auto toolbar = getCurrentMapListToolBar(); + if (toolbar) toolbar->expandList(); } -void MainWindow::on_toolButton_HideShow_Groups_clicked() { - if (ui->mapList) { - this->groupListProxyModel->toggleHideEmpty(); - this->groupListProxyModel->setFilterRegularExpression(this->ui->lineEdit_filterBox->text()); - } +void MainWindow::mapListShortcut_CollapseAll() { + auto toolbar = getCurrentMapListToolBar(); + if (toolbar) toolbar->collapseList(); } -void MainWindow::on_toolButton_ExpandAll_Groups_clicked() { - if (ui->mapList) { - ui->mapList->expandToDepth(0); - } -} - -void MainWindow::on_toolButton_CollapseAll_Groups_clicked() { - if (ui->mapList) { - ui->mapList->collapseAll(); - } -} - -// TODO: Save this state in porymapConfig -void MainWindow::on_toolButton_EnableDisable_EditGroups_clicked() { - this->ui->mapList->clearSelection(); - if (this->ui->toolButton_EnableDisable_EditGroups->isChecked()) { - ui->mapList->setSelectionMode(QAbstractItemView::ExtendedSelection); - ui->mapList->setDragEnabled(true); - ui->mapList->setAcceptDrops(true); - ui->mapList->setDropIndicatorShown(true); - ui->mapList->setDragDropMode(QAbstractItemView::InternalMove); - ui->mapList->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed); - } else { - ui->mapList->setSelectionMode(QAbstractItemView::NoSelection); - ui->mapList->setDragEnabled(false); - ui->mapList->setAcceptDrops(false); - ui->mapList->setDropIndicatorShown(false); - ui->mapList->setDragDropMode(QAbstractItemView::NoDragDrop); - ui->mapList->setEditTriggers(QAbstractItemView::NoEditTriggers); - } -} - -void MainWindow::on_toolButton_HideShow_Areas_clicked() { - if (ui->areaList) { - this->areaListProxyModel->toggleHideEmpty(); - this->areaListProxyModel->setFilterRegularExpression(this->ui->lineEdit_filterBox->text()); - } -} - -void MainWindow::on_toolButton_ExpandAll_Areas_clicked() { - if (ui->areaList) { - ui->areaList->expandToDepth(0); - } -} - -void MainWindow::on_toolButton_CollapseAll_Areas_clicked() { - if (ui->areaList) { - ui->areaList->collapseAll(); - } -} - -void MainWindow::on_toolButton_HideShow_Layouts_clicked() { - if (ui->layoutList) { - this->layoutListProxyModel->toggleHideEmpty(); - this->layoutListProxyModel->setFilterRegularExpression(this->ui->lineEdit_filterBox->text()); - } -} - -void MainWindow::on_toolButton_ExpandAll_Layouts_clicked() { - if (ui->layoutList) { - ui->layoutList->expandToDepth(0); - } -} - -void MainWindow::on_toolButton_CollapseAll_Layouts_clicked() { - if (ui->layoutList) { - ui->layoutList->collapseAll(); - } +void MainWindow::mapListShortcut_ToggleEmptyFolders() { + auto toolbar = getCurrentMapListToolBar(); + if (toolbar) toolbar->toggleEmptyFolders(); } void MainWindow::on_actionAbout_Porymap_triggered() @@ -3646,7 +3526,7 @@ bool MainWindow::closeProject() { editor->closeProject(); clearProjectUI(); setWindowDisabled(true); - setWindowTitle(QCoreApplication::applicationName()); + updateWindowTitle(); return true; } diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 7e0d7e62e..e9fbaa1f8 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -44,7 +44,7 @@ void GroupNameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOption -MapGroupModel::MapGroupModel(Project *project, QObject *parent) : QStandardItemModel(parent) { +MapGroupModel::MapGroupModel(Project *project, QObject *parent) : MapListModel(parent) { this->project = project; this->root = this->invisibleRootItem(); @@ -283,7 +283,7 @@ QStandardItem *MapGroupModel::getItem(const QModelIndex &index) const { return this->root; } -QModelIndex MapGroupModel::indexOfMap(QString mapName) { +QModelIndex MapGroupModel::indexOf(QString mapName) const { if (this->mapItems.contains(mapName)) { return this->mapItems[mapName]->index(); } @@ -366,7 +366,7 @@ bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int -MapAreaModel::MapAreaModel(Project *project, QObject *parent) : QStandardItemModel(parent) { +MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(parent) { this->project = project; this->root = this->invisibleRootItem(); @@ -461,7 +461,7 @@ QStandardItem *MapAreaModel::getItem(const QModelIndex &index) const { return this->root; } -QModelIndex MapAreaModel::indexOfMap(QString mapName) { +QModelIndex MapAreaModel::indexOf(QString mapName) const { if (this->mapItems.contains(mapName)) { return this->mapItems[mapName]->index(); } @@ -531,7 +531,7 @@ QVariant MapAreaModel::data(const QModelIndex &index, int role) const { -LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : QStandardItemModel(parent) { +LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : MapListModel(parent) { this->project = project; this->root = this->invisibleRootItem(); @@ -609,7 +609,7 @@ QStandardItem *LayoutTreeModel::getItem(const QModelIndex &index) const { return this->root; } -QModelIndex LayoutTreeModel::indexOfLayout(QString layoutName) { +QModelIndex LayoutTreeModel::indexOf(QString layoutName) const { if (this->layoutItems.contains(layoutName)) { return this->layoutItems[layoutName]->index(); } diff --git a/src/ui/maplisttoolbar.cpp b/src/ui/maplisttoolbar.cpp new file mode 100644 index 000000000..4dd26ecd3 --- /dev/null +++ b/src/ui/maplisttoolbar.cpp @@ -0,0 +1,121 @@ +#include "maplisttoolbar.h" +#include "ui_maplisttoolbar.h" +#include "editor.h" + +#include + +MapListToolBar::MapListToolBar(QWidget *parent) + : QFrame(parent) + , ui(new Ui::MapListToolBar) +{ + ui->setupUi(this); + + connect(ui->button_ToggleEmptyFolders, &QAbstractButton::clicked, this, &MapListToolBar::toggleEmptyFolders); + connect(ui->button_AddFolder, &QAbstractButton::clicked, this, &MapListToolBar::addFolderClicked); // TODO: Tool tip + connect(ui->button_ExpandAll, &QAbstractButton::clicked, this, &MapListToolBar::expandList); + connect(ui->button_CollapseAll, &QAbstractButton::clicked, this, &MapListToolBar::collapseList); + connect(ui->button_ToggleEdit, &QAbstractButton::clicked, this, &MapListToolBar::toggleEditsAllowed); + connect(ui->lineEdit_filterBox, &QLineEdit::textChanged, this, &MapListToolBar::applyFilter); +} + +MapListToolBar::~MapListToolBar() +{ + delete ui; +} + +void MapListToolBar::setList(MapTree *list) { + m_list = list; + + // Sync list with current button states + setEditsAllowed(ui->button_ToggleEdit->isChecked()); + // TODO: Empty folders +} + +void MapListToolBar::setEditsAllowedButtonHidden(bool hidden) { + ui->button_ToggleEdit->setVisible(!hidden); +} + +void MapListToolBar::setEditsAllowed(bool allowed) { + if (!m_list) + return; + + if (allowed) { + m_list->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_list->setDragEnabled(true); + m_list->setAcceptDrops(true); + m_list->setDropIndicatorShown(true); + m_list->setDragDropMode(QAbstractItemView::InternalMove); + m_list->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed); + } else { + m_list->setSelectionMode(QAbstractItemView::NoSelection); + m_list->setDragEnabled(false); + m_list->setAcceptDrops(false); + m_list->setDropIndicatorShown(false); + m_list->setDragDropMode(QAbstractItemView::NoDragDrop); + m_list->setEditTriggers(QAbstractItemView::NoEditTriggers); + } +} + +// TODO: Sync the UI in each of these + +void MapListToolBar::toggleEmptyFolders() { + if (!m_list) + return; + + auto model = static_cast(m_list->model()); + if (!model) + return; + + bool hidden = model->toggleHideEmpty(); + model->setFilterRegularExpression(ui->lineEdit_filterBox->text()); + + // Update tool tip to reflect what will happen if the button is pressed. + const QString toolTip = QString("%1 empty folders in the list.").arg(hidden ? "Show" : "Hide"); + ui->button_ToggleEmptyFolders->setToolTip(toolTip); + + // Display message to let user know what just happened (if there are no empty folders visible it's not obvious). + const QString message = QString("%1 empty folders!").arg(hidden ? "Hiding" : "Showing"); + QToolTip::showText(ui->button_ToggleEmptyFolders->mapToGlobal(QPoint(0, 0)), message); +} + +void MapListToolBar::expandList() { + if (m_list) + m_list->expandToDepth(0); +} + +void MapListToolBar::collapseList() { + if (m_list) { + m_list->collapseAll(); + } +} + +// TODO: Save this state in porymapConfig? +// TODO: This isn't actually toggling anything, it's just updating based on the button +void MapListToolBar::toggleEditsAllowed() { + if (m_list) { + m_list->clearSelection(); + } + setEditsAllowed(ui->button_ToggleEdit->isChecked()); +} + +void MapListToolBar::applyFilter(const QString &filterText) { + if (!m_list || m_filterLocked) + return; + + const QSignalBlocker b(ui->lineEdit_filterBox); + ui->lineEdit_filterBox->setText(filterText); + + auto model = static_cast(m_list->model()); + if (model) model->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption)); + + if (filterText.isEmpty()) { + m_list->collapseAll(); + emit filterCleared(m_list); + } else { + m_list->expandToDepth(0); + } +} + +void MapListToolBar::clearFilter() { + applyFilter(""); +} From a18b2c960bf1a65f579c7ac66b462ef527320261 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 28 Oct 2024 15:43:13 -0400 Subject: [PATCH 58/70] Stop unnecessary work/leaks from extra setProjectUI calls --- src/mainwindow.cpp | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 14a255c2e..8ea0d5df6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1634,25 +1634,32 @@ void MainWindow::onNewMapCreated() { editor->project->saveMap(newMap); editor->project->saveAllDataStructures(); - setProjectUI(); // need to maybe repopulate layout combo - // Add new Map / Layout to the mapList models this->mapGroupModel->insertMapItem(newMapName, editor->project->groupNames[newMapGroup]); this->mapAreaModel->insertMapItem(newMapName, newMap->location, newMapGroup); this->layoutTreeModel->insertMapItem(newMapName, newMap->layout->id); - setMap(newMapName); - // Refresh any combo box that displays map names and persists between maps // (other combo boxes like for warp destinations are repopulated when the map changes). - int index = this->editor->project->mapNames.indexOf(newMapName); - if (index >= 0) { - const QSignalBlocker blocker1(ui->comboBox_DiveMap); - const QSignalBlocker blocker2(ui->comboBox_EmergeMap); - ui->comboBox_DiveMap->insertItem(index, newMapName); - ui->comboBox_EmergeMap->insertItem(index, newMapName); + int mapIndex = this->editor->project->mapNames.indexOf(newMapName); + if (mapIndex >= 0) { + const QSignalBlocker b_DiveMap(ui->comboBox_DiveMap); + const QSignalBlocker b_EmergeMap(ui->comboBox_EmergeMap); + ui->comboBox_DiveMap->insertItem(mapIndex, newMapName); + ui->comboBox_EmergeMap->insertItem(mapIndex, newMapName); + } + + // Refresh layout combo box (if a new one was created) + if (!existingLayout) { + int layoutIndex = this->editor->project->mapLayoutsTable.indexOf(newMap->layout->id); + if (layoutIndex >= 0) { + const QSignalBlocker b_Layouts(ui->comboBox_LayoutSelector); + ui->comboBox_LayoutSelector->insertItem(layoutIndex, newMap->layout->id); + } } + setMap(newMapName); + if (newMap->needsHealLocation) { addNewEvent(Event::Type::HealLocation); editor->project->saveHealLocations(newMap); @@ -1787,8 +1794,6 @@ void MainWindow::on_actionNew_Tileset_triggered() { } insertTilesetLabel(&editor->project->tilesetLabelsOrdered, createTilesetDialog->fullSymbolName); - setProjectUI(); // need to reload tileset combos - QMessageBox msgBox(this); msgBox.setText("Successfully created tileset."); QString message = QString("Tileset \"%1\" was created successfully.").arg(createTilesetDialog->friendlyName); From 3bd5ddbf2f1c227356f8eed9fbac64ee499b8f8d Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 28 Oct 2024 16:02:17 -0400 Subject: [PATCH 59/70] Simplify saving the map list tab --- include/config.h | 10 ++----- include/mainwindow.h | 5 +--- include/ui/newmappopup.h | 2 +- src/config.cpp | 18 ++--------- src/mainwindow.cpp | 65 ++++++++++++---------------------------- src/ui/newmappopup.cpp | 10 +++---- 6 files changed, 31 insertions(+), 79 deletions(-) diff --git a/include/config.h b/include/config.h index 01a7b09c5..31f7fa7fd 100644 --- a/include/config.h +++ b/include/config.h @@ -22,12 +22,6 @@ static const QVersionNumber porymapVersion = QVersionNumber::fromString(PORYMAP_ #define CONFIG_BACKWARDS_COMPATABILITY -enum MapSortOrder { - SortByGroup = 0, - SortByArea = 1, - SortByLayout = 2, -}; - class KeyValueConfigBase { public: @@ -56,7 +50,7 @@ class PorymapConfig: public KeyValueConfigBase this->recentProjects.clear(); this->projectManuallyClosed = false; this->reopenOnLaunch = true; - this->mapSortOrder = MapSortOrder::SortByGroup; + this->mapListTab = 0; this->prettyCursors = true; this->mirrorConnectingMaps = true; this->showDiveEmergeMaps = false; @@ -107,7 +101,7 @@ class PorymapConfig: public KeyValueConfigBase bool reopenOnLaunch; bool projectManuallyClosed; - MapSortOrder mapSortOrder; + int mapListTab; bool prettyCursors; bool mirrorConnectingMaps; bool showDiveEmergeMaps; diff --git a/include/mainwindow.h b/include/mainwindow.h index e0bf7177f..2abc151df 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -242,11 +242,7 @@ private slots: void on_toolButton_Move_clicked(); void on_toolButton_Shift_clicked(); - void on_mapListContainer_currentChanged(int index); void onOpenMapListContextMenu(const QPoint &point); - void onAddNewMapToGroupClick(QAction* triggeredAction); - void onAddNewMapToAreaClick(QAction* triggeredAction); - void onAddNewMapToLayoutClick(QAction* triggeredAction); void currentMetatilesSelectionChanged(); void on_action_Export_Map_Image_triggered(); @@ -393,6 +389,7 @@ private slots: void mapListRemoveArea(); void mapListRemoveLayout(); void openMapListItem(const QModelIndex &index); + void saveMapListTab(int index); void displayMapProperties(); void checkToolButtons(); diff --git a/include/ui/newmappopup.h b/include/ui/newmappopup.h index 3d24715df..66a15a919 100644 --- a/include/ui/newmappopup.h +++ b/include/ui/newmappopup.h @@ -24,7 +24,7 @@ class NewMapPopup : public QMainWindow QString layoutId; void init(); void initUi(); - void init(MapSortOrder type, QVariant data); + void init(int tabIndex, QVariant data); void init(Layout *); static void setDefaultSettings(Project *project); diff --git a/src/config.cpp b/src/config.cpp index 0d72542d8..ca6473b1c 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -278,12 +278,6 @@ uint32_t KeyValueConfigBase::getConfigUint32(QString key, QString value, uint32_ return qMin(max, qMax(min, result)); } -const QMap mapSortOrderMap = { - {"group", MapSortOrder::SortByGroup}, - {"layout", MapSortOrder::SortByLayout}, - {"area", MapSortOrder::SortByArea}, -}; - PorymapConfig porymapConfig; QString PorymapConfig::getConfigFilepath() { @@ -308,14 +302,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->reopenOnLaunch = getConfigBool(key, value); } else if (key == "pretty_cursors") { this->prettyCursors = getConfigBool(key, value); - } else if (key == "map_sort_order") { - QString sortOrder = value.toLower(); - if (mapSortOrderMap.contains(sortOrder)) { - this->mapSortOrder = mapSortOrderMap.value(sortOrder); - } else { - this->mapSortOrder = MapSortOrder::SortByGroup; - logWarn(QString("Invalid config value for map_sort_order: '%1'. Must be 'group', 'area', or 'layout'.").arg(value)); - } + } else if (key == "map_list_tab") { + this->mapListTab = getConfigInteger(key, value, 0, 2, 0); } else if (key == "main_window_geometry") { this->mainWindowGeometry = bytesFromString(value); } else if (key == "main_window_state") { @@ -432,7 +420,7 @@ QMap PorymapConfig::getKeyValueMap() { map.insert("project_manually_closed", this->projectManuallyClosed ? "1" : "0"); map.insert("reopen_on_launch", this->reopenOnLaunch ? "1" : "0"); map.insert("pretty_cursors", this->prettyCursors ? "1" : "0"); - map.insert("map_sort_order", mapSortOrderMap.key(this->mapSortOrder)); + map.insert("map_list_tab", QString::number(this->mapListTab)); map.insert("main_window_geometry", stringFromByteArray(this->mainWindowGeometry)); map.insert("main_window_state", stringFromByteArray(this->mainWindowState)); map.insert("map_splitter_state", stringFromByteArray(this->mapSplitterState)); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8ea0d5df6..db7cf6b10 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -371,7 +371,7 @@ void MainWindow::initMiscHeapObjects() { } void MainWindow::initMapList() { - ui->mapListContainer->setCurrentIndex(static_cast(porymapConfig.mapSortOrder)); + ui->mapListContainer->setCurrentIndex(porymapConfig.mapListTab); WheelFilter *wheelFilter = new WheelFilter(this); ui->mainTabBar->installEventFilter(wheelFilter); @@ -430,6 +430,8 @@ void MainWindow::initMapList() { connect(ui->mapListToolBar_Groups, &MapListToolBar::addFolderClicked, this, &MainWindow::mapListAddGroup); connect(ui->mapListToolBar_Areas, &MapListToolBar::addFolderClicked, this, &MainWindow::mapListAddArea); connect(ui->mapListToolBar_Layouts, &MapListToolBar::addFolderClicked, this, &MainWindow::mapListAddLayout); + + connect(ui->mapListContainer, &QTabWidget::currentChanged, this, &MainWindow::saveMapListTab); } void MainWindow::updateWindowTitle() { @@ -1209,7 +1211,6 @@ bool MainWindow::setProjectUI() { ui->spinBox_SelectedCollision->setMaximum(Block::getMaxCollision()); // map models - // !TODO: delete these on close this->mapGroupModel = new MapGroupModel(editor->project); this->groupListProxyModel = new FilterChildrenProxyModel(); groupListProxyModel->setSourceModel(this->mapGroupModel); @@ -1308,32 +1309,30 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) { int dataRole; FilterChildrenProxyModel *proxy; QTreeView *list; - void (MainWindow::*addFunction)(QAction *); QString actionText; - switch (porymapConfig.mapSortOrder) { - case MapSortOrder::SortByGroup: + int currentTab = ui->mapListContainer->currentIndex(); + + switch (currentTab) { + case MapListTab::Groups: model = this->mapGroupModel; dataRole = MapListUserRoles::GroupRole; proxy = this->groupListProxyModel; list = this->ui->mapList; - addFunction = &MainWindow::onAddNewMapToGroupClick; actionText = "Add New Map to Group"; break; - case MapSortOrder::SortByArea: + case MapListTab::Areas: model = this->mapAreaModel; dataRole = Qt::UserRole; proxy = this->areaListProxyModel; list = this->ui->areaList; - addFunction = &MainWindow::onAddNewMapToAreaClick; actionText = "Add New Map to Area"; break; - case MapSortOrder::SortByLayout: + case MapListTab::Layouts: model = this->layoutTreeModel; dataRole = Qt::UserRole; proxy = this->layoutListProxyModel; list = this->ui->layoutList; - addFunction = &MainWindow::onAddNewMapToLayoutClick; actionText = "Add New Map with Layout"; break; } @@ -1358,7 +1357,14 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) { QMenu menu(this); QActionGroup actions(&menu); actions.addAction(menu.addAction(actionText))->setData(itemData); - (this->*addFunction)(menu.exec(QCursor::pos())); + + auto triggeredAction = menu.exec(QCursor::pos()); + if (!triggeredAction) + return; + + // At the moment all the actions do the same thing (add new map/layout). + openNewMapPopupWindow(); + this->newMapPrompt->init(currentTab, triggeredAction->data()); } void MainWindow::mapListAddGroup() { @@ -1598,28 +1604,6 @@ void MainWindow::mapListRemoveLayout() { // TODO: consider this in the future } - -void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction) { - if (!triggeredAction) return; - - openNewMapPopupWindow(); - this->newMapPrompt->init(MapSortOrder::SortByGroup, triggeredAction->data()); -} - -void MainWindow::onAddNewMapToAreaClick(QAction* triggeredAction) { - if (!triggeredAction) return; - - openNewMapPopupWindow(); - this->newMapPrompt->init(MapSortOrder::SortByArea, triggeredAction->data()); -} - -void MainWindow::onAddNewMapToLayoutClick(QAction* triggeredAction) { - if (!triggeredAction) return; - - openNewMapPopupWindow(); - this->newMapPrompt->init(MapSortOrder::SortByLayout, triggeredAction->data()); -} - void MainWindow::onNewMapCreated() { QString newMapName = this->newMapPrompt->map->name; int newMapGroup = this->newMapPrompt->group; @@ -1862,19 +1846,8 @@ void MainWindow::currentMetatilesSelectionChanged() { scrollMetatileSelectorToSelection(); } -// TODO: Redundant. Remove -void MainWindow::on_mapListContainer_currentChanged(int index) { - switch (index) { - case MapListTab::Groups: - porymapConfig.mapSortOrder = MapSortOrder::SortByGroup; - break; - case MapListTab::Areas: - porymapConfig.mapSortOrder = MapSortOrder::SortByArea; - break; - case MapListTab::Layouts: - porymapConfig.mapSortOrder = MapSortOrder::SortByLayout; - break; - } +void MainWindow::saveMapListTab(int index) { + porymapConfig.mapListTab = index; } void MainWindow::openMapListItem(const QModelIndex &index) { diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index 17c1ed29c..a9d661da9 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -102,17 +102,17 @@ void NewMapPopup::init() { } // Creating new map by right-clicking in the map list -void NewMapPopup::init(MapSortOrder type, QVariant data) { +void NewMapPopup::init(int tabIndex, QVariant data) { initUi(); - switch (type) + switch (tabIndex) { - case MapSortOrder::SortByGroup: + case MapListTab::Groups: settings.group = project->groupNames.at(data.toInt()); break; - case MapSortOrder::SortByArea: + case MapListTab::Areas: settings.location = data.toString(); break; - case MapSortOrder::SortByLayout: + case MapListTab::Layouts: this->ui->checkBox_UseExistingLayout->setCheckState(Qt::Checked); useLayout(data.toString()); break; From 2ce5c3fcc59ce62512592d0533242844897a8dfe Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 29 Oct 2024 15:56:02 -0400 Subject: [PATCH 60/70] Fix crash on tileset save, bugs with map resizing --- include/core/map.h | 1 - include/mainwindow.h | 3 --- src/core/editcommands.cpp | 1 + src/editor.cpp | 13 ++++++++----- src/mainwindow.cpp | 39 +++++++++++---------------------------- src/scriptapi/apimap.cpp | 12 ++++++------ 6 files changed, 26 insertions(+), 43 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index 03a8931df..66aa00084 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -114,7 +114,6 @@ class Map : public QObject signals: void modified(); void mapDimensionsChanged(const QSize &size); - void mapNeedsRedrawing(); void openScriptRequested(QString label); void connectionAdded(MapConnection*); void connectionRemoved(MapConnection*); diff --git a/include/mainwindow.h b/include/mainwindow.h index 2abc151df..986036d6c 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -185,8 +185,6 @@ private slots: void onLayoutChanged(Layout *layout); void onOpenConnectedMap(MapConnection*); - void onMapNeedsRedrawing(); - void onLayoutNeedsRedrawing(); void onTilesetsSaved(QString, QString); void openNewMapPopupWindow(); void onNewMapCreated(); @@ -355,7 +353,6 @@ private slots: bool userSetLayout(QString layoutId); bool userSetMap(QString); void redrawMapScene(); - void redrawLayoutScene(); void refreshMapScene(); void setLayoutOnlyMode(bool layoutOnly); diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp index 224aad215..0843b2c0d 100644 --- a/src/core/editcommands.cpp +++ b/src/core/editcommands.cpp @@ -486,6 +486,7 @@ int EventPaste::id() const { ************************************************************************ ******************************************************************************/ +// TODO: Undo/redo for script edits to layout dimensions doesn't render correctly. ScriptEditLayout::ScriptEditLayout(Layout *layout, QSize oldLayoutDimensions, QSize newLayoutDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, diff --git a/src/editor.cpp b/src/editor.cpp index 681694321..ac0f10113 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1280,6 +1280,7 @@ bool Editor::setMap(QString map_name) { if (!displayMap()) { return false; } + displayWildMonTables(); connect(map, &Map::openScriptRequested, this, &Editor::openScript); connect(map, &Map::connectionAdded, this, &Editor::displayConnection); @@ -1551,10 +1552,11 @@ void Editor::clearMap() { } bool Editor::displayMap() { + if (!this->map) + return false; displayMapEvents(); displayMapConnections(); - displayWildMonTables(); maskNonVisibleConnectionTiles(); if (events_group) { @@ -1564,6 +1566,9 @@ bool Editor::displayMap() { } bool Editor::displayLayout() { + if (!this->layout) + return false; + if (!scene) { scene = new QGraphicsScene; MapSceneEventFilter *filter = new MapSceneEventFilter(scene); @@ -1826,10 +1831,8 @@ void Editor::clearMapConnections() { void Editor::displayMapConnections() { clearMapConnections(); - if (map) { - for (auto connection : map->getConnections()) - displayConnection(connection); - } + for (auto connection : map->getConnections()) + displayConnection(connection); if (!connection_items.isEmpty()) setSelectedConnectionItem(connection_items.first()); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index db7cf6b10..bd69d464c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -839,6 +839,7 @@ bool MainWindow::setMap(QString map_name) { return false; } + // TODO: Redundant? if (editor->map && !editor->map->name.isNull()) { ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOf(map_name)), false); } @@ -851,11 +852,10 @@ bool MainWindow::setMap(QString map_name) { updateWindowTitle(); resetMapListFilters(); - connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing, Qt::UniqueConnection); connect(editor->map, &Map::modified, this, &MainWindow::markMapEdited, Qt::UniqueConnection); connect(editor->layout, &Layout::layoutChanged, this, &MainWindow::onLayoutChanged, Qt::UniqueConnection); - connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing, Qt::UniqueConnection); + connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::redrawMapScene, Qt::UniqueConnection); userConfig.recentMapOrLayout = map_name; @@ -911,7 +911,7 @@ bool MainWindow::setLayout(QString layoutId) { updateWindowTitle(); resetMapListFilters(); - connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::onLayoutNeedsRedrawing, Qt::UniqueConnection); + connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::redrawMapScene, Qt::UniqueConnection); updateTilesetEditor(); @@ -921,17 +921,9 @@ bool MainWindow::setLayout(QString layoutId) { } void MainWindow::redrawMapScene() { - if (!editor->displayMap()) - return; - - this->refreshMapScene(); -} - -void MainWindow::redrawLayoutScene() { - if (!editor->displayLayout()) - return; - - this->refreshMapScene(); + editor->displayMap(); + editor->displayLayout(); + refreshMapScene(); } void MainWindow::refreshMapScene() { @@ -2837,31 +2829,22 @@ void MainWindow::onLayoutChanged(Layout *) { updateMapList(); } -void MainWindow::onMapNeedsRedrawing() { - redrawMapScene(); -} - -void MainWindow::onLayoutNeedsRedrawing() { - redrawLayoutScene(); -} - void MainWindow::onMapLoaded(Map *map) { connect(map, &Map::modified, [this, map] { this->markSpecificMapEdited(map); }); } -// TODO: editor->layout below? and redrawLayoutScene? void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) { // If saved tilesets are currently in-use, update them and redraw // Otherwise overwrite the cache for the saved tileset bool updated = false; - if (primaryTilesetLabel == this->editor->map->layout->tileset_primary_label) { + if (primaryTilesetLabel == this->editor->layout->tileset_primary_label) { this->editor->updatePrimaryTileset(primaryTilesetLabel, true); Scripting::cb_TilesetUpdated(primaryTilesetLabel); updated = true; } else { this->editor->project->getTileset(primaryTilesetLabel, true); } - if (secondaryTilesetLabel == this->editor->map->layout->tileset_secondary_label) { + if (secondaryTilesetLabel == this->editor->layout->tileset_secondary_label) { this->editor->updateSecondaryTileset(secondaryTilesetLabel, true); Scripting::cb_TilesetUpdated(secondaryTilesetLabel); updated = true; @@ -3012,7 +2995,7 @@ void MainWindow::on_comboBox_PrimaryTileset_currentTextChanged(const QString &ti { if (editor->project->primaryTilesetLabels.contains(tilesetLabel) && editor->layout) { editor->updatePrimaryTileset(tilesetLabel); - redrawLayoutScene(); + redrawMapScene(); on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value()); updateTilesetEditor(); prefab.updatePrefabUi(editor->layout); @@ -3024,7 +3007,7 @@ void MainWindow::on_comboBox_SecondaryTileset_currentTextChanged(const QString & { if (editor->project->secondaryTilesetLabels.contains(tilesetLabel) && editor->layout) { editor->updateSecondaryTileset(tilesetLabel); - redrawLayoutScene(); + redrawMapScene(); on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value()); updateTilesetEditor(); prefab.updatePrefabUi(editor->layout); @@ -3289,7 +3272,7 @@ void MainWindow::reloadScriptEngine() { // Lying to the scripts here, simulating a project reload Scripting::cb_ProjectOpened(projectConfig.projectDir); if (editor && editor->map) - Scripting::cb_MapOpened(editor->map->name); + Scripting::cb_MapOpened(editor->map->name); // TODO: API should have equivalent for layout } void MainWindow::on_pushButton_AddCustomHeaderField_clicked() diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index 5df7fc589..ef260390d 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -231,7 +231,7 @@ void MainWindow::setDimensions(int width, int height) { return; this->editor->layout->setDimensions(width, height); this->tryCommitMapChanges(true); - this->onMapNeedsRedrawing(); + this->redrawMapScene(); } void MainWindow::setWidth(int width) { @@ -241,7 +241,7 @@ void MainWindow::setWidth(int width) { return; this->editor->layout->setDimensions(width, this->editor->layout->getHeight()); this->tryCommitMapChanges(true); - this->onMapNeedsRedrawing(); + this->redrawMapScene(); } void MainWindow::setHeight(int height) { @@ -251,7 +251,7 @@ void MainWindow::setHeight(int height) { return; this->editor->layout->setDimensions(this->editor->layout->getWidth(), height); this->tryCommitMapChanges(true); - this->onMapNeedsRedrawing(); + this->redrawMapScene(); } //===================== @@ -301,7 +301,7 @@ void MainWindow::setBorderDimensions(int width, int height) { return; this->editor->layout->setBorderDimensions(width, height); this->tryCommitMapChanges(true); - this->onMapNeedsRedrawing(); + this->redrawMapScene(); } void MainWindow::setBorderWidth(int width) { @@ -311,7 +311,7 @@ void MainWindow::setBorderWidth(int width) { return; this->editor->layout->setBorderDimensions(width, this->editor->layout->getBorderHeight()); this->tryCommitMapChanges(true); - this->onMapNeedsRedrawing(); + this->redrawMapScene(); } void MainWindow::setBorderHeight(int height) { @@ -321,7 +321,7 @@ void MainWindow::setBorderHeight(int height) { return; this->editor->layout->setBorderDimensions(this->editor->layout->getBorderWidth(), height); this->tryCommitMapChanges(true); - this->onMapNeedsRedrawing(); + this->redrawMapScene(); } //====================== From 785ac958a519706bbd373b0b98b0ad17b58e9a08 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 29 Oct 2024 20:09:01 -0400 Subject: [PATCH 61/70] Fix crash when file watcher message triggers --- include/mainwindow.h | 1 + include/project.h | 5 +---- src/mainwindow.cpp | 47 ++++++++++++++++++++++++++++++++++++++------ src/project.cpp | 41 +------------------------------------- 4 files changed, 44 insertions(+), 50 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 986036d6c..160c138a6 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -366,6 +366,7 @@ private slots: void scrollMapListToCurrentMap(MapTree *list); void scrollMapListToCurrentLayout(MapTree *list); void resetMapListFilters(); + void showFileWatcherWarning(QString filepath); QString getExistingDirectory(QString); bool openProject(QString dir, bool initial = false); bool closeProject(); diff --git a/include/project.h b/include/project.h index 6782769be..07d6dcab9 100644 --- a/include/project.h +++ b/include/project.h @@ -88,8 +88,6 @@ class Project : public QObject void set_root(QString); - void initSignals(); - void clearMapCache(); void clearTilesetCache(); void clearMapLayouts(); @@ -267,8 +265,7 @@ class Project : public QObject static int max_object_events; signals: - void reloadProject(); - void uncheckMonitorFilesAction(); + void fileChanged(QString filepath); void mapLoaded(Map *map); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index bd69d464c..6e0f91853 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -602,13 +602,8 @@ bool MainWindow::openProject(QString dir, bool initial) { // Create the project auto project = new Project(editor); project->set_root(dir); - QObject::connect(project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered); + QObject::connect(project, &Project::fileChanged, this, &MainWindow::showFileWatcherWarning); QObject::connect(project, &Project::mapLoaded, this, &MainWindow::onMapLoaded); - QObject::connect(project, &Project::uncheckMonitorFilesAction, [this]() { - porymapConfig.monitorFiles = false; - if (this->preferenceEditor) - this->preferenceEditor->updateFields(); - }); this->editor->setProject(project); // Make sure project looks reasonable before attempting to load it @@ -761,6 +756,46 @@ void MainWindow::openSubWindow(QWidget * window) { } } +void MainWindow::showFileWatcherWarning(QString filepath) { + if (!porymapConfig.monitorFiles || !isProjectOpen()) + return; + + Project *project = this->editor->project; + if (project->modifiedFileTimestamps.contains(filepath)) { + if (QDateTime::currentMSecsSinceEpoch() < project->modifiedFileTimestamps[filepath]) { + return; + } + project->modifiedFileTimestamps.remove(filepath); + } + + static bool showing = false; + if (showing) return; + + QMessageBox notice(this); + notice.setText("File Changed"); + notice.setInformativeText(QString("The file %1 has changed on disk. Would you like to reload the project?") + .arg(filepath.remove(project->root + "/"))); + notice.setStandardButtons(QMessageBox::No | QMessageBox::Yes); + notice.setDefaultButton(QMessageBox::No); + notice.setIcon(QMessageBox::Question); + + QCheckBox showAgainCheck("Do not ask again."); + notice.setCheckBox(&showAgainCheck); + + showing = true; + int choice = notice.exec(); + if (choice == QMessageBox::Yes) { + on_action_Reload_Project_triggered(); + } else if (choice == QMessageBox::No) { + if (showAgainCheck.isChecked()) { + porymapConfig.monitorFiles = false; + if (this->preferenceEditor) + this->preferenceEditor->updateFields(); + } + } + showing = false; +} + QString MainWindow::getExistingDirectory(QString dir) { return FileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly); } diff --git a/src/project.cpp b/src/project.cpp index f3c02ecb9..314503f46 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -38,7 +38,7 @@ int Project::max_object_events = 64; Project::Project(QObject *parent) : QObject(parent) { - initSignals(); + QObject::connect(&this->fileWatcher, &QFileSystemWatcher::fileChanged, this, &Project::fileChanged); } Project::~Project() @@ -49,45 +49,6 @@ Project::~Project() clearEventGraphics(); } -void Project::initSignals() { - // detect changes to specific filepaths being monitored - QObject::connect(&fileWatcher, &QFileSystemWatcher::fileChanged, [this](QString changed){ - if (!porymapConfig.monitorFiles) return; - if (modifiedFileTimestamps.contains(changed)) { - if (QDateTime::currentMSecsSinceEpoch() < modifiedFileTimestamps[changed]) { - return; - } - modifiedFileTimestamps.remove(changed); - } - - static bool showing = false; - if (showing) return; - - QMessageBox notice(this->parentWidget()); - notice.setText("File Changed"); - notice.setInformativeText(QString("The file %1 has changed on disk. Would you like to reload the project?") - .arg(changed.remove(this->root + "/"))); - notice.setStandardButtons(QMessageBox::No | QMessageBox::Yes); - notice.setDefaultButton(QMessageBox::No); - notice.setIcon(QMessageBox::Question); - - QCheckBox showAgainCheck("Do not ask again."); - notice.setCheckBox(&showAgainCheck); - - showing = true; - int choice = notice.exec(); - if (choice == QMessageBox::Yes) { - emit reloadProject(); - } else if (choice == QMessageBox::No) { - if (showAgainCheck.isChecked()) { - porymapConfig.monitorFiles = false; - emit uncheckMonitorFilesAction(); - } - } - showing = false; - }); -} - void Project::set_root(QString dir) { this->root = dir; FileDialog::setDirectory(dir); From b89c1ddc80f013ac9ee99f38b8add3d74b33d405 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 29 Oct 2024 21:51:05 -0400 Subject: [PATCH 62/70] Show unsaved changes warning for map list and layout-only edits --- include/core/map.h | 2 +- include/core/maplayout.h | 2 +- include/project.h | 3 +++ src/core/map.cpp | 2 +- src/core/maplayout.cpp | 2 +- src/mainwindow.cpp | 16 ++++------------ src/project.cpp | 25 +++++++++++++++++++++++-- src/ui/maplistmodels.cpp | 1 + 8 files changed, 35 insertions(+), 18 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index 66aa00084..acc52d908 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -101,7 +101,7 @@ class Map : public QObject QUndoStack editHistory; void modify(); void clean(); - bool hasUnsavedChanges(); + bool hasUnsavedChanges() const; void pruneEditHistory(); private: diff --git a/include/core/maplayout.h b/include/core/maplayout.h index cdd3b5d6b..b617002fa 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -104,7 +104,7 @@ class Layout : public QObject { void clearBorderCache(); void cacheBorder(); - bool hasUnsavedChanges(); + bool hasUnsavedChanges() const; bool layoutBlockChanged(int i, const Blockdata &cache); diff --git a/include/project.h b/include/project.h index 07d6dcab9..39c492bbb 100644 --- a/include/project.h +++ b/include/project.h @@ -144,6 +144,9 @@ class Project : public QObject int appendMapsec(QString name); + bool hasUnsavedChanges(); + bool hasUnsavedDataChanges = false; + QSet getTopLevelMapFields(); bool loadMapData(Map*); bool readMapLayouts(); diff --git a/src/core/map.cpp b/src/core/map.cpp index 8067b9a74..2a7d96dcc 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -256,7 +256,7 @@ void Map::clean() { this->hasUnsavedDataChanges = false; } -bool Map::hasUnsavedChanges() { +bool Map::hasUnsavedChanges() const { return !editHistory.isClean() || this->layout->hasUnsavedChanges() || hasUnsavedDataChanges || !isPersistedToFile; } diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 9e283e264..34033ac55 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -418,6 +418,6 @@ QPixmap Layout::getLayoutItemPixmap() { return this->layoutItem ? this->layoutItem->pixmap() : QPixmap(); } -bool Layout::hasUnsavedChanges() { +bool Layout::hasUnsavedChanges() const { return !this->editHistory.isClean(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6e0f91853..9bac433a3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1427,6 +1427,8 @@ void MainWindow::mapListAddGroup() { // TODO: Pull this all out into a custom window. Connect that to an action in the main menu as well. // (or, re-use the new map dialog with some tweaks) +// TODO: This needs to take the same default settings you would get for a new map (tilesets, dimensions, etc.) +// and initialize it with the same fill settings (default metatile/collision/elevation, default border) void MainWindow::mapListAddLayout() { if (!editor || !editor->project) return; @@ -1458,7 +1460,6 @@ void MainWindow::mapListAddLayout() { errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }"); QString errorMessage; - // TODO: Select default tilesets QComboBox *primaryCombo = new QComboBox(&dialog); primaryCombo->addItems(this->editor->project->primaryTilesetLabels); QComboBox *secondaryCombo = new QComboBox(&dialog); @@ -1642,6 +1643,7 @@ void MainWindow::onNewMapCreated() { logInfo(QString("Created a new map named %1.").arg(newMapName)); + // TODO: Creating a new map shouldn't be automatically saved editor->project->saveMap(newMap); editor->project->saveAllDataStructures(); @@ -3496,17 +3498,7 @@ bool MainWindow::closeProject() { if (!isProjectOpen()) return true; - // Check loaded maps for unsaved changes - // TODO: This needs to check for unsaved changes in layouts too. - bool unsavedChanges = false; - for (auto map : editor->project->mapCache.values()) { - if (map && map->hasUnsavedChanges()) { - unsavedChanges = true; - break; - } - } - - if (unsavedChanges) { + if (this->editor->project->hasUnsavedChanges()) { QMessageBox::StandardButton result = QMessageBox::question( this, "porymap", "The project has been modified, save changes?", QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); diff --git a/src/project.cpp b/src/project.cpp index 314503f46..e7a9beeba 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -484,7 +484,7 @@ bool Project::loadMapLayout(Map* map) { return false; } - if (map->hasUnsavedChanges() || map->layout->hasUnsavedChanges()) { + if (map->hasUnsavedChanges()) { return true; } else { return loadLayout(map->layout); @@ -1463,6 +1463,7 @@ void Project::saveAllDataStructures() { saveMapConstantsHeader(); saveWildMonData(); saveConfig(); + this->hasUnsavedDataChanges = false; } void Project::saveConfig() { @@ -2293,7 +2294,6 @@ QString Project::getEmptyMapsecName() { // This function assumes a valid and unique name. // Will return the new index. -// TODO: We're not currently tracking map/layout agonstic changes like this as unsaved, so there's no warning if you close the project after doing this. int Project::appendMapsec(QString name) { const QString emptyMapsecName = getEmptyMapsecName(); int newMapsecValue = mapSectionValueToName.isEmpty() ? 0 : mapSectionValueToName.lastKey(); @@ -2308,6 +2308,7 @@ int Project::appendMapsec(QString name) { this->mapSectionNameToValue[name] = newMapsecValue; this->mapSectionValueToName[newMapsecValue] = name; + this->hasUnsavedDataChanges = true; return newMapsecValue; } @@ -2993,3 +2994,23 @@ void Project::applyParsedLimits() { projectConfig.collisionSheetHeight = qMin(projectConfig.collisionSheetHeight, Block::getMaxElevation() + 1); projectConfig.collisionSheetWidth = qMin(projectConfig.collisionSheetWidth, Block::getMaxCollision() + 1); } + +bool Project::hasUnsavedChanges() { + if (this->hasUnsavedDataChanges) + return true; + + // Check layouts for unsaved changes + for (auto i = this->mapLayouts.constBegin(); i != this->mapLayouts.constEnd(); i++) { + auto map = i.value(); + if (map && map->hasUnsavedChanges()) + return true; + } + + // Check loaded maps for unsaved changes + for (auto i = this->mapCache.constBegin(); i != this->mapCache.constEnd(); i++) { + auto layout = i.value(); + if (layout && layout->hasUnsavedChanges()) + return true; + } + return false; +} diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index e9fbaa1f8..462978920 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -214,6 +214,7 @@ void MapGroupModel::updateProject() { this->project->mapGroups = mapGroups; this->project->groupedMapNames = groupedMapNames; this->project->mapNames = mapNames; + this->project->hasUnsavedDataChanges = true; } QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex, QStandardItem *group) { From 23e094d850ba875fee0de4a8b2a70e1c846aae4f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 29 Oct 2024 22:18:16 -0400 Subject: [PATCH 63/70] Update map list delete functionality --- include/mainwindow.h | 4 +- include/ui/maplistmodels.h | 18 ++-- include/ui/newmappopup.h | 2 +- src/mainwindow.cpp | 163 ++++++++++++------------------------- src/project.cpp | 8 +- src/ui/maplistmodels.cpp | 56 +++++++++++-- src/ui/newmappopup.cpp | 8 +- 7 files changed, 127 insertions(+), 132 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 160c138a6..ea1c62dec 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -383,9 +383,6 @@ private slots: void mapListAddGroup(); void mapListAddLayout(); void mapListAddArea(); - void mapListRemoveGroup(); - void mapListRemoveArea(); - void mapListRemoveLayout(); void openMapListItem(const QModelIndex &index); void saveMapListTab(int index); @@ -424,6 +421,7 @@ private slots: void redrawMetatileSelection(); void scrollMetatileSelectorToSelection(); MapListToolBar* getCurrentMapListToolBar(); + MapTree* getCurrentMapList(); QObjectList shortcutableObjects() const; void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 8d00c4927..fbcd97106 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -26,8 +26,12 @@ class MapTree : public QTreeView { MapTree(QWidget *parent) : QTreeView(parent) { this->setDropIndicatorShown(true); this->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + this->setFocusPolicy(Qt::StrongFocus); } +protected: + virtual void keyPressEvent(QKeyEvent *event) override; + public slots: void removeSelected(); }; @@ -61,6 +65,9 @@ class MapListModel : public QStandardItemModel { ~MapListModel() { } virtual QModelIndex indexOf(QString id) const = 0; + virtual void removeFolder(int index) = 0; + virtual void removeItem(const QModelIndex &index); + virtual QStandardItem *getItem(const QModelIndex &index) const = 0; }; class MapGroupModel : public MapListModel { @@ -87,9 +94,9 @@ class MapGroupModel : public MapListModel { QStandardItem *insertGroupItem(QString groupName); QStandardItem *insertMapItem(QString mapName, QString groupName); - void removeGroup(int groupIndex); + virtual void removeFolder(int index) override; - QStandardItem *getItem(const QModelIndex &index) const; + virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString mapName) const override; void initialize(); @@ -130,9 +137,9 @@ class MapAreaModel : public MapListModel { QStandardItem *insertAreaItem(QString areaName); QStandardItem *insertMapItem(QString mapName, QString areaName, int groupIndex); - void removeArea(int groupIndex); + virtual void removeFolder(int index) override; - QStandardItem *getItem(const QModelIndex &index) const; + virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString mapName) const override; void initialize(); @@ -170,8 +177,9 @@ class LayoutTreeModel : public MapListModel { QStandardItem *insertLayoutItem(QString layoutId); QStandardItem *insertMapItem(QString mapName, QString layoutId); + virtual void removeFolder(int index) override; - QStandardItem *getItem(const QModelIndex &index) const; + virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString layoutName) const override; void initialize(); diff --git a/include/ui/newmappopup.h b/include/ui/newmappopup.h index 66a15a919..f160876a0 100644 --- a/include/ui/newmappopup.h +++ b/include/ui/newmappopup.h @@ -24,7 +24,7 @@ class NewMapPopup : public QMainWindow QString layoutId; void init(); void initUi(); - void init(int tabIndex, QVariant data); + void init(int tabIndex, QString data); void init(Layout *); static void setDefaultSettings(Project *project); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9bac433a3..df62341af 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -153,10 +153,11 @@ void MainWindow::initExtraShortcuts() { shortcutDuplicate_Events->setObjectName("shortcutDuplicate_Events"); shortcutDuplicate_Events->setWhatsThis("Duplicate Selected Event(s)"); - auto *shortcutDelete_Object = new Shortcut( + // TODO: Reimplement this using keyPressEvent on the relevant widgets. Otherwise it steals the key event from anything else trying to use delete. + /*auto *shortcutDelete_Object = new Shortcut( {QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(onDeleteKeyPressed())); shortcutDelete_Object->setObjectName("shortcutDelete_Object"); - shortcutDelete_Object->setWhatsThis("Delete Selected Item(s)"); + shortcutDelete_Object->setWhatsThis("Delete Selected Item(s)");*/ auto *shortcutToggle_Border = new Shortcut(QKeySequence(), ui->checkBox_ToggleBorder, SLOT(toggle())); shortcutToggle_Border->setObjectName("shortcutToggle_Border"); @@ -874,11 +875,6 @@ bool MainWindow::setMap(QString map_name) { return false; } - // TODO: Redundant? - if (editor->map && !editor->map->name.isNull()) { - ui->mapList->setExpanded(groupListProxyModel->mapFromSource(mapGroupModel->indexOf(map_name)), false); - } - setLayoutOnlyMode(false); this->lastSelectedEvent.clear(); @@ -1301,11 +1297,7 @@ void MainWindow::scrollMapList(MapTree *list, QString itemName) { if (!list || itemName.isEmpty()) return; auto model = static_cast(list->model()); - if (!model) - return; auto sourceModel = static_cast(model->sourceModel()); - if (!sourceModel) - return; QModelIndex sourceIndex = sourceModel->indexOf(itemName); if (!sourceIndex.isValid()) return; @@ -1332,66 +1324,53 @@ void MainWindow::scrollMapListToCurrentLayout(MapTree *list) { } void MainWindow::onOpenMapListContextMenu(const QPoint &point) { - QStandardItemModel *model; - int dataRole; - FilterChildrenProxyModel *proxy; - QTreeView *list; - QString actionText; - - int currentTab = ui->mapListContainer->currentIndex(); - - switch (currentTab) { - case MapListTab::Groups: - model = this->mapGroupModel; - dataRole = MapListUserRoles::GroupRole; - proxy = this->groupListProxyModel; - list = this->ui->mapList; - actionText = "Add New Map to Group"; - break; - case MapListTab::Areas: - model = this->mapAreaModel; - dataRole = Qt::UserRole; - proxy = this->areaListProxyModel; - list = this->ui->areaList; - actionText = "Add New Map to Area"; - break; - case MapListTab::Layouts: - model = this->layoutTreeModel; - dataRole = Qt::UserRole; - proxy = this->layoutListProxyModel; - list = this->ui->layoutList; - actionText = "Add New Map with Layout"; - break; - } - - QModelIndex index = proxy->mapToSource(list->indexAt(point)); - if (!index.isValid()) { - return; - } - - QStandardItem *selectedItem = model->itemFromIndex(index); + // Get selected item from list + auto list = getCurrentMapList(); + if (!list) return; + auto model = static_cast(list->model()); + QModelIndex index = model->mapToSource(list->indexAt(point)); + if (!index.isValid()) return; + auto sourceModel = static_cast(model->sourceModel()); + QStandardItem *selectedItem = sourceModel->itemFromIndex(index); + const QString itemType = selectedItem->data(MapListUserRoles::TypeRole).toString(); + const QString itemName = selectedItem->data(Qt::UserRole).toString(); - if (selectedItem->parent()) { - // TODO: Right-click delete on maps? - return; + QMenu menu(this); + QAction* addToFolderAction = nullptr; + QAction* deleteFolderAction = nullptr; + if (itemType == "map_name") { + // Right-clicking on a map. + // TODO: Add action to delete map once deleting maps is supported + } else if (itemType == "map_group") { + // Right-clicking on a map group folder + addToFolderAction = menu.addAction("Add New Map to Group"); + deleteFolderAction = menu.addAction("Delete Map Group"); + } else if (itemType == "map_section") { + // Right-clicking on an MAPSEC folder + addToFolderAction = menu.addAction("Add New Map to Area"); + } else if (itemType == "map_layout") { + // Right-clicking on a map layout + addToFolderAction = menu.addAction("Add New Map with Layout"); + } + + if (addToFolderAction) { + connect(addToFolderAction, &QAction::triggered, [this, itemName] { + openNewMapPopupWindow(); + this->newMapPrompt->init(ui->mapListContainer->currentIndex(), itemName); + }); } - - QVariant itemData = selectedItem->data(dataRole); - if (!itemData.isValid()) { - return; + if (deleteFolderAction) { + connect(deleteFolderAction, &QAction::triggered, [sourceModel, index] { + sourceModel->removeFolder(index.row()); + }); + if (selectedItem->hasChildren()){ + // TODO: No support for deleting maps, so you may only delete folders if they don't contain any maps. + deleteFolderAction->setEnabled(false); + } } - QMenu menu(this); - QActionGroup actions(&menu); - actions.addAction(menu.addAction(actionText))->setData(itemData); - - auto triggeredAction = menu.exec(QCursor::pos()); - if (!triggeredAction) - return; - - // At the moment all the actions do the same thing (add new map/layout). - openNewMapPopupWindow(); - this->newMapPrompt->init(currentTab, triggeredAction->data()); + if (menu.actions().length() != 0) + menu.exec(QCursor::pos()); } void MainWindow::mapListAddGroup() { @@ -1589,49 +1568,6 @@ void MainWindow::mapListAddArea() { } } -// TODO: Connect to right-click on map group folder in list -void MainWindow::mapListRemoveGroup() { - QItemSelectionModel *selectionModel = this->ui->mapList->selectionModel(); - if (selectionModel->hasSelection()) { - QModelIndexList selectedIndexes = selectionModel->selectedRows(); - for (QModelIndex proxyIndex : selectedIndexes) { - QModelIndex index = this->groupListProxyModel->mapToSource(proxyIndex); - QStandardItem *item = this->mapGroupModel->getItem(index)->child(index.row(), index.column()); - if (!item) continue; - QString type = item->data(MapListUserRoles::TypeRole).toString(); - if (type == "map_group" && !item->hasChildren()) { - QString groupName = item->data(Qt::UserRole).toString(); - // delete empty group - this->mapGroupModel->removeGroup(index.row()); - } - } - } -} - -// TODO: Decide what to do about this. Currently unused. -void MainWindow::mapListRemoveArea() { - QItemSelectionModel *selectionModel = this->ui->areaList->selectionModel(); - if (selectionModel->hasSelection()) { - QModelIndexList selectedIndexes = selectionModel->selectedRows(); - for (QModelIndex proxyIndex : selectedIndexes) { - QModelIndex index = this->areaListProxyModel->mapToSource(proxyIndex); - QStandardItem *item = this->mapAreaModel->getItem(index)->child(index.row(), index.column()); - if (!item) continue; - QString type = item->data(MapListUserRoles::TypeRole).toString(); - if (type == "map_section" && !item->hasChildren()) { - QString groupName = item->data(Qt::UserRole).toString(); - // delete empty section - this->mapAreaModel->removeArea(index.row()); - } - } - } -} - -// TODO: Connect to right-click on layout -void MainWindow::mapListRemoveLayout() { - // TODO: consider this in the future -} - void MainWindow::onNewMapCreated() { QString newMapName = this->newMapPrompt->map->name; int newMapGroup = this->newMapPrompt->group; @@ -3186,6 +3122,13 @@ MapListToolBar* MainWindow::getCurrentMapListToolBar() { } } +MapTree* MainWindow::getCurrentMapList() { + auto toolbar = getCurrentMapListToolBar(); + if (toolbar) + return toolbar->list(); + return nullptr; +} + // Clear the search filters on all the map lists. // When the search filter is cleared the map lists will (if possible) display the currently-selected map/layout. void MainWindow::resetMapListFilters() { diff --git a/src/project.cpp b/src/project.cpp index e7a9beeba..657bd89c9 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -3001,15 +3001,15 @@ bool Project::hasUnsavedChanges() { // Check layouts for unsaved changes for (auto i = this->mapLayouts.constBegin(); i != this->mapLayouts.constEnd(); i++) { - auto map = i.value(); - if (map && map->hasUnsavedChanges()) + auto layout = i.value(); + if (layout && layout->hasUnsavedChanges()) return true; } // Check loaded maps for unsaved changes for (auto i = this->mapCache.constBegin(); i != this->mapCache.constEnd(); i++) { - auto layout = i.value(); - if (layout && layout->hasUnsavedChanges()) + auto map = i.value(); + if (map && map->hasUnsavedChanges()) return true; } return false; diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 462978920..af8149d8c 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -15,6 +15,45 @@ void MapTree::removeSelected() { } } +void MapTree::keyPressEvent(QKeyEvent *event) { + if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { + // Delete selected items in the tree + auto selectionModel = this->selectionModel(); + if (!selectionModel->hasSelection()) + return; + + auto model = static_cast(this->model()); + auto sourceModel = static_cast(model->sourceModel()); + + QModelIndexList selectedIndexes = selectionModel->selectedRows(); + QList persistentIndexes; + for (const auto &index : selectedIndexes) { + persistentIndexes.append(model->mapToSource(index)); + } + for (const auto &index : persistentIndexes) { + sourceModel->removeItem(index); + } + } else { + QWidget::keyPressEvent(event); + } +} + +void MapListModel::removeItem(const QModelIndex &index) { + QStandardItem *item = this->getItem(index)->child(index.row(), index.column()); + if (!item) + return; + + const QString type = item->data(MapListUserRoles::TypeRole).toString(); + if (type == "map_name") { + // TODO: No support for deleting maps + } else { + // TODO: Because there's no support for deleting maps we can only delete empty folders + if (!item->hasChildren()) { + this->removeFolder(index.row()); + } + } +} + QWidget *GroupNameDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { @@ -244,8 +283,8 @@ QStandardItem *MapGroupModel::insertGroupItem(QString groupName) { return group; } -void MapGroupModel::removeGroup(int groupIndex) { - this->removeRow(groupIndex); +void MapGroupModel::removeFolder(int index) { + this->removeRow(index); this->updateProject(); } @@ -365,6 +404,8 @@ bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int } } +// TODO: Deleting MAPSEC support? Currently it has no limits on drag/drop etc, so editing is disabled (so delete key from the map list is ignored) +// and it has no delete action in the context menu. MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(parent) { @@ -422,9 +463,9 @@ QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, in return map; } -void MapAreaModel::removeArea(int areaIndex) { - this->removeRow(areaIndex); - this->project->mapSectionNameToValue.remove(this->project->mapSectionValueToName.take(areaIndex)); +void MapAreaModel::removeFolder(int index) { + this->removeRow(index); + this->project->mapSectionNameToValue.remove(this->project->mapSectionValueToName.take(index)); } void MapAreaModel::initialize() { @@ -583,6 +624,11 @@ QStandardItem *LayoutTreeModel::insertMapItem(QString mapName, QString layoutId) return map; } +void LayoutTreeModel::removeFolder(int) { + // TODO: Deleting layouts not supported +} + + void LayoutTreeModel::initialize() { this->layoutItems.clear(); this->mapItems.clear(); diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index a9d661da9..a9e50c93e 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -102,19 +102,19 @@ void NewMapPopup::init() { } // Creating new map by right-clicking in the map list -void NewMapPopup::init(int tabIndex, QVariant data) { +void NewMapPopup::init(int tabIndex, QString fieldName) { initUi(); switch (tabIndex) { case MapListTab::Groups: - settings.group = project->groupNames.at(data.toInt()); + settings.group = fieldName; break; case MapListTab::Areas: - settings.location = data.toString(); + settings.location = fieldName; break; case MapListTab::Layouts: this->ui->checkBox_UseExistingLayout->setCheckState(Qt::Checked); - useLayout(data.toString()); + useLayout(fieldName); break; } init(); From ab8eb7c7e4cb0370a20adf1258bf71509dc2d4df Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 31 Oct 2024 14:55:32 -0400 Subject: [PATCH 64/70] Reimplement disabled Delete key features --- include/editor.h | 2 +- include/mainwindow.h | 3 - include/ui/connectionpixmapitem.h | 12 ++-- include/ui/connectionslistitem.h | 5 +- include/ui/graphicsview.h | 9 +-- include/ui/mapview.h | 3 +- src/editor.cpp | 94 ++++++++++++++++++++++--------- src/mainwindow.cpp | 69 +---------------------- src/ui/connectionpixmapitem.cpp | 25 +++++++- src/ui/connectionslistitem.cpp | 14 +++++ src/ui/graphicsview.cpp | 8 +++ src/ui/maplistmodels.cpp | 2 - 12 files changed, 133 insertions(+), 113 deletions(-) diff --git a/include/editor.h b/include/editor.h index ad2ae6721..f5e94d288 100644 --- a/include/editor.h +++ b/include/editor.h @@ -96,7 +96,6 @@ class Editor : public QObject void renderDivingConnections(); void addConnection(MapConnection* connection); void removeConnection(MapConnection* connection); - void removeSelectedConnection(); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); void configureEncounterJSON(QWidget *); @@ -187,6 +186,7 @@ class Editor : public QObject bool selectingEvent = false; + void deleteSelectedEvents(); void shouldReselectEvents(); void scaleMapView(int); static void openInTextEditor(const QString &path, int lineNum = 0); diff --git a/include/mainwindow.h b/include/mainwindow.h index ea1c62dec..d77eaadc6 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -224,9 +224,6 @@ private slots: void on_actionMove_triggered(); void on_actionMap_Shift_triggered(); - void onDeleteKeyPressed(); - void on_toolButton_deleteObject_clicked(); - void addNewEvent(Event::Type type); void tryAddEventTab(QWidget * tab); void displayEventTabs(); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index 62eda6fe4..183f2d795 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -5,6 +5,7 @@ #include #include #include +#include class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT @@ -36,14 +37,17 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { static const int mHeight = 16; protected: - QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; - void mousePressEvent(QGraphicsSceneMouseEvent*) override; - void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override; - void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override; + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + virtual void mousePressEvent(QGraphicsSceneMouseEvent*) override; + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override; + virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override; + virtual void keyPressEvent(QKeyEvent*) override; + virtual void focusInEvent(QFocusEvent*) override; signals: void connectionItemDoubleClicked(MapConnection*); void selectionChanged(bool selected); + void deleteRequested(MapConnection*); }; #endif // CONNECTIONPIXMAPITEM_H diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index bbe0f2d31..7ba6a9d8e 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -34,11 +34,12 @@ class ConnectionsListItem : public QFrame unsigned actionId = 0; protected: - void mousePressEvent(QMouseEvent*) override; + virtual void mousePressEvent(QMouseEvent*) override; + virtual void focusInEvent(QFocusEvent*) override; + virtual void keyPressEvent(QKeyEvent*) override; signals: void selected(); - void removed(MapConnection*); void openMapClicked(MapConnection*); private slots: diff --git a/include/ui/graphicsview.h b/include/ui/graphicsview.h index c0d1592cf..92771cf7a 100644 --- a/include/ui/graphicsview.h +++ b/include/ui/graphicsview.h @@ -34,6 +34,7 @@ class ClickableGraphicsView : public NoScrollGraphicsView class Editor; +// TODO: This should just be MapView. It makes map-based assumptions, and no other class inherits GraphicsView. class GraphicsView : public QGraphicsView { public: @@ -44,10 +45,10 @@ class GraphicsView : public QGraphicsView // GraphicsView_Object object; Editor *editor; protected: - void mousePressEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void moveEvent(QMoveEvent *event); + virtual void mousePressEvent(QMouseEvent *event) override; + virtual void mouseMoveEvent(QMouseEvent *event) override; + virtual void mouseReleaseEvent(QMouseEvent *event) override; + virtual void moveEvent(QMoveEvent *event) override; }; //Q_DECLARE_METATYPE(GraphicsView) diff --git a/include/ui/mapview.h b/include/ui/mapview.h index 9176c825a..7355da9d0 100644 --- a/include/ui/mapview.h +++ b/include/ui/mapview.h @@ -73,7 +73,8 @@ class MapView : public GraphicsView private: QMap overlayMap; protected: - void drawForeground(QPainter *painter, const QRectF &rect); + virtual void drawForeground(QPainter *painter, const QRectF &rect) override; + virtual void keyPressEvent(QKeyEvent*) override; }; #endif // GRAPHICSVIEW_H diff --git a/src/editor.cpp b/src/editor.cpp index ac0f10113..86cedd5b7 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -811,6 +811,9 @@ void Editor::displayConnection(MapConnection *connection) { connect(listItem, &ConnectionsListItem::openMapClicked, this, &Editor::openConnectedMap); connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::openConnectedMap); + // Pressing the delete key on a selected connection's pixmap deletes it + connect(pixmapItem, &ConnectionPixmapItem::deleteRequested, this, &Editor::removeConnection); + // Sync the selection highlight between the list UI and the pixmap connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [=](bool selected) { listItem->setSelected(selected); @@ -869,11 +872,6 @@ void Editor::removeConnection(MapConnection *connection) { this->map->editHistory.push(new MapConnectionRemove(this->map, connection)); } -void Editor::removeSelectedConnection() { - if (selected_connection_item) - removeConnection(selected_connection_item->connection); -} - void Editor::removeConnectionPixmap(MapConnection *connection) { if (!connection) return; @@ -1257,42 +1255,42 @@ void Editor::unsetMap() { } bool Editor::setMap(QString map_name) { - if (map_name.isEmpty()) { + if (!project || map_name.isEmpty()) { return false; } unsetMap(); - if (project) { - Map *loadedMap = project->loadMap(map_name); - if (!loadedMap) { - return false; - } - - this->map = loadedMap; + Map *loadedMap = project->loadMap(map_name); + if (!loadedMap) { + return false; + } - setLayout(map->layout->id); + this->map = loadedMap; - editGroup.addStack(&map->editHistory); - editGroup.setActiveStack(&map->editHistory); + setLayout(map->layout->id); - selected_events->clear(); - if (!displayMap()) { - return false; - } - displayWildMonTables(); + editGroup.addStack(&map->editHistory); + editGroup.setActiveStack(&map->editHistory); - connect(map, &Map::openScriptRequested, this, &Editor::openScript); - connect(map, &Map::connectionAdded, this, &Editor::displayConnection); - connect(map, &Map::connectionRemoved, this, &Editor::removeConnectionPixmap); - updateSelectedEvents(); + selected_events->clear(); + if (!displayMap()) { + return false; } + displayWildMonTables(); + + connect(map, &Map::openScriptRequested, this, &Editor::openScript); + connect(map, &Map::connectionAdded, this, &Editor::displayConnection); + connect(map, &Map::connectionRemoved, this, &Editor::removeConnectionPixmap); + updateSelectedEvents(); return true; } bool Editor::setLayout(QString layoutId) { - if (layoutId.isEmpty()) return false; + if (!project || layoutId.isEmpty()) { + return false; + } this->layout = this->project->loadLayout(layoutId); @@ -2224,6 +2222,50 @@ bool Editor::eventLimitReached(Event::Type event_type) { return false; } +void Editor::deleteSelectedEvents() { + if (!this->selected_events || this->selected_events->length() == 0 || !this->map || this->editMode != EditMode::Events) + return; + + DraggablePixmapItem *nextSelectedEvent = nullptr; + QList selectedEvents; + int numDeleted = 0; + for (DraggablePixmapItem *item : *this->selected_events) { + Event::Group event_group = item->event->getEventGroup(); + if (event_group != Event::Group::Heal) { + numDeleted++; + item->event->setPixmapItem(item); + selectedEvents.append(item->event); + } + else { // don't allow deletion of heal locations + logWarn(QString("Cannot delete event of type '%1'").arg(Event::eventTypeToString(item->event->getEventType()))); + } + } + if (numDeleted) { + // Get the index for the event that should be selected after this event has been deleted. + // Select event at next smallest index when deleting a single event. + // If deleting multiple events, just let editor work out next selected. + if (numDeleted == 1) { + Event::Group event_group = selectedEvents[0]->getEventGroup(); + int index = this->map->events.value(event_group).indexOf(selectedEvents[0]); + if (index != this->map->events.value(event_group).size() - 1) + index++; + else + index--; + Event *event = nullptr; + if (index >= 0) + event = this->map->events.value(event_group).at(index); + for (QGraphicsItem *child : this->events_group->childItems()) { + DraggablePixmapItem *event_item = static_cast(child); + if (event_item->event == event) { + nextSelectedEvent = event_item; + break; + } + } + } + this->map->editHistory.push(new EventDelete(this, this->map, selectedEvents, nextSelectedEvent ? nextSelectedEvent->event : nullptr)); + } +} + void Editor::openMapScripts() const { openInTextEditor(map->getScriptsFilePath()); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index df62341af..8a1b7859d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -153,12 +153,6 @@ void MainWindow::initExtraShortcuts() { shortcutDuplicate_Events->setObjectName("shortcutDuplicate_Events"); shortcutDuplicate_Events->setWhatsThis("Duplicate Selected Event(s)"); - // TODO: Reimplement this using keyPressEvent on the relevant widgets. Otherwise it steals the key event from anything else trying to use delete. - /*auto *shortcutDelete_Object = new Shortcut( - {QKeySequence("Del"), QKeySequence("Backspace")}, this, SLOT(onDeleteKeyPressed())); - shortcutDelete_Object->setObjectName("shortcutDelete_Object"); - shortcutDelete_Object->setWhatsThis("Delete Selected Item(s)");*/ - auto *shortcutToggle_Border = new Shortcut(QKeySequence(), ui->checkBox_ToggleBorder, SLOT(toggle())); shortcutToggle_Border->setObjectName("shortcutToggle_Border"); shortcutToggle_Border->setWhatsThis("Toggle Border"); @@ -320,6 +314,7 @@ void MainWindow::initEditor() { connect(this->editor, &Editor::wildMonTableEdited, [this] { this->markMapEdited(); }); connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged); connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated); + connect(ui->toolButton_deleteObject, &QAbstractButton::clicked, this->editor, &Editor::deleteSelectedEvents); this->loadUserSettings(); @@ -857,13 +852,7 @@ bool MainWindow::userSetMap(QString map_name) { } bool MainWindow::setMap(QString map_name) { - // if map name is empty, clear & disable map ui - if (map_name.isEmpty()) { - unsetMap(); - return false; - } - - if (map_name == DYNAMIC_MAP_NAME) { + if (map_name.isEmpty() || map_name == DYNAMIC_MAP_NAME) { logInfo(QString("Cannot set map to '%1'").arg(DYNAMIC_MAP_NAME)); return false; } @@ -2585,60 +2574,6 @@ void MainWindow::on_horizontalSlider_CollisionTransparency_valueChanged(int valu this->editor->collision_item->draw(true); } -void MainWindow::onDeleteKeyPressed() { - auto tab = ui->mainTabBar->currentIndex(); - if (tab == MainTab::Events) { - on_toolButton_deleteObject_clicked(); - } else if (tab == MainTab::Connections) { - if (editor) editor->removeSelectedConnection(); - } -} - -void MainWindow::on_toolButton_deleteObject_clicked() { - if (editor && editor->selected_events) { - if (editor->selected_events->length()) { - DraggablePixmapItem *nextSelectedEvent = nullptr; - QList selectedEvents; - int numDeleted = 0; - for (DraggablePixmapItem *item : *editor->selected_events) { - Event::Group event_group = item->event->getEventGroup(); - if (event_group != Event::Group::Heal) { - numDeleted++; - item->event->setPixmapItem(item); - selectedEvents.append(item->event); - } - else { // don't allow deletion of heal locations - logWarn(QString("Cannot delete event of type '%1'").arg(Event::eventTypeToString(item->event->getEventType()))); - } - } - if (numDeleted) { - // Get the index for the event that should be selected after this event has been deleted. - // Select event at next smallest index when deleting a single event. - // If deleting multiple events, just let editor work out next selected. - if (numDeleted == 1) { - Event::Group event_group = selectedEvents[0]->getEventGroup(); - int index = editor->map->events.value(event_group).indexOf(selectedEvents[0]); - if (index != editor->map->events.value(event_group).size() - 1) - index++; - else - index--; - Event *event = nullptr; - if (index >= 0) - event = editor->map->events.value(event_group).at(index); - for (QGraphicsItem *child : editor->events_group->childItems()) { - DraggablePixmapItem *event_item = static_cast(child); - if (event_item->event == event) { - nextSelectedEvent = event_item; - break; - } - } - } - editor->map->editHistory.push(new EventDelete(editor, editor->map, selectedEvents, nextSelectedEvent ? nextSelectedEvent->event : nullptr)); - } - } - } -} - void MainWindow::on_toolButton_Paint_clicked() { if (ui->mainTabBar->currentIndex() == MainTab::Map) diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index f84120128..35e07a15c 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -9,6 +9,7 @@ ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection, int x, int connection(connection) { this->setEditable(true); + setFlag(ItemIsFocusable, true); this->basePixmap = pixmap(); this->setOrigin(x, y); } @@ -110,17 +111,20 @@ bool ConnectionPixmapItem::getEditable() { } void ConnectionPixmapItem::setSelected(bool selected) { + if (selected && !hasFocus()) { + setFocus(Qt::OtherFocusReason); + } + if (this->selected == selected) return; this->selected = selected; + this->render(); emit selectionChanged(selected); } void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) { - if (!this->getEditable()) - return; - this->setSelected(true); + setFocus(Qt::MouseFocusReason); } void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { @@ -131,3 +135,18 @@ void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) { emit connectionItemDoubleClicked(this->connection); } + +void ConnectionPixmapItem::keyPressEvent(QKeyEvent* event) { + if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { + emit deleteRequested(this->connection); + } else { + QGraphicsPixmapItem::keyPressEvent(event); + } +} + +void ConnectionPixmapItem::focusInEvent(QFocusEvent* event) { + if (!this->getEditable()) + return; + this->setSelected(true); + QGraphicsPixmapItem::focusInEvent(event); +} diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index a5b8759a3..ccdf7e6c0 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -10,6 +10,7 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec ui(new Ui::ConnectionsListItem) { ui->setupUi(this); + setFocusPolicy(Qt::StrongFocus); const QSignalBlocker blocker1(ui->comboBox_Direction); const QSignalBlocker blocker2(ui->comboBox_Map); @@ -101,3 +102,16 @@ void ConnectionsListItem::on_button_Delete_clicked() { void ConnectionsListItem::on_button_OpenMap_clicked() { emit openMapClicked(this->connection); } + +void ConnectionsListItem::focusInEvent(QFocusEvent* event) { + this->setSelected(true); + QFrame::focusInEvent(event); +} + +void ConnectionsListItem::keyPressEvent(QKeyEvent* event) { + if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { + on_button_Delete_clicked(); + } else { + QFrame::keyPressEvent(event); + } +} diff --git a/src/ui/graphicsview.cpp b/src/ui/graphicsview.cpp index fa04c0f72..a9761139a 100644 --- a/src/ui/graphicsview.cpp +++ b/src/ui/graphicsview.cpp @@ -24,6 +24,14 @@ void GraphicsView::moveEvent(QMoveEvent *event) { label_MapRulerStatus->move(mapToGlobal(QPoint(6, 6))); } +void MapView::keyPressEvent(QKeyEvent *event) { + if (editor && (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace)) { + editor->deleteSelectedEvents(); + } else { + QGraphicsView::keyPressEvent(event); + } +} + void MapView::drawForeground(QPainter *painter, const QRectF&) { for (auto i = this->overlayMap.constBegin(); i != this->overlayMap.constEnd(); i++) { i.value()->renderItems(painter); diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index af8149d8c..b375beb1c 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -404,8 +404,6 @@ bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int } } -// TODO: Deleting MAPSEC support? Currently it has no limits on drag/drop etc, so editing is disabled (so delete key from the map list is ignored) -// and it has no delete action in the context menu. MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(parent) { From f90dae0da00e6621094d960a83a39b23a41ccf13 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 31 Oct 2024 16:36:16 -0400 Subject: [PATCH 65/70] Set up map list tool bar to record setting states --- include/ui/filterchildrenproxymodel.h | 2 +- include/ui/maplisttoolbar.h | 11 ++-- src/mainwindow.cpp | 4 +- src/ui/maplisttoolbar.cpp | 74 +++++++++++++++++---------- 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/include/ui/filterchildrenproxymodel.h b/include/ui/filterchildrenproxymodel.h index d9eed7af9..507693b33 100644 --- a/include/ui/filterchildrenproxymodel.h +++ b/include/ui/filterchildrenproxymodel.h @@ -9,7 +9,7 @@ class FilterChildrenProxyModel : public QSortFilterProxyModel public: explicit FilterChildrenProxyModel(QObject *parent = nullptr); - bool toggleHideEmpty() { return this->hideEmpty = !this->hideEmpty; } + void setHideEmpty(bool hidden) { this->hideEmpty = hidden; } protected: bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const; private: diff --git a/include/ui/maplisttoolbar.h b/include/ui/maplisttoolbar.h index c66b0d80d..bf749a3e1 100644 --- a/include/ui/maplisttoolbar.h +++ b/include/ui/maplisttoolbar.h @@ -22,12 +22,15 @@ class MapListToolBar : public QFrame MapTree* list() const { return m_list; } void setList(MapTree *list); - void setEditsAllowedButtonHidden(bool hidden); + void setEditsAllowedButtonVisible(bool visible); + void setEditsAllowed(bool allowed); + void toggleEditsAllowed(); + void setEmptyFoldersVisible(bool visible); void toggleEmptyFolders(); + void expandList(); void collapseList(); - void toggleEditsAllowed(); void applyFilter(const QString &filterText); void clearFilter(); @@ -42,8 +45,8 @@ class MapListToolBar : public QFrame Ui::MapListToolBar *ui; QPointer m_list; bool m_filterLocked = false; - - void setEditsAllowed(bool allowed); + bool m_editsAllowed = false; + bool m_emptyFoldersVisible = true; }; #endif // MAPLISTTOOLBAR_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8a1b7859d..77391c3eb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -414,8 +414,8 @@ void MainWindow::initMapList() { connect(ui->layoutList, &QTreeView::customContextMenuRequested, this, &MainWindow::onOpenMapListContextMenu); // Only the groups list allows reorganizing folder contents, editing folder names, etc. - ui->mapListToolBar_Areas->setEditsAllowedButtonHidden(true); - ui->mapListToolBar_Layouts->setEditsAllowedButtonHidden(true); + ui->mapListToolBar_Areas->setEditsAllowedButtonVisible(false); + ui->mapListToolBar_Layouts->setEditsAllowedButtonVisible(false); // When map list search filter is cleared we want the current map/layout in the editor to be visible in the list. connect(ui->mapListToolBar_Groups, &MapListToolBar::filterCleared, this, &MainWindow::scrollMapListToCurrentMap); diff --git a/src/ui/maplisttoolbar.cpp b/src/ui/maplisttoolbar.cpp index 4dd26ecd3..2468c8492 100644 --- a/src/ui/maplisttoolbar.cpp +++ b/src/ui/maplisttoolbar.cpp @@ -4,18 +4,32 @@ #include +/* + TODO: The button states for each tool bar (just the two toggleable buttons, hide empty folders and allow editing) + should be saved in the config. This will be cleaner/easier once the config is JSON, so holding off on that for now. +*/ + MapListToolBar::MapListToolBar(QWidget *parent) : QFrame(parent) , ui(new Ui::MapListToolBar) { ui->setupUi(this); - connect(ui->button_ToggleEmptyFolders, &QAbstractButton::clicked, this, &MapListToolBar::toggleEmptyFolders); + ui->button_ToggleEmptyFolders->setChecked(!m_emptyFoldersVisible); + ui->button_ToggleEdit->setChecked(m_editsAllowed); + connect(ui->button_AddFolder, &QAbstractButton::clicked, this, &MapListToolBar::addFolderClicked); // TODO: Tool tip connect(ui->button_ExpandAll, &QAbstractButton::clicked, this, &MapListToolBar::expandList); connect(ui->button_CollapseAll, &QAbstractButton::clicked, this, &MapListToolBar::collapseList); connect(ui->button_ToggleEdit, &QAbstractButton::clicked, this, &MapListToolBar::toggleEditsAllowed); connect(ui->lineEdit_filterBox, &QLineEdit::textChanged, this, &MapListToolBar::applyFilter); + connect(ui->button_ToggleEmptyFolders, &QAbstractButton::clicked, [this] { + toggleEmptyFolders(); + + // Display message to let user know what just happened (if there are no empty folders visible it's not obvious). + const QString message = QString("%1 empty folders!").arg(m_emptyFoldersVisible ? "Showing" : "Hiding"); + QToolTip::showText(ui->button_ToggleEmptyFolders->mapToGlobal(QPoint(0, 0)), message); + }); } MapListToolBar::~MapListToolBar() @@ -26,16 +40,28 @@ MapListToolBar::~MapListToolBar() void MapListToolBar::setList(MapTree *list) { m_list = list; - // Sync list with current button states - setEditsAllowed(ui->button_ToggleEdit->isChecked()); - // TODO: Empty folders + // Sync list with current settings + setEditsAllowed(m_editsAllowed); + setEmptyFoldersVisible(m_emptyFoldersVisible); } -void MapListToolBar::setEditsAllowedButtonHidden(bool hidden) { - ui->button_ToggleEdit->setVisible(!hidden); +void MapListToolBar::setEditsAllowedButtonVisible(bool visible) { + ui->button_ToggleEdit->setVisible(visible); +} + +void MapListToolBar::toggleEditsAllowed() { + if (m_list) { + m_list->clearSelection(); + } + setEditsAllowed(!m_editsAllowed); } void MapListToolBar::setEditsAllowed(bool allowed) { + m_editsAllowed = allowed; + + const QSignalBlocker b(ui->button_ToggleEdit); + ui->button_ToggleEdit->setChecked(allowed); + if (!m_list) return; @@ -56,26 +82,27 @@ void MapListToolBar::setEditsAllowed(bool allowed) { } } -// TODO: Sync the UI in each of these - void MapListToolBar::toggleEmptyFolders() { - if (!m_list) - return; + setEmptyFoldersVisible(!m_emptyFoldersVisible); +} - auto model = static_cast(m_list->model()); - if (!model) - return; +void MapListToolBar::setEmptyFoldersVisible(bool visible) { + m_emptyFoldersVisible = visible; - bool hidden = model->toggleHideEmpty(); - model->setFilterRegularExpression(ui->lineEdit_filterBox->text()); + if (m_list) { + auto model = static_cast(m_list->model()); + if (model) { + model->setHideEmpty(!visible); + model->setFilterRegularExpression(ui->lineEdit_filterBox->text()); + } + } // Update tool tip to reflect what will happen if the button is pressed. - const QString toolTip = QString("%1 empty folders in the list.").arg(hidden ? "Show" : "Hide"); + const QString toolTip = QString("%1 empty folders in the list.").arg(visible ? "Hide" : "Show"); ui->button_ToggleEmptyFolders->setToolTip(toolTip); - // Display message to let user know what just happened (if there are no empty folders visible it's not obvious). - const QString message = QString("%1 empty folders!").arg(hidden ? "Hiding" : "Showing"); - QToolTip::showText(ui->button_ToggleEmptyFolders->mapToGlobal(QPoint(0, 0)), message); + const QSignalBlocker b(ui->button_ToggleEmptyFolders); + ui->button_ToggleEmptyFolders->setChecked(!visible); } void MapListToolBar::expandList() { @@ -89,15 +116,6 @@ void MapListToolBar::collapseList() { } } -// TODO: Save this state in porymapConfig? -// TODO: This isn't actually toggling anything, it's just updating based on the button -void MapListToolBar::toggleEditsAllowed() { - if (m_list) { - m_list->clearSelection(); - } - setEditsAllowed(ui->button_ToggleEdit->isChecked()); -} - void MapListToolBar::applyFilter(const QString &filterText) { if (!m_list || m_filterLocked) return; From 7d890312733547605e450a604b8e27b8e258d032 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 4 Nov 2024 20:55:31 -0500 Subject: [PATCH 66/70] Resolve warnings and low-hanging TODO items --- forms/maplisttoolbar.ui | 7 ++++-- include/mainwindow.h | 2 -- include/ui/maplistmodels.h | 1 - src/mainwindow.cpp | 50 +++++++++++++++++++++++++------------- src/ui/maplistmodels.cpp | 7 +++--- src/ui/maplisttoolbar.cpp | 18 ++++++++------ 6 files changed, 52 insertions(+), 33 deletions(-) diff --git a/forms/maplisttoolbar.ui b/forms/maplisttoolbar.ui index 6f753ea8b..54eb48d08 100644 --- a/forms/maplisttoolbar.ui +++ b/forms/maplisttoolbar.ui @@ -31,8 +31,11 @@
+ + Add a new folder to the list. + - Add a folder to the list. + @@ -110,7 +113,7 @@ - Toggle editability of folders in the list. + If enabled, folders may be renamed and items in the list may be rearranged. diff --git a/include/mainwindow.h b/include/mainwindow.h index d77eaadc6..8e999b243 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -369,8 +369,6 @@ private slots: bool closeProject(); void showProjectOpenFailure(); - QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum); - bool setInitialMap(); void saveGlobalConfigs(); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index fbcd97106..20eb24a93 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -150,7 +150,6 @@ class MapAreaModel : public MapListModel { QMap areaItems; QMap mapItems; - // TODO: if reordering, will the item be the same? QString openMap; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 77391c3eb..0ace9fb9c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -465,7 +465,6 @@ void MainWindow::updateWindowTitle() { } else { ui->mainTabBar->setTabIcon(MainTab::Map, QIcon(QStringLiteral(":/icons/map.ico"))); } - updateMapList(); // TODO: Why is this function responsible for this } void MainWindow::markMapEdited() { @@ -479,6 +478,7 @@ void MainWindow::markSpecificMapEdited(Map* map) { if (editor && editor->map == map) updateWindowTitle(); + updateMapList(); } void MainWindow::loadUserSettings() { @@ -870,6 +870,7 @@ bool MainWindow::setMap(QString map_name) { refreshMapScene(); displayMapProperties(); updateWindowTitle(); + updateMapList(); resetMapListFilters(); connect(editor->map, &Map::modified, this, &MainWindow::markMapEdited, Qt::UniqueConnection); @@ -918,8 +919,9 @@ bool MainWindow::setLayout(QString layoutId) { unsetMap(); - // TODO: Using the 'id' instead of the layout name here is inconsistent with how we treat maps. - logInfo(QString("Setting layout to '%1'").arg(layoutId)); + // Prefer logging the name of the layout as displayed in the map list. + const QString layoutName = this->editor->project ? this->editor->project->layoutIdsToNames.value(layoutId, layoutId) : layoutId; + logInfo(QString("Setting layout to '%1'").arg(layoutName)); if (!this->editor->setLayout(layoutId)) { return false; @@ -929,6 +931,7 @@ bool MainWindow::setLayout(QString layoutId) { refreshMapScene(); updateWindowTitle(); + updateMapList(); resetMapListFilters(); connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::redrawMapScene, Qt::UniqueConnection); @@ -1241,8 +1244,6 @@ bool MainWindow::setProjectUI() { this->layoutListProxyModel->setSourceModel(this->layoutTreeModel); ui->layoutList->setModel(layoutListProxyModel); - //on_toolButton_EnableDisable_EditGroups_clicked();//TODO - return true; } @@ -1366,7 +1367,6 @@ void MainWindow::mapListAddGroup() { QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::ApplicationModal); QDialogButtonBox newItemButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); - connect(&newItemButtonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); connect(&newItemButtonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); QLineEdit *newNameEdit = new QLineEdit(&dialog); @@ -1375,15 +1375,24 @@ void MainWindow::mapListAddGroup() { static const QRegularExpression re_validChars("[A-Za-z_]+[\\w]*"); newNameEdit->setValidator(new QRegularExpressionValidator(re_validChars, newNameEdit)); + QLabel *errorMessageLabel = new QLabel(&dialog); + errorMessageLabel->setVisible(false); + errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }"); + connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ - if (!this->editor->project->groupNames.contains(newNameEdit->text())) + const QString mapGroupName = newNameEdit->text(); + if (this->editor->project->groupNames.contains(mapGroupName)) { + errorMessageLabel->setText(QString("A map group with the name '%1' already exists").arg(mapGroupName)); + errorMessageLabel->setVisible(true); + } else { dialog.accept(); - // TODO: Else display error? + } }); QFormLayout form(&dialog); form.addRow("New Group Name", newNameEdit); + form.addRow("", errorMessageLabel); form.addRow(&newItemButtonBox); if (dialog.exec() == QDialog::Accepted) { @@ -1426,7 +1435,6 @@ void MainWindow::mapListAddLayout() { QLabel *errorMessageLabel = new QLabel(&dialog); errorMessageLabel->setVisible(false); errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }"); - QString errorMessage; QComboBox *primaryCombo = new QComboBox(&dialog); primaryCombo->addItems(this->editor->project->primaryTilesetLabels); @@ -1463,28 +1471,25 @@ void MainWindow::mapListAddLayout() { connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ // verify some things - bool issue = false; + QString errorMessage; QString tryLayoutName = newNameEdit->text(); // name not empty if (tryLayoutName.isEmpty()) { errorMessage = "Name cannot be empty"; - issue = true; } // unique layout name & id else if (this->editor->project->mapLayoutsTable.contains(newId->text()) || this->editor->project->layoutIdsToNames.find(tryLayoutName) != this->editor->project->layoutIdsToNames.end()) { errorMessage = "Layout Name / ID is not unique"; - issue = true; } // from id is existing value else if (useExistingCheck->isChecked()) { if (!this->editor->project->mapLayoutsTable.contains(useExistingCombo->currentText())) { errorMessage = "Existing layout ID is not valid"; - issue = true; } } - if (issue) { + if (!errorMessage.isEmpty()) { // show error errorMessageLabel->setText(errorMessage); errorMessageLabel->setVisible(true); @@ -1532,16 +1537,24 @@ void MainWindow::mapListAddArea() { newNameDisplay->setText(prefix + text); }); + QLabel *errorMessageLabel = new QLabel(&dialog); + errorMessageLabel->setVisible(false); + errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }"); + static const QRegularExpression re_validChars("[A-Za-z_]+[\\w]*"); newNameEdit->setValidator(new QRegularExpressionValidator(re_validChars, newNameEdit)); connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ - if (!this->editor->project->mapSectionNameToValue.contains(newNameDisplay->text())) + const QString newAreaName = newNameDisplay->text(); + if (this->editor->project->mapSectionNameToValue.contains(newAreaName)){ + errorMessageLabel->setText(QString("An area with the name '%1' already exists").arg(newAreaName)); + errorMessageLabel->setVisible(true); + } else { dialog.accept(); - // TODO: Else display error? + } }); - QLabel *newNameEditLabel = new QLabel("New Map Section Name", &dialog); + QLabel *newNameEditLabel = new QLabel("New Area Name", &dialog); QLabel *newNameDisplayLabel = new QLabel("Constant Name", &dialog); newNameDisplayLabel->setEnabled(false); @@ -1549,6 +1562,7 @@ void MainWindow::mapListAddArea() { form.addRow(newNameEditLabel, newNameEdit); form.addRow(newNameDisplayLabel, newNameDisplay); + form.addRow("", errorMessageLabel); form.addRow(&newItemButtonBox); if (dialog.exec() == QDialog::Accepted) { @@ -1855,11 +1869,13 @@ void MainWindow::updateMapList() { void MainWindow::on_action_Save_Project_triggered() { editor->saveProject(); updateWindowTitle(); + updateMapList(); } void MainWindow::on_action_Save_triggered() { editor->save(); updateWindowTitle(); + updateMapList(); } void MainWindow::duplicate() { diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index b375beb1c..e4ebd82c5 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -131,7 +131,7 @@ QMimeData *MapGroupModel::mimeData(const QModelIndexList &indexes) const { return mimeData; } -bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parentIndex) { +bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int, const QModelIndex &parentIndex) { if (action == Qt::IgnoreAction) return true; @@ -154,7 +154,6 @@ bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i QByteArray encodedData = data->data("application/porymap.mapgroupmodel.group"); QDataStream stream(&encodedData, QIODevice::ReadOnly); QString groupName; - int rowCount = 1; while (!stream.atEnd()) { stream >> groupName; @@ -402,6 +401,7 @@ bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int if (QStandardItemModel::setData(index, value, role)) { this->updateProject(); } + return true; } @@ -425,7 +425,7 @@ QStandardItem *MapAreaModel::createAreaItem(QString mapsecName, int areaIndex) { return area; } -QStandardItem *MapAreaModel::createMapItem(QString mapName, int groupIndex, int mapIndex) { +QStandardItem *MapAreaModel::createMapItem(QString mapName, int, int) { QStandardItem *map = new QStandardItem; map->setText(mapName); map->setEditable(false); @@ -603,6 +603,7 @@ QStandardItem *LayoutTreeModel::createMapItem(QString mapName) { QStandardItem *LayoutTreeModel::insertLayoutItem(QString layoutId) { QStandardItem *layoutItem = this->createLayoutItem(layoutId); this->root->appendRow(layoutItem); + return layoutItem; } QStandardItem *LayoutTreeModel::insertMapItem(QString mapName, QString layoutId) { diff --git a/src/ui/maplisttoolbar.cpp b/src/ui/maplisttoolbar.cpp index 2468c8492..d03aa8384 100644 --- a/src/ui/maplisttoolbar.cpp +++ b/src/ui/maplisttoolbar.cpp @@ -117,20 +117,22 @@ void MapListToolBar::collapseList() { } void MapListToolBar::applyFilter(const QString &filterText) { - if (!m_list || m_filterLocked) + if (m_filterLocked) return; const QSignalBlocker b(ui->lineEdit_filterBox); ui->lineEdit_filterBox->setText(filterText); - auto model = static_cast(m_list->model()); - if (model) model->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption)); + if (m_list) { + auto model = static_cast(m_list->model()); + if (model) model->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption)); - if (filterText.isEmpty()) { - m_list->collapseAll(); - emit filterCleared(m_list); - } else { - m_list->expandToDepth(0); + if (filterText.isEmpty()) { + m_list->collapseAll(); + emit filterCleared(m_list); + } else { + m_list->expandToDepth(0); + } } } From d448765d631940ba094f15293cac53dc97b4ca2e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 4 Nov 2024 21:49:49 -0500 Subject: [PATCH 67/70] Read/write MAPSEC values using the region map json --- docsrc/manual/project-files.rst | 2 - include/config.h | 2 - include/core/regionmap.h | 10 +- include/core/regionmapeditcommands.h | 4 +- include/core/wildmoninfo.h | 2 +- include/project.h | 13 +-- include/ui/maplistmodels.h | 2 +- include/ui/regionmapeditor.h | 3 +- src/config.cpp | 2 - src/core/regionmap.cpp | 37 +----- src/core/regionmapeditcommands.cpp | 2 +- src/mainwindow.cpp | 4 +- src/project.cpp | 165 +++++++++++++++------------ src/scriptapi/apimap.cpp | 2 +- src/scriptapi/apiutility.cpp | 2 +- src/ui/maplistmodels.cpp | 34 ++---- src/ui/newmappopup.cpp | 4 +- src/ui/regionmapeditor.cpp | 90 ++------------- 18 files changed, 141 insertions(+), 239 deletions(-) diff --git a/docsrc/manual/project-files.rst b/docsrc/manual/project-files.rst index 30f0acc89..e4f0479b5 100644 --- a/docsrc/manual/project-files.rst +++ b/docsrc/manual/project-files.rst @@ -59,7 +59,6 @@ The filepath that Porymap expects for each file can be overridden on the ``Files include/constants/event_object_movement.h, yes, no, ``constants_obj_event_movement``, include/constants/event_objects.h, yes, no, ``constants_obj_events``, include/constants/event_bg.h, yes, no, ``constants_event_bg``, - include/constants/region_map_sections.h, yes, no, ``constants_region_map_sections``, include/constants/metatile_labels.h, yes, yes, ``constants_metatile_labels``, include/constants/metatile_behaviors.h, yes, no, ``constants_metatile_behaviors``, include/constants/species.h, yes, no, ``constants_metatile_behaviors``, for the Wild Pokémon tab @@ -122,7 +121,6 @@ In addition to these files, there are some specific symbol and macro names that ``define_map_empty``, ``UNDEFINED``, macro name after prefix for empty maps ``define_map_section_prefix``, ``MAPSEC_``, expected prefix for location macro names ``define_map_section_empty``, ``NONE``, macro name after prefix for empty region map sections - ``define_map_section_count``, ``COUNT``, macro name after prefix for total number of region map sections ``define_species_prefix``, ``SPECIES_``, expected prefix for species macro names ``regex_behaviors``, ``\bMB_``, regex to find metatile behavior macro names ``regex_obj_event_gfx``, ``\bOBJ_EVENT_GFX_``, regex to find Object Event graphics ID macro names diff --git a/include/config.h b/include/config.h index 31f7fa7fd..6b64b612c 100644 --- a/include/config.h +++ b/include/config.h @@ -213,7 +213,6 @@ enum ProjectIdentifier { define_map_empty, define_map_section_prefix, define_map_section_empty, - define_map_section_count, define_species_prefix, regex_behaviors, regex_obj_event_gfx, @@ -269,7 +268,6 @@ enum ProjectFilePath { constants_obj_event_movement, constants_obj_events, constants_event_bg, - constants_region_map_sections, constants_metatile_labels, constants_metatile_behaviors, constants_species, diff --git a/include/core/regionmap.h b/include/core/regionmap.h index bc05a84f7..822df79b3 100644 --- a/include/core/regionmap.h +++ b/include/core/regionmap.h @@ -57,8 +57,8 @@ class RegionMap : public QObject bool loadLayout(poryjson::Json); bool loadEntries(); - void setEntries(tsl::ordered_map *entries) { this->region_map_entries = entries; } - void setEntries(tsl::ordered_map entries) { *(this->region_map_entries) = entries; } + void setEntries(QMap *entries) { this->region_map_entries = entries; } + void setEntries(const QMap &entries) { *(this->region_map_entries) = entries; } void clearEntries() { this->region_map_entries->clear(); } MapSectionEntry getEntry(QString section); void setEntry(QString section, MapSectionEntry entry); @@ -114,8 +114,6 @@ class RegionMap : public QObject void setLayer(QString layer) { this->current_layer = layer; } QString getLayer() { return this->current_layer; } - QString fixCase(QString); - int padLeft() { return this->offset_left; } int padTop() { return this->offset_top; } int padRight() { return this->tilemap_width - this->layout_width - this->offset_left; } @@ -149,14 +147,12 @@ class RegionMap : public QObject const QString section_prefix; const QString default_map_section; - const QString count_map_section; signals: void mapNeedsDisplaying(); private: - // TODO: defaults needed? - tsl::ordered_map *region_map_entries = nullptr; + QMap *region_map_entries = nullptr; QString alias = ""; diff --git a/include/core/regionmapeditcommands.h b/include/core/regionmapeditcommands.h index e142c5ccf..05b12bc3b 100644 --- a/include/core/regionmapeditcommands.h +++ b/include/core/regionmapeditcommands.h @@ -153,7 +153,7 @@ class ResizeTilemap : public EditTilemap { /// ClearEntries class ClearEntries : public QUndoCommand { public: - ClearEntries(RegionMap *map, tsl::ordered_map, QUndoCommand *parent = nullptr); + ClearEntries(RegionMap *map, QMap, QUndoCommand *parent = nullptr); void undo() override; void redo() override; @@ -163,7 +163,7 @@ class ClearEntries : public QUndoCommand { private: RegionMap *map; - tsl::ordered_map entries; + QMap entries; }; #endif // REGIONMAPEDITCOMMANDS_H diff --git a/include/core/wildmoninfo.h b/include/core/wildmoninfo.h index 6c93d0d20..d0aa29dce 100644 --- a/include/core/wildmoninfo.h +++ b/include/core/wildmoninfo.h @@ -8,7 +8,7 @@ struct WildPokemon { int minLevel = 5; int maxLevel = 5; - QString species = "SPECIES_NONE"; + QString species = "SPECIES_NONE"; // TODO: Use define_species_prefix }; struct WildMonInfo { diff --git a/include/project.h b/include/project.h index 39c492bbb..c99bd05be 100644 --- a/include/project.h +++ b/include/project.h @@ -49,9 +49,6 @@ class Project : public QObject QMap layoutIdsToNames; QMap mapLayouts; QMap mapLayoutsMaster; - QMap mapSecToMapHoverName; - QMap mapSectionNameToValue; - QMap mapSectionValueToName; QMap eventGraphicsMap; QMap gfxDefines; QString defaultSong; @@ -68,6 +65,8 @@ class Project : public QObject QStringList bgEventFacingDirections; QStringList trainerTypes; QStringList globalScriptLabels; + QStringList mapSectionIdNames; + QMap regionMapEntries; QMap> metatileLabelsMap; QMap unusedMetatileLabels; QMap metatileBehaviorMap; @@ -82,9 +81,7 @@ class Project : public QObject int pokemonMaxLevel; int maxEncounterRate; bool wildEncountersLoaded; - - // For files that are read and could contain extra text - QMap extraFileText; + bool saveEmptyMapsec; void set_root(QString); @@ -142,7 +139,7 @@ class Project : public QObject bool readSpeciesIconPaths(); QMap speciesToIconPath; - int appendMapsec(QString name); + void addNewMapsec(QString name); bool hasUnsavedChanges(); bool hasUnsavedDataChanges = false; @@ -172,7 +169,7 @@ class Project : public QObject void saveConfig(); void saveMapLayouts(); void saveMapGroups(); - void saveMapSections(); + void saveRegionMapSections(); void saveWildMonData(); void saveMapConstantsHeader(); void saveHealLocations(Map*); diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 20eb24a93..3e6e95d10 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -132,7 +132,7 @@ class MapAreaModel : public MapListModel { public: void setMap(QString mapName) { this->openMap = mapName; } - QStandardItem *createAreaItem(QString areaName, int areaIndex); + QStandardItem *createAreaItem(QString areaName); QStandardItem *createMapItem(QString mapName, int areaIndex, int mapIndex); QStandardItem *insertAreaItem(QString areaName); diff --git a/include/ui/regionmapeditor.h b/include/ui/regionmapeditor.h index 3d889f881..c19416516 100644 --- a/include/ui/regionmapeditor.h +++ b/include/ui/regionmapeditor.h @@ -57,7 +57,6 @@ public slots: tsl::ordered_map region_maps; QString configFilepath; - QString mapSectionFilepath; poryjson::Json rmConfigJson; @@ -96,7 +95,7 @@ public slots: void saveConfig(); bool loadRegionMapEntries(); bool saveRegionMapEntries(); - tsl::ordered_map region_map_entries; + QMap region_map_entries; bool buildConfigDialog(); poryjson::Json configRegionMapDialog(); diff --git a/src/config.cpp b/src/config.cpp index ca6473b1c..3d604da60 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -110,7 +110,6 @@ const QMap> ProjectConfig::defaultIde {ProjectIdentifier::define_map_empty, {"define_map_empty", "UNDEFINED"}}, {ProjectIdentifier::define_map_section_prefix, {"define_map_section_prefix", "MAPSEC_"}}, {ProjectIdentifier::define_map_section_empty, {"define_map_section_empty", "NONE"}}, - {ProjectIdentifier::define_map_section_count, {"define_map_section_count", "COUNT"}}, {ProjectIdentifier::define_species_prefix, {"define_species_prefix", "SPECIES_"}}, // Regex {ProjectIdentifier::regex_behaviors, {"regex_behaviors", "\\bMB_"}}, @@ -167,7 +166,6 @@ const QMap> ProjectConfig::defaultPaths {ProjectFilePath::constants_obj_event_movement, { "constants_obj_event_movement", "include/constants/event_object_movement.h"}}, {ProjectFilePath::constants_obj_events, { "constants_obj_events", "include/constants/event_objects.h"}}, {ProjectFilePath::constants_event_bg, { "constants_event_bg", "include/constants/event_bg.h"}}, - {ProjectFilePath::constants_region_map_sections, { "constants_region_map_sections", "include/constants/region_map_sections.h"}}, {ProjectFilePath::constants_metatile_labels, { "constants_metatile_labels", "include/constants/metatile_labels.h"}}, {ProjectFilePath::constants_metatile_behaviors, { "constants_metatile_behaviors", "include/constants/metatile_behaviors.h"}}, {ProjectFilePath::constants_species, { "constants_species", "include/constants/species.h"}}, diff --git a/src/core/regionmap.cpp b/src/core/regionmap.cpp index 7dbd4c5f1..94650ccd9 100644 --- a/src/core/regionmap.cpp +++ b/src/core/regionmap.cpp @@ -19,8 +19,7 @@ using std::make_shared; RegionMap::RegionMap(Project *project) : section_prefix(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix)), - default_map_section(section_prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty)), - count_map_section(section_prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_count)) + default_map_section(project->getEmptyMapsecName()) { this->project = project; } @@ -157,7 +156,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) { for (int x = 0; x < this->layout_width; x++) { int bin_index = x + y * this->layout_width; uint8_t square_section_id = mapBinData.at(bin_index); - QString square_section_name = project->mapSectionValueToName.value(square_section_id); + QString square_section_name = project->mapSectionIdNames.value(square_section_id, this->default_map_section); LayoutSquare square; square.map_section = square_section_name; @@ -401,7 +400,7 @@ void RegionMap::saveLayout() { for (int m = 0; m < this->layout_height; m++) { for (int n = 0; n < this->layout_width; n++) { int i = n + this->layout_width * m; - data.append(this->project->mapSectionNameToValue.value(this->layouts["main"][i].map_section)); + data.append(this->project->mapSectionIdNames.indexOf(this->layouts["main"][i].map_section)); } } QFile bfile(fullPath(this->layout_path)); @@ -760,18 +759,15 @@ bool RegionMap::squareInLayout(int x, int y) { } MapSectionEntry RegionMap::getEntry(QString section) { - if (this->region_map_entries->contains(section)) - return this->region_map_entries->operator[](section); - else - return MapSectionEntry(); + return this->region_map_entries->value(section, MapSectionEntry()); } void RegionMap::setEntry(QString section, MapSectionEntry entry) { - this->region_map_entries->operator[](section) = entry; + this->region_map_entries->insert(section, entry); } void RegionMap::removeEntry(QString section) { - this->region_map_entries->erase(section); + this->region_map_entries->remove(section); } QString RegionMap::palPath() { @@ -788,27 +784,6 @@ int RegionMap::getMapSquareIndex(int x, int y) { return ((index < tilemap.length()) && (index >= 0)) ? index : 0; } -// For turning a MAPSEC_NAME into a unique identifier sMapName-style variable. -// CAPS_WITH_UNDERSCORE to CamelCase -QString RegionMap::fixCase(QString caps) { - bool big = true; - QString camel; - - static const QRegularExpression re_braced("({.*})"); - for (auto ch : caps.remove(re_braced).remove(this->section_prefix)) { - if (ch == '_' || ch == ' ') { - big = true; - continue; - } - if (big) { - camel += ch.toUpper(); - big = false; - } - else camel += ch.toLower(); - } - return camel; -} - QString RegionMap::fullPath(QString local) { return this->project->root + "/" + local; } diff --git a/src/core/regionmapeditcommands.cpp b/src/core/regionmapeditcommands.cpp index 1be247b02..7a12cbc6c 100644 --- a/src/core/regionmapeditcommands.cpp +++ b/src/core/regionmapeditcommands.cpp @@ -260,7 +260,7 @@ void ResizeTilemap::undo() { /// -ClearEntries::ClearEntries(RegionMap *map, tsl::ordered_map entries, QUndoCommand *parent) +ClearEntries::ClearEntries(RegionMap *map, QMap entries, QUndoCommand *parent) : QUndoCommand(parent) { setText("Clear Entries"); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0ace9fb9c..90b2a80cf 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1177,7 +1177,7 @@ bool MainWindow::setProjectUI() { ui->comboBox_Song->clear(); ui->comboBox_Song->addItems(project->songNames); ui->comboBox_Location->clear(); - ui->comboBox_Location->addItems(project->mapSectionValueToName.values()); + ui->comboBox_Location->addItems(project->mapSectionIdNames); ui->comboBox_PrimaryTileset->clear(); ui->comboBox_PrimaryTileset->addItems(project->primaryTilesetLabels); ui->comboBox_SecondaryTileset->clear(); @@ -1546,7 +1546,7 @@ void MainWindow::mapListAddArea() { connect(&newItemButtonBox, &QDialogButtonBox::accepted, [&](){ const QString newAreaName = newNameDisplay->text(); - if (this->editor->project->mapSectionNameToValue.contains(newAreaName)){ + if (this->editor->project->mapSectionIdNames.contains(newAreaName)){ errorMessageLabel->setText(QString("An area with the name '%1' already exists").arg(newAreaName)); errorMessageLabel->setVisible(true); } else { diff --git a/src/project.cpp b/src/project.cpp index 657bd89c9..9d87c6f40 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -708,36 +708,45 @@ void Project::saveMapGroups() { mapGroupsFile.close(); } -void Project::saveMapSections() { - QString filepath = root + "/" + projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections); +void Project::saveRegionMapSections() { + const QString filepath = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries)); + QFile file(filepath); + if (!file.open(QIODevice::WriteOnly)) { + logError(QString("Could not open '%1' for writing").arg(filepath)); + return; + } - QString text = QString("#ifndef GUARD_REGIONMAPSEC_H\n"); - text += QString("#define GUARD_REGIONMAPSEC_H\n\n"); + const QString emptyMapsecName = getEmptyMapsecName(); + OrderedJson::array mapSectionArray; + for (const auto &idName : this->mapSectionIdNames) { + // The 'empty' map section (MAPSEC_NONE) isn't normally present in the region map sections data file. + // We append this name to mapSectionIdNames ourselves if it isn't present, in which case we don't want to output data for it here. + if (!this->saveEmptyMapsec && idName == emptyMapsecName) + continue; - int longestLength = 0; - for (QString label : this->mapSectionNameToValue.keys()) { - if (label.size() > longestLength) - longestLength = label.size(); - } + OrderedJson::object mapSectionObj; + mapSectionObj["id"] = idName; - longestLength += 1; + if (this->regionMapEntries.contains(idName)) { + MapSectionEntry entry = this->regionMapEntries.value(idName); + mapSectionObj["name"] = entry.name; + mapSectionObj["x"] = entry.x; + mapSectionObj["y"] = entry.y; + mapSectionObj["width"] = entry.width; + mapSectionObj["height"] = entry.height; + } - // TODO: Maybe print as an enum now that we can? - for (int value : this->mapSectionValueToName.keys()) { - QString line = QString("#define %1 0x%2\n") - .arg(this->mapSectionValueToName[value], -1 * longestLength) - .arg(QString("%1").arg(value, 2, 16, QLatin1Char('0')).toUpper()); - text += line; + mapSectionArray.append(mapSectionObj); } - // TODO: We should maybe consider another way to update MAPSEC values in this file, in case we break anything by relocating it to the bottom of the file. - // (or alternatively keep separate strings for text before/after the MAPSEC values) - text += "\n" + this->extraFileText[projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections)] + "\n"; - - text += QString("#endif // GUARD_REGIONMAPSEC_H\n"); + OrderedJson::object object; + object["map_sections"] = mapSectionArray; ignoreWatchedFileTemporarily(filepath); - saveTextFile(filepath, text); + OrderedJson json(object); + OrderedJsonDoc jsonDoc(&json); + jsonDoc.dump(&file); + file.close(); } void Project::saveWildMonData() { @@ -1459,7 +1468,7 @@ void Project::updateLayout(Layout *layout) { void Project::saveAllDataStructures() { saveMapLayouts(); saveMapGroups(); - saveMapSections(); + saveRegionMapSections(); saveMapConstantsHeader(); saveWildMonData(); saveConfig(); @@ -2242,49 +2251,66 @@ bool Project::readFieldmapMasks() { } bool Project::readRegionMapSections() { - this->mapSectionNameToValue.clear(); - this->mapSectionValueToName.clear(); - - const QStringList regexList = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))}; - QString filename = projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections); - fileWatcher.addPath(root + "/" + filename); - this->mapSectionNameToValue = parser.readCDefinesByRegex(filename, regexList); - if (this->mapSectionNameToValue.isEmpty()) { - logError(QString("Failed to read region map sections from %1.").arg(filename)); + this->mapSectionIdNames.clear(); + this->regionMapEntries.clear(); + this->saveEmptyMapsec = false; + const QString defaultName = getEmptyMapsecName(); + const QString requiredPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix); + + QJsonDocument doc; + const QString filepath = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries)); + if (!parser.tryParseJsonFile(&doc, filepath)) { + logError(QString("Failed to read region map sections from '%1'").arg(filepath)); return false; } + fileWatcher.addPath(filepath); - for (QString defineName : this->mapSectionNameToValue.keys()) { - this->mapSectionValueToName.insert(this->mapSectionNameToValue[defineName], defineName); - } - - // extra text - QString extraText; - QString fileText = ParseUtil::readTextFile(root + "/" + filename); - QTextStream stream(&fileText); - QString currentLine; - while (stream.readLineInto(¤tLine)) { - // is this line something that porymap will output again? - if (currentLine.isEmpty()) { + QJsonArray mapSections = doc.object()["map_sections"].toArray(); + for (const auto &mapSection : mapSections) { + // For each map section, "id" is the only required field. This is the field we use + // to display the location names in various drop-downs. + QJsonObject mapSectionObj = mapSection.toObject(); + const QString idName = ParseUtil::jsonToQString(mapSectionObj["id"]); + if (!idName.startsWith(requiredPrefix)) { + logWarn(QString("Ignoring data for map section '%1'. IDs must start with the prefix '%2'").arg(idName).arg(requiredPrefix)); continue; } - // include guards - // TODO: Assuming guard name is the same across projects (it isn't) - else if (currentLine.contains("GUARD_REGIONMAPSEC_H")) { - continue; - } - // defines captured - // TODO: Regex to consider comments/extra space - else if (currentLine.contains("#define " + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))) { - continue; + + this->mapSectionIdNames.append(idName); + if (idName == defaultName) { + // If the user has data for the 'empty' MAPSEC we need to know to output it later, + // because we will otherwise add a dummy entry for this value. + this->saveEmptyMapsec = true; } - // everything else should be kept here - else { - extraText += currentLine + "\n"; + + // Map sections may have additional data indicating their position on the region map. + // If they have this data, we can add them to the region map entry list. + bool hasRegionMapData = true; + static const QSet regionMapFieldNames = { "name", "x", "y", "width", "height" }; + for (auto fieldName : regionMapFieldNames) { + if (!mapSectionObj.contains(fieldName)) { + hasRegionMapData = false; + break; + } } + if (!hasRegionMapData) + continue; + + MapSectionEntry entry; + entry.name = ParseUtil::jsonToQString(mapSectionObj["name"]); + entry.x = ParseUtil::jsonToInt(mapSectionObj["x"]); + entry.y = ParseUtil::jsonToInt(mapSectionObj["y"]); + entry.width = ParseUtil::jsonToInt(mapSectionObj["width"]); + entry.height = ParseUtil::jsonToInt(mapSectionObj["height"]); + entry.valid = true; + this->regionMapEntries[idName] = entry; } - stream.seek(0); - this->extraFileText[filename] = extraText; + + // Make sure the default name is present in the list. + if (!this->mapSectionIdNames.contains(defaultName)) { + this->mapSectionIdNames.append(defaultName); + } + return true; } @@ -2292,24 +2318,15 @@ QString Project::getEmptyMapsecName() { return projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty); } -// This function assumes a valid and unique name. -// Will return the new index. -int Project::appendMapsec(QString name) { - const QString emptyMapsecName = getEmptyMapsecName(); - int newMapsecValue = mapSectionValueToName.isEmpty() ? 0 : mapSectionValueToName.lastKey(); - - // If the user has the 'empty' MAPSEC value defined last in the list we'll shift it so that it stays last in the list. - if (this->mapSectionNameToValue.contains(emptyMapsecName) && this->mapSectionNameToValue.value(emptyMapsecName) == newMapsecValue) { - this->mapSectionNameToValue.insert(emptyMapsecName, newMapsecValue + 1); - this->mapSectionValueToName.insert(newMapsecValue + 1, emptyMapsecName); +// This function assumes a valid and unique name +void Project::addNewMapsec(QString name) { + if (!this->mapSectionIdNames.isEmpty() && this->mapSectionIdNames.last() == getEmptyMapsecName()) { + // If the default map section name (MAPSEC_NONE) is last in the list we'll keep it last in the list. + this->mapSectionIdNames.insert(this->mapSectionIdNames.length() - 1, name); + } else { + this->mapSectionIdNames.append(name); } - - // TODO: Update 'define_map_section_count'? - - this->mapSectionNameToValue[name] = newMapsecValue; - this->mapSectionValueToName[newMapsecValue] = name; this->hasUnsavedDataChanges = true; - return newMapsecValue; } // Read the constants to preserve any "unused" heal locations when writing the file later diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp index ef260390d..98478f94b 100644 --- a/src/scriptapi/apimap.cpp +++ b/src/scriptapi/apimap.cpp @@ -836,7 +836,7 @@ QString MainWindow::getLocation() { void MainWindow::setLocation(QString location) { if (!this->ui || !this->editor || !this->editor->project) return; - if (!this->editor->project->mapSectionNameToValue.contains(location)) { + if (!this->editor->project->mapSectionIdNames.contains(location)) { logError(QString("Unknown location '%1'").arg(location)); return; } diff --git a/src/scriptapi/apiutility.cpp b/src/scriptapi/apiutility.cpp index 27bd56770..e5cebc541 100644 --- a/src/scriptapi/apiutility.cpp +++ b/src/scriptapi/apiutility.cpp @@ -282,7 +282,7 @@ QList ScriptUtility::getSongNames() { QList ScriptUtility::getLocationNames() { if (!window || !window->editor || !window->editor->project) return QList(); - return window->editor->project->mapSectionNameToValue.keys(); + return window->editor->project->mapSectionIdNames; } QList ScriptUtility::getWeatherNames() { diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index e4ebd82c5..616e608ca 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -413,13 +413,12 @@ MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(par initialize(); } -QStandardItem *MapAreaModel::createAreaItem(QString mapsecName, int areaIndex) { +QStandardItem *MapAreaModel::createAreaItem(QString mapsecName) { QStandardItem *area = new QStandardItem; area->setText(mapsecName); area->setEditable(false); area->setData(mapsecName, Qt::UserRole); area->setData("map_section", MapListUserRoles::TypeRole); - area->setData(areaIndex, MapListUserRoles::GroupRole); // group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); this->areaItems.insert(mapsecName, area); return area; @@ -437,20 +436,14 @@ QStandardItem *MapAreaModel::createMapItem(QString mapName, int, int) { } QStandardItem *MapAreaModel::insertAreaItem(QString areaName) { - int newAreaIndex = this->project->appendMapsec(areaName); - QStandardItem *item = createAreaItem(areaName, newAreaIndex); - this->root->insertRow(newAreaIndex, item); - - // MAPSEC_NONE may have shifted to accomodate the new item, update it in the list. - const QString emptyMapsecName = Project::getEmptyMapsecName(); - if (this->areaItems.contains(emptyMapsecName)) - this->areaItems[emptyMapsecName]->setData(this->project->mapSectionNameToValue.value(emptyMapsecName), MapListUserRoles::GroupRole); - + this->project->addNewMapsec(areaName); + QStandardItem *item = createAreaItem(areaName); + this->root->appendRow(item); + this->sort(0, Qt::AscendingOrder); return item; } QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, int groupIndex) { - // int areaIndex = this->project->mapSectionNameToValue[areaName]; QStandardItem *area = this->areaItems[areaName]; if (!area) { return nullptr; @@ -461,21 +454,18 @@ QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, in return map; } +// Note: Not actually supported in the interface at the moment. void MapAreaModel::removeFolder(int index) { this->removeRow(index); - this->project->mapSectionNameToValue.remove(this->project->mapSectionValueToName.take(index)); + this->project->mapSectionIdNames.removeAt(index); } void MapAreaModel::initialize() { this->areaItems.clear(); this->mapItems.clear(); - this->setSortRole(MapListUserRoles::GroupRole); - // TODO: Ignore 'define_map_section_count' and/or 'define_map_section_empty'? - for (int i : this->project->mapSectionNameToValue) { - QString mapsecName = project->mapSectionValueToName.value(i); - QStandardItem *areaItem = createAreaItem(mapsecName, i); - this->root->appendRow(areaItem); + for (const auto &idName : this->project->mapSectionIdNames) { + this->root->appendRow(createAreaItem(idName)); } for (int i = 0; i < this->project->groupNames.length(); i++) { @@ -560,9 +550,7 @@ QVariant MapAreaModel::data(const QModelIndex &index, int role) const { QString type = item->data(MapListUserRoles::TypeRole).toString(); if (type == "map_section") { - return QString("[0x%1] %2") - .arg(QString("%1").arg(item->data(MapListUserRoles::GroupRole).toInt(), 2, 16, QLatin1Char('0')).toUpper()) - .arg(item->data(Qt::UserRole).toString()); + return item->data(Qt::UserRole).toString(); } } @@ -603,6 +591,7 @@ QStandardItem *LayoutTreeModel::createMapItem(QString mapName) { QStandardItem *LayoutTreeModel::insertLayoutItem(QString layoutId) { QStandardItem *layoutItem = this->createLayoutItem(layoutId); this->root->appendRow(layoutItem); + this->sort(0, Qt::AscendingOrder); return layoutItem; } @@ -644,6 +633,7 @@ void LayoutTreeModel::initialize() { this->layoutItems[layoutId]->appendRow(map); } } + this->sort(0, Qt::AscendingOrder); } QStandardItem *LayoutTreeModel::getItem(const QModelIndex &index) const { diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index a9e50c93e..261544f2b 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -34,7 +34,7 @@ void NewMapPopup::initUi() { ui->comboBox_NewMap_Group->addItems(project->groupNames); ui->comboBox_NewMap_Song->addItems(project->songNames); ui->comboBox_NewMap_Type->addItems(project->mapTypes); - ui->comboBox_NewMap_Location->addItems(project->mapSectionNameToValue.keys()); + ui->comboBox_NewMap_Location->addItems(project->mapSectionIdNames); const QSignalBlocker b(ui->comboBox_Layout); ui->comboBox_Layout->addItems(project->mapLayoutsTable); @@ -186,7 +186,7 @@ void NewMapPopup::setDefaultSettings(Project *project) { settings.primaryTilesetLabel = project->getDefaultPrimaryTilesetLabel(); settings.secondaryTilesetLabel = project->getDefaultSecondaryTilesetLabel(); settings.type = project->mapTypes.value(0, "0"); - settings.location = project->mapSectionNameToValue.keys().value(0, "0"); + settings.location = project->mapSectionIdNames.value(0, "0"); settings.song = project->defaultSong; settings.canFlyTo = false; settings.showLocationName = true; diff --git a/src/ui/regionmapeditor.cpp b/src/ui/regionmapeditor.cpp index 2a23b454a..c6485d519 100644 --- a/src/ui/regionmapeditor.cpp +++ b/src/ui/regionmapeditor.cpp @@ -29,7 +29,6 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project) : this->ui->setupUi(this); this->project = project; this->configFilepath = QString("%1/%2").arg(this->project->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_porymap_cfg)); - this->mapSectionFilepath = QString("%1/%2").arg(this->project->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries)); this->initShortcuts(); this->restoreWindowState(); } @@ -110,67 +109,13 @@ void RegionMapEditor::applyUserShortcuts() { } bool RegionMapEditor::loadRegionMapEntries() { - this->region_map_entries.clear(); - - ParseUtil parser; - QJsonDocument sectionsDoc; - if (!parser.tryParseJsonFile(§ionsDoc, this->mapSectionFilepath)) { - logError(QString("Failed to read map data from %1").arg(this->mapSectionFilepath)); - return false; - } - - // for some unknown reason, the OrderedJson class would not parse this properly - // perhaps updating nlohmann/json here would fix it, but that also requires using C++17 - QJsonObject object = sectionsDoc.object(); - - for (auto entryRef : object["map_sections"].toArray()) { - QJsonObject entryObject = entryRef.toObject(); - QString entryMapSection = ParseUtil::jsonToQString(entryObject["map_section"]); - MapSectionEntry entry; - entry.name = ParseUtil::jsonToQString(entryObject["name"]); - entry.x = ParseUtil::jsonToInt(entryObject["x"]); - entry.y = ParseUtil::jsonToInt(entryObject["y"]); - entry.width = ParseUtil::jsonToInt(entryObject["width"]); - entry.height = ParseUtil::jsonToInt(entryObject["height"]); - entry.valid = true; - this->region_map_entries[entryMapSection] = entry; - } - + this->region_map_entries = this->project->regionMapEntries; return true; } bool RegionMapEditor::saveRegionMapEntries() { - QFile sectionsFile(this->mapSectionFilepath); - if (!sectionsFile.open(QIODevice::WriteOnly)) { - logError(QString("Could not open %1 for writing").arg(this->mapSectionFilepath)); - return false; - } - - OrderedJson::object object; - OrderedJson::array mapSectionArray; - - for (auto pair : this->region_map_entries) { - QString section = pair.first; - MapSectionEntry entry = pair.second; - - OrderedJson::object entryObject; - entryObject["map_section"] = section; - entryObject["name"] = entry.name; - entryObject["x"] = entry.x; - entryObject["y"] = entry.y; - entryObject["width"] = entry.width; - entryObject["height"] = entry.height; - - mapSectionArray.append(entryObject); - } - - object["map_sections"] = mapSectionArray; - - OrderedJson sectionsJson(object); - OrderedJsonDoc jsonDoc(§ionsJson); - jsonDoc.dump(§ionsFile); - sectionsFile.close(); - + this->project->regionMapEntries = this->region_map_entries; + this->project->saveRegionMapSections(); return true; } @@ -708,7 +653,7 @@ void RegionMapEditor::displayRegionMapLayoutOptions() { this->ui->comboBox_RM_ConnectedMap->blockSignals(true); this->ui->comboBox_RM_ConnectedMap->clear(); - this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionValueToName.values()); + this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionIdNames); this->ui->comboBox_RM_ConnectedMap->blockSignals(false); this->ui->frame_RM_Options->setEnabled(true); @@ -775,7 +720,7 @@ void RegionMapEditor::displayRegionMapEntryOptions() { if (!this->region_map->layoutEnabled()) return; this->ui->comboBox_RM_Entry_MapSection->clear(); - this->ui->comboBox_RM_Entry_MapSection->addItems(this->project->mapSectionValueToName.values()); + this->ui->comboBox_RM_Entry_MapSection->addItems(this->project->mapSectionIdNames); this->ui->spinBox_RM_Entry_x->setMaximum(128); this->ui->spinBox_RM_Entry_y->setMaximum(128); this->ui->spinBox_RM_Entry_width->setMinimum(1); @@ -787,17 +732,13 @@ void RegionMapEditor::displayRegionMapEntryOptions() { void RegionMapEditor::updateRegionMapEntryOptions(QString section) { if (!this->region_map->layoutEnabled()) return; - bool isSpecialSection = (section == this->region_map->default_map_section - || section == this->region_map->count_map_section); - - bool enabled = (!isSpecialSection && this->region_map_entries.contains(section)); - + bool enabled = (section != this->region_map->default_map_section) && this->region_map_entries.contains(section); this->ui->lineEdit_RM_MapName->setEnabled(enabled); this->ui->spinBox_RM_Entry_x->setEnabled(enabled); this->ui->spinBox_RM_Entry_y->setEnabled(enabled); this->ui->spinBox_RM_Entry_width->setEnabled(enabled); this->ui->spinBox_RM_Entry_height->setEnabled(enabled); - this->ui->pushButton_entryActivate->setEnabled(!isSpecialSection); + this->ui->pushButton_entryActivate->setEnabled(section != this->region_map->default_map_section); this->ui->pushButton_entryActivate->setText(enabled ? "Remove" : "Add"); this->ui->lineEdit_RM_MapName->blockSignals(true); @@ -902,14 +843,8 @@ void RegionMapEditor::onRegionMapEntryDragged(int new_x, int new_y) { } void RegionMapEditor::onRegionMapLayoutSelectedTileChanged(int index) { - QString message = QString(); this->currIndex = index; this->region_map_layout_item->highlightedTile = index; - if (this->region_map->squareHasMap(index)) { - message = QString("\t %1").arg(this->project->mapSecToMapHoverName.value( - this->region_map->squareMapSection(index))).remove("{NAME_END}"); - } - this->ui->statusbar->showMessage(message); updateRegionMapLayoutOptions(index); this->region_map_layout_item->draw(); @@ -922,8 +857,7 @@ void RegionMapEditor::onRegionMapLayoutHoveredTileChanged(int index) { if (x >= 0 && y >= 0) { message = QString("(%1, %2)").arg(x).arg(y); if (this->region_map->squareHasMap(index)) { - message += QString("\t %1").arg(this->project->mapSecToMapHoverName.value( - this->region_map->squareMapSection(index))).remove("{NAME_END}"); + message += QString("\t %1").arg(this->region_map->squareMapSection(index)); } } this->ui->statusbar->showMessage(message); @@ -1203,10 +1137,10 @@ void RegionMapEditor::on_action_Swap_triggered() { QFormLayout form(&popup); QComboBox *oldSecBox = new QComboBox(); - oldSecBox->addItems(this->project->mapSectionValueToName.values()); + oldSecBox->addItems(this->project->mapSectionIdNames); form.addRow(new QLabel("Map Section 1:"), oldSecBox); QComboBox *newSecBox = new QComboBox(); - newSecBox->addItems(this->project->mapSectionValueToName.values()); + newSecBox->addItems(this->project->mapSectionIdNames); form.addRow(new QLabel("Map Section 2:"), newSecBox); QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup); @@ -1242,10 +1176,10 @@ void RegionMapEditor::on_action_Replace_triggered() { QFormLayout form(&popup); QComboBox *oldSecBox = new QComboBox(); - oldSecBox->addItems(this->project->mapSectionValueToName.values()); + oldSecBox->addItems(this->project->mapSectionIdNames); form.addRow(new QLabel("Old Map Section:"), oldSecBox); QComboBox *newSecBox = new QComboBox(); - newSecBox->addItems(this->project->mapSectionValueToName.values()); + newSecBox->addItems(this->project->mapSectionIdNames); form.addRow(new QLabel("New Map Section:"), newSecBox); QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup); From 06ece16b9351677b19ea29e596f5afc2683c7678 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 8 Nov 2024 13:55:50 -0500 Subject: [PATCH 68/70] Finish support for deleting MAPSEC values --- include/mainwindow.h | 1 + include/project.h | 4 +++- include/ui/maplistmodels.h | 18 +++++++++++++----- src/mainwindow.cpp | 38 +++++++++++++++++++++++++++++++------- src/project.cpp | 12 +++++++++++- src/ui/maplistmodels.cpp | 19 +++++++++---------- src/ui/newmappopup.cpp | 2 ++ 7 files changed, 70 insertions(+), 24 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 8e999b243..397a1d722 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -417,6 +417,7 @@ private slots: void scrollMetatileSelectorToSelection(); MapListToolBar* getCurrentMapListToolBar(); MapTree* getCurrentMapList(); + void refreshLocationsComboBox(); QObjectList shortcutableObjects() const; void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false); diff --git a/include/project.h b/include/project.h index c99bd05be..efb7db7c6 100644 --- a/include/project.h +++ b/include/project.h @@ -139,7 +139,8 @@ class Project : public QObject bool readSpeciesIconPaths(); QMap speciesToIconPath; - void addNewMapsec(QString name); + void addNewMapsec(const QString &name); + void removeMapsec(const QString &name); bool hasUnsavedChanges(); bool hasUnsavedDataChanges = false; @@ -266,6 +267,7 @@ class Project : public QObject signals: void fileChanged(QString filepath); + void mapSectionIdNamesChanged(); void mapLoaded(Map *map); }; diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 3e6e95d10..80a5423b2 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -65,9 +65,11 @@ class MapListModel : public QStandardItemModel { ~MapListModel() { } virtual QModelIndex indexOf(QString id) const = 0; - virtual void removeFolder(int index) = 0; - virtual void removeItem(const QModelIndex &index); + virtual void removeItemAt(const QModelIndex &index); virtual QStandardItem *getItem(const QModelIndex &index) const = 0; + +protected: + virtual void removeItem(QStandardItem *item) = 0; }; class MapGroupModel : public MapListModel { @@ -94,13 +96,15 @@ class MapGroupModel : public MapListModel { QStandardItem *insertGroupItem(QString groupName); QStandardItem *insertMapItem(QString mapName, QString groupName); - virtual void removeFolder(int index) override; virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString mapName) const override; void initialize(); +protected: + virtual void removeItem(QStandardItem *item) override; + private: friend class MapTree; void updateProject(); @@ -137,13 +141,15 @@ class MapAreaModel : public MapListModel { QStandardItem *insertAreaItem(QString areaName); QStandardItem *insertMapItem(QString mapName, QString areaName, int groupIndex); - virtual void removeFolder(int index) override; virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString mapName) const override; void initialize(); +protected: + virtual void removeItem(QStandardItem *item) override; + private: Project *project; QStandardItem *root = nullptr; @@ -176,13 +182,15 @@ class LayoutTreeModel : public MapListModel { QStandardItem *insertLayoutItem(QString layoutId); QStandardItem *insertMapItem(QString mapName, QString layoutId); - virtual void removeFolder(int index) override; virtual QStandardItem *getItem(const QModelIndex &index) const override; virtual QModelIndex indexOf(QString layoutName) const override; void initialize(); +protected: + virtual void removeItem(QStandardItem *item) override; + private: Project *project; QStandardItem *root = nullptr; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 90b2a80cf..9cb9d1309 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -598,8 +598,9 @@ bool MainWindow::openProject(QString dir, bool initial) { // Create the project auto project = new Project(editor); project->set_root(dir); - QObject::connect(project, &Project::fileChanged, this, &MainWindow::showFileWatcherWarning); - QObject::connect(project, &Project::mapLoaded, this, &MainWindow::onMapLoaded); + connect(project, &Project::fileChanged, this, &MainWindow::showFileWatcherWarning); + connect(project, &Project::mapLoaded, this, &MainWindow::onMapLoaded); + connect(project, &Project::mapSectionIdNamesChanged, this, &MainWindow::refreshLocationsComboBox); this->editor->setProject(project); // Make sure project looks reasonable before attempting to load it @@ -1163,7 +1164,6 @@ bool MainWindow::setProjectUI() { // Block signals to the comboboxes while they are being modified const QSignalBlocker blocker1(ui->comboBox_Song); - const QSignalBlocker blocker2(ui->comboBox_Location); const QSignalBlocker blocker3(ui->comboBox_PrimaryTileset); const QSignalBlocker blocker4(ui->comboBox_SecondaryTileset); const QSignalBlocker blocker5(ui->comboBox_Weather); @@ -1176,8 +1176,6 @@ bool MainWindow::setProjectUI() { // Set up project comboboxes ui->comboBox_Song->clear(); ui->comboBox_Song->addItems(project->songNames); - ui->comboBox_Location->clear(); - ui->comboBox_Location->addItems(project->mapSectionIdNames); ui->comboBox_PrimaryTileset->clear(); ui->comboBox_PrimaryTileset->addItems(project->primaryTilesetLabels); ui->comboBox_SecondaryTileset->clear(); @@ -1198,6 +1196,7 @@ bool MainWindow::setProjectUI() { ui->comboBox_EmergeMap->addItems(project->mapNames); ui->comboBox_EmergeMap->setClearButtonEnabled(true); ui->comboBox_EmergeMap->setFocusedScrollingEnabled(false); + refreshLocationsComboBox(); // Show/hide parts of the UI that are dependent on the user's project settings @@ -1247,6 +1246,17 @@ bool MainWindow::setProjectUI() { return true; } +void MainWindow::refreshLocationsComboBox() { + QStringList locations = this->editor->project->mapSectionIdNames; + locations.sort(); + + const QSignalBlocker b(ui->comboBox_Location); + ui->comboBox_Location->clear(); + ui->comboBox_Location->addItems(locations); + if (this->editor->map) + ui->comboBox_Location->setCurrentText(this->editor->map->location); +} + void MainWindow::clearProjectUI() { // Block signals to the comboboxes while they are being modified const QSignalBlocker blocker1(ui->comboBox_Song); @@ -1328,19 +1338,30 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) { QMenu menu(this); QAction* addToFolderAction = nullptr; QAction* deleteFolderAction = nullptr; + QAction* openItemAction = nullptr; if (itemType == "map_name") { // Right-clicking on a map. - // TODO: Add action to delete map once deleting maps is supported + openItemAction = menu.addAction("Open Map"); + //menu.addSeparator(); + //connect(menu.addAction("Delete Map"), &QAction::triggered, [this, index] { deleteMapListItem(index); }); // TODO: No support for deleting maps } else if (itemType == "map_group") { // Right-clicking on a map group folder addToFolderAction = menu.addAction("Add New Map to Group"); + menu.addSeparator(); deleteFolderAction = menu.addAction("Delete Map Group"); } else if (itemType == "map_section") { // Right-clicking on an MAPSEC folder addToFolderAction = menu.addAction("Add New Map to Area"); + menu.addSeparator(); + deleteFolderAction = menu.addAction("Delete Area"); + if (itemName == this->editor->project->getEmptyMapsecName()) + deleteFolderAction->setEnabled(false); // Disallow deleting the default name } else if (itemType == "map_layout") { // Right-clicking on a map layout + openItemAction = menu.addAction("Open Layout"); addToFolderAction = menu.addAction("Add New Map with Layout"); + //menu.addSeparator(); + //deleteFolderAction = menu.addAction("Delete Layout"); // TODO: No support for deleting layouts } if (addToFolderAction) { @@ -1351,13 +1372,16 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) { } if (deleteFolderAction) { connect(deleteFolderAction, &QAction::triggered, [sourceModel, index] { - sourceModel->removeFolder(index.row()); + sourceModel->removeItemAt(index); }); if (selectedItem->hasChildren()){ // TODO: No support for deleting maps, so you may only delete folders if they don't contain any maps. deleteFolderAction->setEnabled(false); } } + if (openItemAction) { + connect(openItemAction, &QAction::triggered, [this, index] { openMapListItem(index); }); + } if (menu.actions().length() != 0) menu.exec(QCursor::pos()); diff --git a/src/project.cpp b/src/project.cpp index 9d87c6f40..9c9fcf140 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -2319,7 +2319,7 @@ QString Project::getEmptyMapsecName() { } // This function assumes a valid and unique name -void Project::addNewMapsec(QString name) { +void Project::addNewMapsec(const QString &name) { if (!this->mapSectionIdNames.isEmpty() && this->mapSectionIdNames.last() == getEmptyMapsecName()) { // If the default map section name (MAPSEC_NONE) is last in the list we'll keep it last in the list. this->mapSectionIdNames.insert(this->mapSectionIdNames.length() - 1, name); @@ -2327,6 +2327,16 @@ void Project::addNewMapsec(QString name) { this->mapSectionIdNames.append(name); } this->hasUnsavedDataChanges = true; + emit mapSectionIdNamesChanged(); +} + +void Project::removeMapsec(const QString &name) { + if (!this->mapSectionIdNames.contains(name) || name == getEmptyMapsecName()) + return; + + this->mapSectionIdNames.removeOne(name); + this->hasUnsavedDataChanges = true; + emit mapSectionIdNamesChanged(); } // Read the constants to preserve any "unused" heal locations when writing the file later diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index 616e608ca..a270736af 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -31,14 +31,14 @@ void MapTree::keyPressEvent(QKeyEvent *event) { persistentIndexes.append(model->mapToSource(index)); } for (const auto &index : persistentIndexes) { - sourceModel->removeItem(index); + sourceModel->removeItemAt(index); } } else { QWidget::keyPressEvent(event); } } -void MapListModel::removeItem(const QModelIndex &index) { +void MapListModel::removeItemAt(const QModelIndex &index) { QStandardItem *item = this->getItem(index)->child(index.row(), index.column()); if (!item) return; @@ -49,7 +49,7 @@ void MapListModel::removeItem(const QModelIndex &index) { } else { // TODO: Because there's no support for deleting maps we can only delete empty folders if (!item->hasChildren()) { - this->removeFolder(index.row()); + this->removeItem(item); } } } @@ -282,8 +282,8 @@ QStandardItem *MapGroupModel::insertGroupItem(QString groupName) { return group; } -void MapGroupModel::removeFolder(int index) { - this->removeRow(index); +void MapGroupModel::removeItem(QStandardItem *item) { + this->removeRow(item->row()); this->updateProject(); } @@ -454,10 +454,9 @@ QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, in return map; } -// Note: Not actually supported in the interface at the moment. -void MapAreaModel::removeFolder(int index) { - this->removeRow(index); - this->project->mapSectionIdNames.removeAt(index); +void MapAreaModel::removeItem(QStandardItem *item) { + this->project->removeMapsec(item->data(Qt::UserRole).toString()); + this->removeRow(item->row()); } void MapAreaModel::initialize() { @@ -612,7 +611,7 @@ QStandardItem *LayoutTreeModel::insertMapItem(QString mapName, QString layoutId) return map; } -void LayoutTreeModel::removeFolder(int) { +void LayoutTreeModel::removeItem(QStandardItem *) { // TODO: Deleting layouts not supported } diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index 261544f2b..def485c2a 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -8,6 +8,8 @@ #include #include +// TODO: Convert to modal dialog (among other things, this means we wouldn't need to worry about changes to the map list while this is open) + struct NewMapPopup::Settings NewMapPopup::settings = {}; NewMapPopup::NewMapPopup(QWidget *parent, Project *project) : From e278d48380c198d0589164e7b12edd4c7d9c3a0c Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 8 Nov 2024 14:59:41 -0500 Subject: [PATCH 69/70] Fix script API undo/redo for layouts, final TODO items --- include/ui/maplistmodels.h | 1 + src/core/editcommands.cpp | 5 ++--- src/mainwindow.cpp | 4 ---- src/project.cpp | 15 ++++++++++----- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/ui/maplistmodels.h b/include/ui/maplistmodels.h index 80a5423b2..17810c7ed 100644 --- a/include/ui/maplistmodels.h +++ b/include/ui/maplistmodels.h @@ -27,6 +27,7 @@ class MapTree : public QTreeView { this->setDropIndicatorShown(true); this->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); this->setFocusPolicy(Qt::StrongFocus); + this->setContextMenuPolicy(Qt::CustomContextMenu); } protected: diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp index 0843b2c0d..c500c8c0d 100644 --- a/src/core/editcommands.cpp +++ b/src/core/editcommands.cpp @@ -486,7 +486,6 @@ int EventPaste::id() const { ************************************************************************ ******************************************************************************/ -// TODO: Undo/redo for script edits to layout dimensions doesn't render correctly. ScriptEditLayout::ScriptEditLayout(Layout *layout, QSize oldLayoutDimensions, QSize newLayoutDimensions, const Blockdata &oldMetatiles, const Blockdata &newMetatiles, @@ -538,7 +537,7 @@ void ScriptEditLayout::redo() { layout->lastCommitBlocks.border = newBorder; layout->lastCommitBlocks.borderDimensions = QSize(newBorderWidth, newBorderHeight); - renderBlocks(layout); + renderBlocks(layout, true); layout->borderItem->draw(); } @@ -564,7 +563,7 @@ void ScriptEditLayout::undo() { layout->lastCommitBlocks.border = oldBorder; layout->lastCommitBlocks.borderDimensions = QSize(oldBorderWidth, oldBorderHeight); - renderBlocks(layout); + renderBlocks(layout, true); layout->borderItem->draw(); QUndoCommand::undo(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9cb9d1309..2b83e0b0b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -406,9 +406,6 @@ void MainWindow::initMapList() { connect(ui->layoutList, &QAbstractItemView::activated, this, &MainWindow::openMapListItem); // Right-clicking on items in the map list brings up a context menu. - ui->mapList->setContextMenuPolicy(Qt::CustomContextMenu); - ui->areaList->setContextMenuPolicy(Qt::CustomContextMenu); - ui->layoutList->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->mapList, &QTreeView::customContextMenuRequested, this, &MainWindow::onOpenMapListContextMenu); connect(ui->areaList, &QTreeView::customContextMenuRequested, this, &MainWindow::onOpenMapListContextMenu); connect(ui->layoutList, &QTreeView::customContextMenuRequested, this, &MainWindow::onOpenMapListContextMenu); @@ -1316,7 +1313,6 @@ void MainWindow::scrollMapListToCurrentMap(MapTree *list) { } } -// TODO: Initial scrolling doesn't center the layout on launch if it's not the current tab. void MainWindow::scrollMapListToCurrentLayout(MapTree *list) { if (this->editor->layout) { scrollMapList(list, this->editor->layout->id); diff --git a/src/project.cpp b/src/project.cpp index 9c9fcf140..88e3d9d1d 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -2266,11 +2266,16 @@ bool Project::readRegionMapSections() { fileWatcher.addPath(filepath); QJsonArray mapSections = doc.object()["map_sections"].toArray(); - for (const auto &mapSection : mapSections) { - // For each map section, "id" is the only required field. This is the field we use - // to display the location names in various drop-downs. - QJsonObject mapSectionObj = mapSection.toObject(); - const QString idName = ParseUtil::jsonToQString(mapSectionObj["id"]); + for (int i = 0; i < mapSections.size(); i++) { + QJsonObject mapSectionObj = mapSections.at(i).toObject(); + + // For each map section, "id" is the only required field. This is the field we use to display the location names in various drop-downs. + const QString idField = "id"; + if (!mapSectionObj.contains(idField)) { + logWarn(QString("Ignoring data for map section %1. Missing required field \"%2\"").arg(i).arg(idField)); + continue; + } + const QString idName = ParseUtil::jsonToQString(mapSectionObj[idField]); if (!idName.startsWith(requiredPrefix)) { logWarn(QString("Ignoring data for map section '%1'. IDs must start with the prefix '%2'").arg(idName).arg(requiredPrefix)); continue; From 43c45f7d98f39131db3843c200330dd4ea53a8a4 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 8 Nov 2024 19:06:56 -0500 Subject: [PATCH 70/70] Fix some typos --- src/mainwindow.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2b83e0b0b..d9e65eb30 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -851,7 +851,7 @@ bool MainWindow::userSetMap(QString map_name) { bool MainWindow::setMap(QString map_name) { if (map_name.isEmpty() || map_name == DYNAMIC_MAP_NAME) { - logInfo(QString("Cannot set map to '%1'").arg(DYNAMIC_MAP_NAME)); + logInfo(QString("Cannot set map to '%1'").arg(map_name)); return false; } @@ -1346,7 +1346,7 @@ void MainWindow::onOpenMapListContextMenu(const QPoint &point) { menu.addSeparator(); deleteFolderAction = menu.addAction("Delete Map Group"); } else if (itemType == "map_section") { - // Right-clicking on an MAPSEC folder + // Right-clicking on a MAPSEC folder addToFolderAction = menu.addAction("Add New Map to Area"); menu.addSeparator(); deleteFolderAction = menu.addAction("Delete Area"); @@ -1541,7 +1541,6 @@ void MainWindow::mapListAddLayout() { } void MainWindow::mapListAddArea() { - // Note: there is no checking here for the limits on map section count QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::ApplicationModal); QDialogButtonBox newItemButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); @@ -2824,7 +2823,7 @@ void MainWindow::on_actionExport_Stitched_Map_Image_triggered() { if (!this->editor->map) { QMessageBox warning(this); warning.setText("Notice"); - warning.setInformativeText("Map stich images are not possible without a map selected."); + warning.setInformativeText("Map stitch images are not possible without a map selected."); warning.setStandardButtons(QMessageBox::Ok); warning.setDefaultButton(QMessageBox::Cancel); warning.setIcon(QMessageBox::Warning);