From 2d827f62f786f2de2b8ad7a4e08a41a23dc01fcc Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 7 Apr 2025 11:44:54 -0400 Subject: [PATCH] Support event lookup by ID name --- include/core/events.h | 6 ++-- include/core/map.h | 1 + include/editor.h | 2 +- include/mainwindow.h | 2 +- include/ui/draggablepixmapitem.h | 5 +-- src/core/events.cpp | 7 ++-- src/core/map.cpp | 15 +++++++++ src/editor.cpp | 1 + src/mainwindow.cpp | 57 ++++++++++++++++++++++++++------ src/project.cpp | 11 ++++-- src/ui/draggablepixmapitem.cpp | 28 ---------------- src/ui/eventframes.cpp | 5 ++- 12 files changed, 88 insertions(+), 52 deletions(-) diff --git a/include/core/events.h b/include/core/events.h index 22b76434..cff233cc 100644 --- a/include/core/events.h +++ b/include/core/events.h @@ -300,12 +300,12 @@ public: void setTargetMap(QString newTargetMap) { this->targetMap = newTargetMap; } QString getTargetMap() const { return this->targetMap; } - void setTargetID(int newTargetID) { this->targetID = newTargetID; } - int getTargetID() const { return this->targetID; } + void setTargetID(QString newTargetID) { this->targetID = newTargetID; } + QString getTargetID() const { return this->targetID; } private: QString targetMap; - int targetID = 0; + QString targetID; }; diff --git a/include/core/map.h b/include/core/map.h index c2078134..a3bb1bbf 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -76,6 +76,7 @@ public: void resetEvents(); QList getEvents(Event::Group group = Event::Group::None) const; Event* getEvent(Event::Group group, int index) const; + Event* getEvent(Event::Group group, const QString &idName) const; int getNumEvents(Event::Group group = Event::Group::None) const; QStringList getScriptLabels(Event::Group group = Event::Group::None); QString getScriptsFilePath() const; diff --git a/include/editor.h b/include/editor.h index 4c7bff02..b56f42d4 100644 --- a/include/editor.h +++ b/include/editor.h @@ -251,11 +251,11 @@ private slots: signals: void eventsChanged(); + void openEventMap(Event*); void openConnectedMap(MapConnection*); void wildMonTableOpened(EncounterTableModel*); void wildMonTableClosed(); void wildMonTableEdited(); - void warpEventDoubleClicked(QString, int, Event::Group); void currentMetatilesSelectionChanged(); void mapRulerStatusChanged(const QString &); void tilesetUpdated(QString); diff --git a/include/mainwindow.h b/include/mainwindow.h index d8fe18a3..e3cdd62f 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -177,7 +177,7 @@ private slots: void on_action_Save_Project_triggered(); void save(bool currentOnly = false); - void openWarpMap(QString map_name, int event_id, Event::Group event_group); + void openEventMap(Event *event); void duplicate(); void setClipboardData(poryjson::Json::object); diff --git a/include/ui/draggablepixmapitem.h b/include/ui/draggablepixmapitem.h index debf1e41..5c617099 100644 --- a/include/ui/draggablepixmapitem.h +++ b/include/ui/draggablepixmapitem.h @@ -42,13 +42,14 @@ signals: void positionChanged(Event *event); void xChanged(int); void yChanged(int); - void spriteChanged(QPixmap pixmap); + void spriteChanged(const QPixmap &pixmap); + void doubleClicked(Event *event); protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent*) override; virtual void mouseMoveEvent(QGraphicsSceneMouseEvent*) override; virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override; - virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override; + virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override { emit doubleClicked(this->event); } }; #endif // DRAGGABLEPIXMAPITEM_H diff --git a/src/core/events.cpp b/src/core/events.cpp index ebb1ac49..e132f277 100644 --- a/src/core/events.cpp +++ b/src/core/events.cpp @@ -275,7 +275,7 @@ bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) { this->setY(readInt(&json, "y")); this->setIdName(readString(&json, "local_id")); this->setGfx(readString(&json, "graphics_id")); - this->setTargetID(readInt(&json, "target_local_id")); + this->setTargetID(readString(&json, "target_local_id")); // Log a warning if "target_map" isn't a known map ID, but don't overwrite user data. const QString mapConstant = readString(&json, "target_map"); @@ -289,7 +289,7 @@ bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) { void CloneObjectEvent::setDefaultValues(Project *project) { this->setGfx(project->gfxDefines.key(0, "0")); - this->setTargetID(1); + this->setTargetID(QString::number(Event::getIndexOffset(Event::Group::Object))); if (this->getMap()) this->setTargetMap(this->getMap()->name()); } @@ -308,9 +308,8 @@ QSet CloneObjectEvent::getExpectedFields() { void CloneObjectEvent::loadPixmap(Project *project) { // Try to get the targeted object to clone - int eventIndex = this->targetID - 1; Map *clonedMap = project->loadMap(this->targetMap); - Event *clonedEvent = clonedMap ? clonedMap->getEvent(Event::Group::Object, eventIndex) : nullptr; + Event *clonedEvent = clonedMap ? clonedMap->getEvent(Event::Group::Object, this->targetID) : nullptr; if (clonedEvent && clonedEvent->getEventType() == Event::Type::Object) { // Get graphics data from cloned object diff --git a/src/core/map.cpp b/src/core/map.cpp index 330132a1..5e5d443f 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -194,6 +194,21 @@ Event* Map::getEvent(Event::Group group, int index) const { return m_events[group].value(index, nullptr); } +Event* Map::getEvent(Event::Group group, const QString &idName) const { + bool idIsNumber; + int id = idName.toInt(&idIsNumber, 0); + if (idIsNumber) + return getEvent(group, id - Event::getIndexOffset(group)); + + auto events = getEvents(group); + for (const auto &event : events) { + if (event->getIdName() == idName) { + return event; + } + } + return nullptr; +} + int Map::getNumEvents(Event::Group group) const { if (group == Event::Group::None) { // Total number of events diff --git a/src/editor.cpp b/src/editor.cpp index 19acbe60..282ec52c 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1699,6 +1699,7 @@ void Editor::displayMapEvents() { DraggablePixmapItem *Editor::addEventPixmapItem(Event *event) { this->project->loadEventPixmap(event); auto item = new DraggablePixmapItem(event, this); + connect(item, &DraggablePixmapItem::doubleClicked, this, &Editor::openEventMap); redrawEventPixmapItem(item); this->events_group->addToGroup(item); return item; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 28d7f996..237ca5c4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -338,7 +338,7 @@ void MainWindow::initEditor() { this->editor = new Editor(ui); connect(this->editor, &Editor::eventsChanged, this, &MainWindow::updateEvents); connect(this->editor, &Editor::openConnectedMap, this, &MainWindow::onOpenConnectedMap); - connect(this->editor, &Editor::warpEventDoubleClicked, this, &MainWindow::openWarpMap); + connect(this->editor, &Editor::openEventMap, this, &MainWindow::openEventMap); connect(this->editor, &Editor::currentMetatilesSelectionChanged, this, &MainWindow::currentMetatilesSelectionChanged); connect(this->editor, &Editor::wildMonTableEdited, this, &MainWindow::markMapEdited); connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged); @@ -1055,19 +1055,56 @@ void MainWindow::refreshCollisionSelector() { on_horizontalSlider_CollisionZoom_valueChanged(ui->horizontalSlider_CollisionZoom->value()); } -void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_group) { - // Open the destination map. - if (!userSetMap(map_name)) +// Some events (like warps) have data that refers to an event on a different map. +// This function opens that map, and selects the event it's referring to. +void MainWindow::openEventMap(Event *sourceEvent) { + if (!sourceEvent || !this->editor->map) return; + + QString targetMapName; + QString targetEventIdName; + Event::Group targetEventGroup; + + Event::Type eventType = sourceEvent->getEventType(); + if (eventType == Event::Type::Warp) { + // Warp events open to their destination warp event. + WarpEvent *warp = dynamic_cast(sourceEvent); + targetMapName = warp->getDestinationMap(); + targetEventIdName = warp->getDestinationWarpID(); + targetEventGroup = Event::Group::Warp; + } else if (eventType == Event::Type::CloneObject) { + // Clone object events open to their target object event. + CloneObjectEvent *clone = dynamic_cast(sourceEvent); + targetMapName = clone->getTargetMap(); + targetEventIdName = clone->getTargetID(); + targetEventGroup = Event::Group::Object; + } else if (eventType == Event::Type::SecretBase) { + // Secret Bases open to their secret base entrance + const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix); + SecretBaseEvent *base = dynamic_cast(sourceEvent); + QString baseId = base->getBaseID(); + targetMapName = this->editor->project->mapConstantsToMapNames.value(mapPrefix + baseId.left(baseId.lastIndexOf("_"))); + targetEventIdName = "0"; + targetEventGroup = Event::Group::Warp; + } else if (eventType == Event::Type::HealLocation && projectConfig.healLocationRespawnDataEnabled) { + // Heal location events open to their respawn NPC + HealLocationEvent *heal = dynamic_cast(sourceEvent); + targetMapName = heal->getRespawnMapName(); + targetEventIdName = heal->getRespawnNPC(); + targetEventGroup = Event::Group::Object; + } else { + // Other event types have no target map to open. + return; + } + if (!userSetMap(targetMapName)) return; - // Select the target event. - int index = event_id - Event::getIndexOffset(event_group); - Event* event = this->editor->map->getEvent(event_group, index); - if (event) { - this->editor->selectMapEvent(event); + // Map opened successfully, now try to select the targeted event on that map. + Event* targetEvent = this->editor->map->getEvent(targetEventGroup, targetEventIdName); + if (targetEvent) { + this->editor->selectMapEvent(targetEvent); } else { // Can still warp to this map, but can't select the specified event - logWarn(QString("%1 %2 doesn't exist on map '%3'").arg(Event::groupToString(event_group)).arg(event_id).arg(map_name)); + logWarn(QString("%1 '%2' doesn't exist on map '%3'").arg(Event::groupToString(targetEventGroup)).arg(targetEventIdName).arg(targetMapName)); } } diff --git a/src/project.cpp b/src/project.cpp index 6f225ff6..e02db858 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -162,8 +162,10 @@ void Project::clearTilesetCache() { Map* Project::loadMap(const QString &mapName) { Map* map = this->maps.value(mapName); - if (!map) + if (!map) { + logError(QString("Unknown map name '%1'.").arg(mapName)); return nullptr; + } if (isMapLoaded(map)) return map; @@ -445,7 +447,12 @@ bool Project::loadLayout(Layout *layout) { Layout *Project::loadLayout(QString layoutId) { Layout *layout = this->mapLayouts.value(layoutId); - if (!layout || !loadLayout(layout)) { + if (!layout) { + logError(QString("Unknown layout ID '%1'.").arg(layoutId)); + return nullptr; + } + + if (!loadLayout(layout)) { logError(QString("Failed to load layout '%1'").arg(layoutId)); return nullptr; } diff --git a/src/ui/draggablepixmapitem.cpp b/src/ui/draggablepixmapitem.cpp index 31068fee..53cdd90a 100644 --- a/src/ui/draggablepixmapitem.cpp +++ b/src/ui/draggablepixmapitem.cpp @@ -103,31 +103,3 @@ void DraggablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouse) { this->editor->selectMapEvent(this->event); } } - -// Events with properties that specify a map will open that map when double-clicked. -void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) { - Event::Type eventType = this->event->getEventType(); - if (eventType == Event::Type::Warp) { - WarpEvent *warp = dynamic_cast(this->event); - QString destMap = warp->getDestinationMap(); - int warpId = ParseUtil::gameStringToInt(warp->getDestinationWarpID()); - emit editor->warpEventDoubleClicked(destMap, warpId, Event::Group::Warp); - } - else if (eventType == Event::Type::CloneObject) { - CloneObjectEvent *clone = dynamic_cast(this->event); - emit editor->warpEventDoubleClicked(clone->getTargetMap(), clone->getTargetID(), Event::Group::Object); - } - else if (eventType == Event::Type::SecretBase) { - const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix); - SecretBaseEvent *base = dynamic_cast(this->event); - QString baseId = base->getBaseID(); - QString destMap = editor->project->mapConstantsToMapNames.value(mapPrefix + baseId.left(baseId.lastIndexOf("_"))); - emit editor->warpEventDoubleClicked(destMap, 0, Event::Group::Warp); - } - else if (eventType == Event::Type::HealLocation && projectConfig.healLocationRespawnDataEnabled) { - HealLocationEvent *heal = dynamic_cast(this->event); - const QString localIdName = heal->getRespawnNPC(); - int localId = 0; // TODO: Get value from localIdName - emit editor->warpEventDoubleClicked(heal->getRespawnMapName(), localId, Event::Group::Object); - } -} diff --git a/src/ui/eventframes.cpp b/src/ui/eventframes.cpp index 82334722..c69d35da 100644 --- a/src/ui/eventframes.cpp +++ b/src/ui/eventframes.cpp @@ -453,13 +453,16 @@ void CloneObjectFrame::connectSignals(MainWindow *window) { }); // target id + // TODO: Replace spinner with combo box populated with local IDs from target map. this->spinner_target_id->disconnect(); + /* connect(this->spinner_target_id, QOverload::of(&QSpinBox::valueChanged), [this](int value) { this->clone->setTargetID(value); this->clone->getPixmapItem()->updatePixmap(); this->combo_sprite->setCurrentText(this->clone->getGfx()); this->clone->modify(); }); + */ } void CloneObjectFrame::initialize() { @@ -474,7 +477,7 @@ void CloneObjectFrame::initialize() { // target id this->spinner_target_id->setMinimum(1); this->spinner_target_id->setMaximum(126); - this->spinner_target_id->setValue(this->clone->getTargetID()); + //this->spinner_target_id->setValue(this->clone->getTargetID()); // target map this->combo_target_map->setTextItem(this->clone->getTargetMap());