From ef165e29df30a797d1ad0964a160004c8465d50c Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 4 Jan 2024 12:22:06 -0500 Subject: [PATCH 1/7] Stop enforcing heal locations table name --- CHANGELOG.md | 3 ++- docsrc/manual/project-files.rst | 9 +++++---- include/config.h | 1 + include/project.h | 2 +- src/config.cpp | 5 +++-- src/project.cpp | 30 ++++++++++++++++++------------ 6 files changed, 30 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eac8dfd1..d692d1be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,9 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Add `metatile_behaviors`, `num_primary_palettes`, and `num_secondary_palettes` to `constants` in the API. ### Changed -- The API functions `addImage` and `createImage` now support project-relative paths. - Metatile ID strings are now padded to their current max, not the overall max. +- The name of the Heal Locations table is no longer enforced. +- The API functions `addImage` and `createImage` now support project-relative paths. ### Fixed - Fix the event group tabs sometimes showing an event from the wrong group diff --git a/docsrc/manual/project-files.rst b/docsrc/manual/project-files.rst index bc629a1f..20849ba3 100644 --- a/docsrc/manual/project-files.rst +++ b/docsrc/manual/project-files.rst @@ -86,10 +86,11 @@ In addition to these files, there are some specific symbol and macro names that ``symbol_obj_event_gfx_pointers``, ``gObjectEventGraphicsInfoPointers``, to map Object Event graphics IDs to graphics data ``symbol_pokemon_icon_table``, ``gMonIconTable``, to map species constants to icon images ``symbol_wild_encounters``, ``gWildMonHeaders``, output as the ``label`` property for the top-level wild ecounters JSON object - ``symbol_heal_locations``, ``sHealLocations``, only if ``Respawn Map/NPC`` is disabled - ``symbol_spawn_points``, ``sSpawnPoints``, only if ``Respawn Map/NPC`` is enabled - ``symbol_spawn_maps``, ``sWhiteoutRespawnHealCenterMapIdxs``, values for Heal Locations ``Respawn Map`` field - ``symbol_spawn_npcs``, ``sWhiteoutRespawnHealerNpcIds``, values for Heal Locations ``Respawn NPC`` field + ``symbol_heal_locations_type``, ``struct HealLocation``, the type for the Heal Locations table + ``symbol_heal_locations``, ``sHealLocations``, the default Heal Locations table name when ``Respawn Map/NPC`` is disabled + ``symbol_spawn_points``, ``sSpawnPoints``, the default Heal Locations table name when ``Respawn Map/NPC`` is enabled + ``symbol_spawn_maps``, ``u16 sWhiteoutRespawnHealCenterMapIdxs``, the type and table name for Heal Location ``Respawn Map`` values + ``symbol_spawn_npcs``, ``u8 sWhiteoutRespawnHealerNpcIds``, the type and table name for Heal Location ``Respawn NPC`` values ``symbol_attribute_table``, ``sMetatileAttrMasks``, optionally read to get settings on ``Tilesets`` tab ``symbol_tilesets_prefix``, ``gTileset_``, for new tileset names and to extract base tileset names ``define_obj_event_count``, ``OBJECT_EVENT_TEMPLATES_COUNT``, to limit total Object Events diff --git a/include/config.h b/include/config.h index 7ae31839..9a1f5d8d 100644 --- a/include/config.h +++ b/include/config.h @@ -189,6 +189,7 @@ enum ProjectIdentifier { symbol_obj_event_gfx_pointers, symbol_pokemon_icon_table, symbol_wild_encounters, + symbol_heal_locations_type, symbol_heal_locations, symbol_spawn_points, symbol_spawn_maps, diff --git a/include/project.h b/include/project.h index e4f6840b..c7effcfb 100644 --- a/include/project.h +++ b/include/project.h @@ -93,6 +93,7 @@ public: }; DataQualifiers getDataQualifiers(QString, QString); DataQualifiers healLocationDataQualifiers; + QString healLocationsTableName; QMap mapCache; Map* loadMap(QString); @@ -238,7 +239,6 @@ private: void saveHealLocationsData(Map *map); void saveHealLocationsConstants(); - QString getHealLocationsTableName(); void ignoreWatchedFileTemporarily(QString filepath); diff --git a/src/config.cpp b/src/config.cpp index 11bd06dc..2dba96e4 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -74,10 +74,11 @@ const QMap> ProjectConfig::defaultIde {ProjectIdentifier::symbol_obj_event_gfx_pointers, {"symbol_obj_event_gfx_pointers", "gObjectEventGraphicsInfoPointers"}}, {ProjectIdentifier::symbol_pokemon_icon_table, {"symbol_pokemon_icon_table", "gMonIconTable"}}, {ProjectIdentifier::symbol_wild_encounters, {"symbol_wild_encounters", "gWildMonHeaders"}}, + {ProjectIdentifier::symbol_heal_locations_type, {"symbol_heal_locations_type", "struct HealLocation"}}, {ProjectIdentifier::symbol_heal_locations, {"symbol_heal_locations", "sHealLocations"}}, {ProjectIdentifier::symbol_spawn_points, {"symbol_spawn_points", "sSpawnPoints"}}, - {ProjectIdentifier::symbol_spawn_maps, {"symbol_spawn_maps", "sWhiteoutRespawnHealCenterMapIdxs"}}, - {ProjectIdentifier::symbol_spawn_npcs, {"symbol_spawn_npcs", "sWhiteoutRespawnHealerNpcIds"}}, + {ProjectIdentifier::symbol_spawn_maps, {"symbol_spawn_maps", "u16 sWhiteoutRespawnHealCenterMapIdxs"}}, + {ProjectIdentifier::symbol_spawn_npcs, {"symbol_spawn_npcs", "u8 sWhiteoutRespawnHealerNpcIds"}}, {ProjectIdentifier::symbol_attribute_table, {"symbol_attribute_table", "sMetatileAttrMasks"}}, {ProjectIdentifier::symbol_tilesets_prefix, {"symbol_tilesets_prefix", "gTileset_"}}, // Defines diff --git a/src/project.cpp b/src/project.cpp index 475512ff..fa0dfa7b 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -748,12 +748,6 @@ void Project::saveHealLocations(Map *map) { this->saveHealLocationsConstants(); } -QString Project::getHealLocationsTableName() { - if (projectConfig.getHealLocationRespawnDataEnabled()) - return projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_points); - return projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations); -} - // Saves heal location maps/coords/respawn data in root + /src/data/heal_locations.h void Project::saveHealLocationsData(Map *map) { // Update heal locations from map @@ -780,11 +774,13 @@ void Project::saveHealLocationsData(Map *map) { const QString qualifiers = QString(healLocationDataQualifiers.isStatic ? "static " : "") + QString(healLocationDataQualifiers.isConst ? "const " : ""); - QString locationTableText = QString("%1struct HealLocation %2[] =\n{\n").arg(qualifiers).arg(this->getHealLocationsTableName()); + QString locationTableText = QString("%1%2 %3[] =\n{\n").arg(qualifiers) + .arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations_type)) + .arg(this->healLocationsTableName); QString respawnMapTableText, respawnNPCTableText; if (respawnEnabled) { - respawnMapTableText = QString("\n%1u16 %2[][2] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_maps)); - respawnNPCTableText = QString("\n%1u8 %2[] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_npcs)); + respawnMapTableText = QString("\n%1%2[][2] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_maps)); + respawnNPCTableText = QString("\n%1%2[] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_npcs)); } // Populate the data tables with the heal location data @@ -2087,7 +2083,6 @@ bool Project::readHealLocationConstants() { // TODO: Simplify using the new C struct parsing functions (and indexed array parsing functions) bool Project::readHealLocations() { - this->healLocationDataQualifiers = {}; this->healLocations.clear(); if (!this->readHealLocationConstants()) @@ -2103,8 +2098,19 @@ bool Project::readHealLocations() { bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled(); - // Get data qualifiers for the location data table - this->healLocationDataQualifiers = this->getDataQualifiers(text, this->getHealLocationsTableName()); + // Search for the name of the main Heal Locations table + const QRegularExpression tableNameExpr(QString("%1\\s+(?[A-Za-z0-9_]+)\\[").arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations_type))); + const QRegularExpressionMatch tableNameMatch = tableNameExpr.match(text); + if (tableNameMatch.hasMatch()) { + // Found table name, record it and its qualifiers for output when saving. + this->healLocationsTableName = tableNameMatch.captured("name"); + this->healLocationDataQualifiers = this->getDataQualifiers(text, this->healLocationsTableName); + } else { + // No table name found, initialize default name for output when saving. + this->healLocationsTableName = respawnEnabled ? projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_points) + : projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations); + this->healLocationDataQualifiers = { .isStatic = true, .isConst = true }; + } // Create regex pattern for the constants (ex: "SPAWN_PALLET_TOWN" or "HEAL_LOCATION_PETALBURG_CITY") const QString spawnPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_spawn_prefix); From 8c85209d536858770132e23e3afe255b738562b8 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 4 Jan 2024 21:22:10 -0500 Subject: [PATCH 2/7] Fix metatile selector rectangle jumping --- CHANGELOG.md | 1 + src/ui/metatileselector.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eac8dfd1..c54f13de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Metatile ID strings are now padded to their current max, not the overall max. ### Fixed +- Fix the metatile selector rectangle jumping when selecting up or left of the origin. - Fix the event group tabs sometimes showing an event from the wrong group - Fix API error reporting diff --git a/src/ui/metatileselector.cpp b/src/ui/metatileselector.cpp index 3ce9cf55..d72bb25d 100644 --- a/src/ui/metatileselector.cpp +++ b/src/ui/metatileselector.cpp @@ -4,7 +4,9 @@ #include QPoint MetatileSelector::getSelectionDimensions() { - return selection.dimensions; + if (this->prefabSelection || this->externalSelection) + return selection.dimensions; + return SelectablePixmapItem::getSelectionDimensions(); } void MetatileSelector::draw() { @@ -155,7 +157,7 @@ void MetatileSelector::updateSelectedMetatiles() { this->selection.metatileItems.clear(); this->selection.collisionItems.clear(); this->selection.hasCollision = false; - this->selection.dimensions = SelectablePixmapItem::getSelectionDimensions(); + this->selection.dimensions = this->getSelectionDimensions(); QPoint origin = this->getSelectionStart(); for (int j = 0; j < this->selection.dimensions.y(); j++) { for (int i = 0; i < this->selection.dimensions.x(); i++) { From 941174d0ead8476d68b6b5cd022d7f669c3afac9 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 4 Jan 2024 21:36:14 -0500 Subject: [PATCH 3/7] Reduce redundant work in metatile selector --- include/ui/metatileselector.h | 7 +++++-- src/ui/metatileselector.cpp | 38 ++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/include/ui/metatileselector.h b/include/ui/metatileselector.h index 0c0b779f..eaf357ca 100644 --- a/include/ui/metatileselector.h +++ b/include/ui/metatileselector.h @@ -39,6 +39,7 @@ public: this->primaryTileset = map->layout->tileset_primary; this->secondaryTileset = map->layout->tileset_secondary; this->selection = MetatileSelection{}; + this->cellPos = QPoint(-1, -1); setAcceptHoverEvents(true); } QPoint getSelectionDimensions(); @@ -68,13 +69,15 @@ private: int externalSelectionHeight; QList externalSelectedMetatiles; MetatileSelection selection; + QPoint cellPos; void updateSelectedMetatiles(); void updateExternalSelectedMetatiles(); - uint16_t getMetatileId(int x, int y); + uint16_t getMetatileId(int x, int y) const; QPoint getMetatileIdCoords(uint16_t); - bool shouldAcceptEvent(QGraphicsSceneMouseEvent*); + bool positionIsValid(const QPoint &pos) const; bool selectionIsValid(); + void hoverChanged(); signals: void hoveredMetatileSelectionChanged(uint16_t); diff --git a/src/ui/metatileselector.cpp b/src/ui/metatileselector.cpp index d72bb25d..2c4a5fb3 100644 --- a/src/ui/metatileselector.cpp +++ b/src/ui/metatileselector.cpp @@ -114,41 +114,55 @@ void MetatileSelector::setPrefabSelection(MetatileSelection selection) { emit selectedMetatilesChanged(); } -bool MetatileSelector::shouldAcceptEvent(QGraphicsSceneMouseEvent *event) { - QPoint pos = this->getCellPos(event->pos()); +bool MetatileSelector::positionIsValid(const QPoint &pos) const { return Tileset::metatileIsValid(getMetatileId(pos.x(), pos.y()), this->primaryTileset, this->secondaryTileset); } void MetatileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if (!shouldAcceptEvent(event)) return; + QPoint pos = this->getCellPos(event->pos()); + if (!positionIsValid(pos)) + return; + + this->cellPos = pos; SelectablePixmapItem::mousePressEvent(event); this->updateSelectedMetatiles(); } void MetatileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - if (!shouldAcceptEvent(event)) return; + QPoint pos = this->getCellPos(event->pos()); + if (!positionIsValid(pos) || this->cellPos == pos) + return; + + this->cellPos = pos; SelectablePixmapItem::mouseMoveEvent(event); this->updateSelectedMetatiles(); - - QPoint pos = this->getCellPos(event->pos()); - uint16_t metatileId = this->getMetatileId(pos.x(), pos.y()); - emit this->hoveredMetatileSelectionChanged(metatileId); + this->hoverChanged(); } void MetatileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (!shouldAcceptEvent(event)) return; + QPoint pos = this->getCellPos(event->pos()); + if (!positionIsValid(pos)) + return; SelectablePixmapItem::mouseReleaseEvent(event); - this->updateSelectedMetatiles(); } void MetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { QPoint pos = this->getCellPos(event->pos()); - uint16_t metatileId = this->getMetatileId(pos.x(), pos.y()); + if (!positionIsValid(pos) || this->cellPos == pos) + return; + + this->cellPos = pos; + this->hoverChanged(); +} + +void MetatileSelector::hoverChanged() { + uint16_t metatileId = this->getMetatileId(this->cellPos.x(), this->cellPos.y()); emit this->hoveredMetatileSelectionChanged(metatileId); } void MetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { emit this->hoveredMetatileSelectionCleared(); + this->cellPos = QPoint(-1, -1); } void MetatileSelector::updateSelectedMetatiles() { @@ -182,7 +196,7 @@ void MetatileSelector::updateExternalSelectedMetatiles() { emit selectedMetatilesChanged(); } -uint16_t MetatileSelector::getMetatileId(int x, int y) { +uint16_t MetatileSelector::getMetatileId(int x, int y) const { int index = y * this->numMetatilesWide + x; if (index < this->primaryTileset->metatiles.length()) { return static_cast(index); From db1aabe3c22debb6e0240ad2d9f7ae953764c4e5 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 5 Jan 2024 00:29:36 -0500 Subject: [PATCH 4/7] Fix shortcuts editor clear buttons --- CHANGELOG.md | 1 + src/ui/multikeyedit.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c54f13de..ebdcd6f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ### Fixed - Fix the metatile selector rectangle jumping when selecting up or left of the origin. - Fix the event group tabs sometimes showing an event from the wrong group +- Fix the clear buttons in the Shortcuts Editor not actually removing shortcuts. - Fix API error reporting ## [5.2.0] - 2024-01-02 diff --git a/src/ui/multikeyedit.cpp b/src/ui/multikeyedit.cpp index 09943861..fcf38480 100644 --- a/src/ui/multikeyedit.cpp +++ b/src/ui/multikeyedit.cpp @@ -140,6 +140,14 @@ void MultiKeyEdit::addNewKeySequenceEdit() { connect(lineEdit, &QLineEdit::customContextMenuRequested, this, &MultiKeyEdit::customContextMenuRequested); + // Gross way to connect the line edit's clear button. + auto actions = lineEdit->findChildren(); + if (!actions.isEmpty()) { + connect(actions.first(), &QAction::triggered, this, [this, keySequenceEdit]() { + removeOne(keySequenceEdit->keySequence()); + }); + } + layout()->addWidget(keySequenceEdit); keySequenceEdit_vec.append(keySequenceEdit); } From c9d8de8971d1521786852b573d1b6098da024808 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 5 Jan 2024 02:47:23 -0500 Subject: [PATCH 5/7] Display tile ID when hovering over Tileset Editor layer view --- include/ui/metatilelayersitem.h | 12 +++- src/ui/metatilelayersitem.cpp | 99 ++++++++++++++++++++------------- src/ui/tileseteditor.cpp | 5 ++ 3 files changed, 76 insertions(+), 40 deletions(-) diff --git a/include/ui/metatilelayersitem.h b/include/ui/metatilelayersitem.h index fbd769e0..ef05a77d 100644 --- a/include/ui/metatilelayersitem.h +++ b/include/ui/metatilelayersitem.h @@ -14,25 +14,33 @@ public: this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; this->clearLastModifiedCoords(); + this->clearLastHoveredCoords(); + setAcceptHoverEvents(true); } void draw(); void setTilesets(Tileset*, Tileset*); void setMetatile(Metatile*); void clearLastModifiedCoords(); + void clearLastHoveredCoords(); bool showGrid; private: Metatile* metatile; Tileset *primaryTileset; Tileset *secondaryTileset; - QPoint prevChangedTile; - void getBoundedCoords(QPointF, int*, int*); + QPoint prevChangedPos; + QPoint prevHoveredPos; + QPoint getBoundedPos(const QPointF &); signals: void tileChanged(int, int); void selectedTilesChanged(QPoint, int, int); + void hoveredTileChanged(uint16_t); + void hoveredTileCleared(); protected: void mousePressEvent(QGraphicsSceneMouseEvent*); void mouseMoveEvent(QGraphicsSceneMouseEvent*); void mouseReleaseEvent(QGraphicsSceneMouseEvent*); + void hoverMoveEvent(QGraphicsSceneHoverEvent*); + void hoverLeaveEvent(QGraphicsSceneHoverEvent*); }; #endif // METATILELAYERSITEM_H diff --git a/src/ui/metatilelayersitem.cpp b/src/ui/metatilelayersitem.cpp index d113d098..e4a1e74e 100644 --- a/src/ui/metatilelayersitem.cpp +++ b/src/ui/metatilelayersitem.cpp @@ -3,22 +3,22 @@ #include "imageproviders.h" #include -void MetatileLayersItem::draw() { - static const QList tileCoords = QList{ - QPoint(0, 0), - QPoint(16, 0), - QPoint(0, 16), - QPoint(16, 16), - QPoint(32, 0), - QPoint(48, 0), - QPoint(32, 16), - QPoint(48, 16), - QPoint(64, 0), - QPoint(80, 0), - QPoint(64, 16), - QPoint(80, 16), - }; +static const QList tilePositions = { + QPoint(0, 0), + QPoint(1, 0), + QPoint(0, 1), + QPoint(1, 1), + QPoint(2, 0), + QPoint(3, 0), + QPoint(2, 1), + QPoint(3, 1), + QPoint(4, 0), + QPoint(5, 0), + QPoint(4, 1), + QPoint(5, 1), +}; +void MetatileLayersItem::draw() { const int numLayers = projectConfig.getNumLayersInMetatile(); QPixmap pixmap(numLayers * 32, 32); QPainter painter(&pixmap); @@ -30,7 +30,7 @@ void MetatileLayersItem::draw() { QImage tileImage = getPalettedTileImage(tile.tileId, this->primaryTileset, this->secondaryTileset, tile.palette, true) .mirrored(tile.xflip, tile.yflip) .scaled(16, 16); - painter.drawImage(tileCoords.at(i), tileImage); + painter.drawImage(tilePositions.at(i) * 16, tileImage); } if (this->showGrid) { // Draw grid @@ -47,6 +47,7 @@ void MetatileLayersItem::draw() { void MetatileLayersItem::setMetatile(Metatile *metatile) { this->metatile = metatile; this->clearLastModifiedCoords(); + this->clearLastHoveredCoords(); } void MetatileLayersItem::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { @@ -54,6 +55,7 @@ void MetatileLayersItem::setTilesets(Tileset *primaryTileset, Tileset *secondary this->secondaryTileset = secondaryTileset; this->draw(); this->clearLastModifiedCoords(); + this->clearLastHoveredCoords(); } void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { @@ -64,11 +66,10 @@ void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { emit this->selectedTilesChanged(selectionOrigin, dimensions.x(), dimensions.y()); this->drawSelection(); } else { - int x, y; - this->getBoundedCoords(event->pos(), &x, &y); - this->prevChangedTile.setX(x); - this->prevChangedTile.setY(y); - emit this->tileChanged(x, y); + const QPoint pos = this->getBoundedPos(event->pos()); + this->prevChangedPos = pos; + this->clearLastHoveredCoords(); + emit this->tileChanged(pos.x(), pos.y()); } } @@ -80,12 +81,11 @@ void MetatileLayersItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { emit this->selectedTilesChanged(selectionOrigin, dimensions.x(), dimensions.y()); this->drawSelection(); } else { - int x, y; - this->getBoundedCoords(event->pos(), &x, &y); - if (prevChangedTile.x() != x || prevChangedTile.y() != y) { - this->prevChangedTile.setX(x); - this->prevChangedTile.setY(y); - emit this->tileChanged(x, y); + const QPoint pos = this->getBoundedPos(event->pos()); + if (prevChangedPos != pos) { + this->prevChangedPos = pos; + this->clearLastHoveredCoords(); + emit this->tileChanged(pos.x(), pos.y()); } } } @@ -101,17 +101,40 @@ void MetatileLayersItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { this->draw(); } -void MetatileLayersItem::clearLastModifiedCoords() { - this->prevChangedTile.setX(-1); - this->prevChangedTile.setY(-1); +void MetatileLayersItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) { + const QPoint pos = this->getBoundedPos(event->pos()); + if (pos == this->prevHoveredPos) + return; + this->prevHoveredPos = pos; + + int tileIndex = tilePositions.indexOf(pos); + if (tileIndex < 0 || tileIndex >= this->metatile->tiles.length()) + return; + + emit this->hoveredTileChanged(this->metatile->tiles.at(tileIndex).tileId); } -void MetatileLayersItem::getBoundedCoords(QPointF pos, int *x, int *y) { - int maxX = (projectConfig.getNumLayersInMetatile() * 2) - 1; - *x = static_cast(pos.x()) / 16; - *y = static_cast(pos.y()) / 16; - if (*x < 0) *x = 0; - if (*y < 0) *y = 0; - if (*x > maxX) *x = maxX; - if (*y > 1) *y = 1; +void MetatileLayersItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { + this->clearLastHoveredCoords(); + emit this->hoveredTileCleared(); +} + +void MetatileLayersItem::clearLastModifiedCoords() { + this->prevChangedPos = QPoint(-1, -1); +} + +void MetatileLayersItem::clearLastHoveredCoords() { + this->prevHoveredPos = QPoint(-1, -1); +} + +QPoint MetatileLayersItem::getBoundedPos(const QPointF &pos) { + int x, y; + int maxX = (projectConfig.getNumLayersInMetatile() * 2) - 1; + x = static_cast(pos.x()) / 16; + y = static_cast(pos.y()) / 16; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x > maxX) x = maxX; + if (y > 1) y = 1; + return QPoint(x, y); } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 0032264e..1d8f74fd 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -206,6 +206,10 @@ void TilesetEditor::initMetatileLayersItem() { this, &TilesetEditor::onMetatileLayerTileChanged); connect(this->metatileLayersItem, &MetatileLayersItem::selectedTilesChanged, this, &TilesetEditor::onMetatileLayerSelectionChanged); + connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileChanged, + this, &TilesetEditor::onHoveredTileChanged); + connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileCleared, + this, &TilesetEditor::onHoveredTileCleared); bool showGrid = porymapConfig.getShowTilesetEditorLayerGrid(); this->ui->actionLayer_Grid->setChecked(showGrid); @@ -861,6 +865,7 @@ bool TilesetEditor::replaceMetatile(uint16_t metatileId, const Metatile * src, Q this->metatileSelector->draw(); this->metatileLayersItem->draw(); this->metatileLayersItem->clearLastModifiedCoords(); + this->metatileLayersItem->clearLastHoveredCoords(); return true; } From 4df8b1e6fd29d0003f6e59f65690ac4c1270a24b Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 5 Jan 2024 02:49:22 -0500 Subject: [PATCH 6/7] Fix minor issues with project opening --- include/mainwindow.h | 4 +- src/mainwindow.cpp | 97 +++++++++++++++++++------------------ src/scriptapi/scripting.cpp | 1 + 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index bc6dface..e95db003 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -347,7 +347,8 @@ private: void sortMapList(); void openSubWindow(QWidget * window); QString getExistingDirectory(QString); - bool openProject(QString dir); + bool openProject(const QString &dir, bool initial = false); + void showProjectOpenFailure(); bool setInitialMap(); void setRecentMap(QString map_name); QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum); @@ -377,7 +378,6 @@ private: void applyMapListFilter(QString filterText); void restoreWindowState(); void setTheme(QString); - bool openRecentProject(); void updateTilesetEditor(); Event::Group getEventGroupFromTabWidget(QWidget *tab); void closeSupplementaryWindows(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 49dd4ac1..38e7f689 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -60,7 +60,7 @@ MainWindow::MainWindow(QWidget *parent) : cleanupLargeLog(); this->initWindow(); - if (this->openRecentProject()) + if (porymapConfig.getReopenOnLaunch() && this->openProject(porymapConfig.getRecentProject(), true)) on_toolButton_Paint_clicked(); // there is a bug affecting macOS users, where the trackpad deilveres a bad touch-release gesture @@ -477,35 +477,29 @@ void MainWindow::setTheme(QString theme) { } } -bool MainWindow::openRecentProject() { - if (!porymapConfig.getReopenOnLaunch()) - return false; - - QString default_dir = porymapConfig.getRecentProject(); - if (default_dir.isNull() || default_dir.length() <= 0) - return false; - - if (!QDir(default_dir).exists()) { - QString message = QString("Recent project directory '%1' doesn't exist.").arg(QDir::toNativeSeparators(default_dir)); - logWarn(message); - this->statusBar()->showMessage(message); - return false; - } - - logInfo(QString("Opening recent project: '%1'").arg(default_dir)); - return openProject(default_dir); -} - -bool MainWindow::openProject(QString dir) { - if (dir.isNull()) { +bool MainWindow::openProject(const QString &dir, bool initial) { + if (dir.isNull() || dir.length() <= 0) { projectOpenFailure = true; - setWindowDisabled(true); + if (!initial) setWindowDisabled(true); return false; } - QString nativeDir = QDir::toNativeSeparators(dir); + const QString projectString = QString("%1project '%2'").arg(initial ? "recent " : "").arg(QDir::toNativeSeparators(dir)); - this->statusBar()->showMessage(QString("Opening project %1").arg(nativeDir)); + if (!QDir(dir).exists()) { + projectOpenFailure = true; + const QString errorMsg = QString("Failed to open %1: No such directory").arg(projectString); + this->statusBar()->showMessage(errorMsg); + if (initial) { + // Graceful startup if recent project directory is missing + logWarn(errorMsg); + } else { + logError(errorMsg); + showProjectOpenFailure(); + } + return false; + } + this->statusBar()->showMessage(QString("Opening %1").arg(projectString)); userConfig.setProjectDir(dir); userConfig.load(); @@ -515,7 +509,10 @@ bool MainWindow::openProject(QString dir) { this->closeSupplementaryWindows(); this->newMapDefaultsSet = false; + if (isProjectOpen()) + Scripting::cb_ProjectClosed(editor->project->root); Scripting::init(this); + bool already_open = isProjectOpen() && (editor->project->root == dir); if (!already_open) { editor->closeProject(); @@ -540,19 +537,16 @@ bool MainWindow::openProject(QString dir) { && setInitialMap()); if (this->projectOpenFailure) { - this->statusBar()->showMessage(QString("Failed to open project %1").arg(nativeDir)); - QMessageBox msgBox(this); - QString errorMsg = QString("There was an error opening the project %1. Please see %2 for full error details.\n\n%3") - .arg(dir) - .arg(getLogPath()) - .arg(getMostRecentError()); - msgBox.critical(nullptr, "Error Opening Project", errorMsg); - setWindowDisabled(true); + this->statusBar()->showMessage(QString("Failed to open %1").arg(projectString)); + showProjectOpenFailure(); return false; } showWindowTitle(); - this->statusBar()->showMessage(QString("Opened project %1").arg(nativeDir)); + + const QString successMessage = QString("Opened %1").arg(projectString); + this->statusBar()->showMessage(successMessage); + logInfo(successMessage); porymapConfig.addRecentProject(dir); refreshRecentProjectsMenu(); @@ -567,6 +561,14 @@ bool MainWindow::openProject(QString dir) { return true; } +void MainWindow::showProjectOpenFailure() { + QString errorMsg = QString("There was an error opening the project. Please see %1 for full error details.").arg(getLogPath()); + QMessageBox error(QMessageBox::Critical, "porymap", errorMsg, QMessageBox::Ok, this); + error.setDetailedText(getMostRecentError()); + error.exec(); + setWindowDisabled(true); +} + bool MainWindow::isProjectOpen() { return !projectOpenFailure && editor && editor->project; } @@ -607,17 +609,22 @@ void MainWindow::refreshRecentProjectsMenu() { recentProjects.removeOne(this->editor->project->root); } - // Add project paths to menu. Arbitrary limit of 10 items. - const int numItems = qMin(10, recentProjects.length()); - for (int i = 0; i < numItems; i++) { + // Add project paths to menu. Skip any paths to folders that don't exist + for (int i = 0; i < recentProjects.length(); i++) { const QString path = recentProjects.at(i); - ui->menuOpen_Recent_Project->addAction(path, [this, path](){ - this->openProject(path); - }); + if (QDir(path).exists()) { + ui->menuOpen_Recent_Project->addAction(path, [this, path](){ + this->openProject(path); + }); + } + // Arbitrary limit of 10 items. + if (ui->menuOpen_Recent_Project->actions().length() >= 10) + break; } // Add action to clear list of paths - if (!recentProjects.isEmpty()) ui->menuOpen_Recent_Project->addSeparator(); + if (!ui->menuOpen_Recent_Project->actions().isEmpty()) + ui->menuOpen_Recent_Project->addSeparator(); QAction *clearAction = ui->menuOpen_Recent_Project->addAction("Clear Items", [this](){ QStringList paths = QStringList(); if (isProjectOpen()) @@ -652,13 +659,8 @@ void MainWindow::on_action_Open_Project_triggered() recent = userConfig.getRecentMap(); } QString dir = getExistingDirectory(recent); - if (!dir.isEmpty()) { - if (this->editor && this->editor->project) { - Scripting::cb_ProjectClosed(this->editor->project->root); - this->ui->graphicsView_Map->clearOverlayMap(); - } + if (!dir.isEmpty()) openProject(dir); - } } void MainWindow::on_action_Reload_Project_triggered() { @@ -2786,7 +2788,6 @@ void MainWindow::initCustomScriptsEditor() { void MainWindow::reloadScriptEngine() { Scripting::init(this); - this->ui->graphicsView_Map->clearOverlayMap(); Scripting::populateGlobalObject(this); // Lying to the scripts here, simulating a project reload Scripting::cb_ProjectOpened(projectConfig.getProjectDir()); diff --git a/src/scriptapi/scripting.cpp b/src/scriptapi/scripting.cpp index 19086df0..626f820b 100644 --- a/src/scriptapi/scripting.cpp +++ b/src/scriptapi/scripting.cpp @@ -23,6 +23,7 @@ QMap callbackFunctions = { Scripting *instance = nullptr; void Scripting::init(MainWindow *mainWindow) { + mainWindow->ui->graphicsView_Map->clearOverlayMap(); if (instance) { instance->engine->setInterrupted(true); instance->scriptUtility->clearActions(); From 3d3811f3b1baee4e9bda3281f442daf47ec828eb Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 5 Jan 2024 14:12:37 -0500 Subject: [PATCH 7/7] Set focus to map on launch --- src/mainwindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 49dd4ac1..3917adf5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2219,6 +2219,7 @@ void MainWindow::on_toolButton_Paint_clicked() ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); QScroller::ungrabGesture(ui->graphicsView_Map); ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate); + ui->graphicsView_Map->setFocus(); checkToolButtons(); } @@ -2237,6 +2238,7 @@ void MainWindow::on_toolButton_Select_clicked() ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); QScroller::ungrabGesture(ui->graphicsView_Map); ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate); + ui->graphicsView_Map->setFocus(); checkToolButtons(); } @@ -2255,6 +2257,7 @@ void MainWindow::on_toolButton_Fill_clicked() ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); QScroller::ungrabGesture(ui->graphicsView_Map); ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate); + ui->graphicsView_Map->setFocus(); checkToolButtons(); } @@ -2273,6 +2276,7 @@ void MainWindow::on_toolButton_Dropper_clicked() ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); QScroller::ungrabGesture(ui->graphicsView_Map); ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate); + ui->graphicsView_Map->setFocus(); checkToolButtons(); } @@ -2291,6 +2295,7 @@ void MainWindow::on_toolButton_Move_clicked() ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QScroller::grabGesture(ui->graphicsView_Map, QScroller::LeftMouseButtonGesture); ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::FullViewportUpdate); + ui->graphicsView_Map->setFocus(); checkToolButtons(); } @@ -2309,6 +2314,7 @@ void MainWindow::on_toolButton_Shift_clicked() ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); QScroller::ungrabGesture(ui->graphicsView_Map); ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate); + ui->graphicsView_Map->setFocus(); checkToolButtons(); }