From a2aa20ec460229f080609771ede25038ef3df5e8 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 19 Feb 2025 13:18:12 -0500 Subject: [PATCH 1/4] Generalize event loading --- include/core/events.h | 6 +-- include/project.h | 1 + src/core/events.cpp | 86 ++++++++++++------------------------- src/editor.cpp | 2 +- src/mainwindow.cpp | 8 ++-- src/project.cpp | 98 +++++++++++++------------------------------ 6 files changed, 65 insertions(+), 136 deletions(-) diff --git a/include/core/events.h b/include/core/events.h index bdf9d5a2..265ec541 100644 --- a/include/core/events.h +++ b/include/core/events.h @@ -186,9 +186,9 @@ public: void setIdName(QString newIdName) { this->idName = newIdName; } QString getIdName() const { return this->idName; } - static QString eventGroupToString(Event::Group group); - static QString eventTypeToString(Event::Type type); - static Event::Type eventTypeFromString(QString type); + static QString groupToString(Event::Group group); + static QString typeToString(Event::Type type); + static Event::Type typeFromString(QString type); static void clearIcons(); static void setIcons(); diff --git a/include/project.h b/include/project.h index f3a1093b..97b9a698 100644 --- a/include/project.h +++ b/include/project.h @@ -157,6 +157,7 @@ public: void initTopLevelMapFields(); bool readMapJson(const QString &mapName, QJsonDocument * out); + bool loadMapEvent(Map *map, const QJsonObject &json, Event::Type defaultType = Event::Type::None); bool loadMapData(Map*); bool readMapLayouts(); Layout *loadLayout(QString layoutId); diff --git a/src/core/events.cpp b/src/core/events.cpp index 87421035..648fb760 100644 --- a/src/core/events.cpp +++ b/src/core/events.cpp @@ -75,70 +75,36 @@ void Event::modify() { this->map->modify(); } -QString Event::eventGroupToString(Event::Group group) { - switch (group) { - case Event::Group::Object: - return "Object"; - case Event::Group::Warp: - return "Warp"; - case Event::Group::Coord: - return "Trigger"; - case Event::Group::Bg: - return "BG"; - case Event::Group::Heal: - return "Heal Location"; - default: - return ""; - } +const QMap groupToStringMap = { + {Event::Group::Object, "Object"}, + {Event::Group::Warp, "Warp"}, + {Event::Group::Coord, "Trigger"}, + {Event::Group::Bg, "BG"}, + {Event::Group::Heal, "Heal Location"}, +}; + +QString Event::groupToString(Event::Group group) { + return groupToStringMap.value(group); } -QString Event::eventTypeToString(Event::Type type) { - switch (type) { - case Event::Type::Object: - return "event_object"; - case Event::Type::CloneObject: - return "event_clone_object"; - case Event::Type::Warp: - return "event_warp"; - case Event::Type::Trigger: - return "event_trigger"; - case Event::Type::WeatherTrigger: - return "event_weather_trigger"; - case Event::Type::Sign: - return "event_sign"; - case Event::Type::HiddenItem: - return "event_hidden_item"; - case Event::Type::SecretBase: - return "event_secret_base"; - case Event::Type::HealLocation: - return "event_heal_location"; - default: - return ""; - } +const QMap typeToStringMap = { + {Event::Type::Object, "object"}, + {Event::Type::CloneObject, "clone_object"}, + {Event::Type::Warp, "warp"}, + {Event::Type::Trigger, "trigger"}, + {Event::Type::WeatherTrigger, "weather"}, + {Event::Type::Sign, "sign"}, + {Event::Type::HiddenItem, "hidden_item"}, + {Event::Type::SecretBase, "secret_base"}, + {Event::Type::HealLocation, "heal_location"}, +}; + +QString Event::typeToString(Event::Type type) { + return typeToStringMap.value(type); } -Event::Type Event::eventTypeFromString(QString type) { - if (type == "event_object") { - return Event::Type::Object; - } else if (type == "event_clone_object") { - return Event::Type::CloneObject; - } else if (type == "event_warp") { - return Event::Type::Warp; - } else if (type == "event_trigger") { - return Event::Type::Trigger; - } else if (type == "event_weather_trigger") { - return Event::Type::WeatherTrigger; - } else if (type == "event_sign") { - return Event::Type::Sign; - } else if (type == "event_hidden_item") { - return Event::Type::HiddenItem; - } else if (type == "event_secret_base") { - return Event::Type::SecretBase; - } else if (type == "event_heal_location") { - return Event::Type::HealLocation; - } else { - return Event::Type::None; - } +Event::Type Event::typeFromString(QString type) { + return typeToStringMap.key(type, Event::Type::None); } void Event::loadPixmap(Project *) { diff --git a/src/editor.cpp b/src/editor.cpp index 6a2e0c20..f654b805 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -2092,7 +2092,7 @@ void Editor::duplicateSelectedEvents() { Event *original = selected_events->at(i)->event; Event::Type eventType = original->getEventType(); if (eventLimitReached(eventType)) { - logWarn(QString("Skipping duplication, the map limit for events of type '%1' has been reached.").arg(Event::eventTypeToString(eventType))); + logWarn(QString("Skipping duplication, the map limit for events of type '%1' has been reached.").arg(Event::typeToString(eventType))); continue; } Event *duplicate = original->duplicate(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a38b3bd0..785c77af 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1039,7 +1039,7 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_ } } // 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::eventGroupToString(event_group)).arg(event_id).arg(map_name)); + logWarn(QString("%1 %2 doesn't exist on map '%3'").arg(Event::groupToString(event_group)).arg(event_id).arg(map_name)); } void MainWindow::displayMapProperties() { @@ -1639,7 +1639,7 @@ void MainWindow::copy() { for (auto item : events) { Event *event = item->event; OrderedJson::object eventContainer; - eventContainer["event_type"] = Event::eventTypeToString(event->getEventType()); + eventContainer["event_type"] = Event::typeToString(event->getEventType()); OrderedJson::object eventJson = event->buildEventJson(editor->project); eventContainer["event"] = eventJson; eventsArray.append(eventContainer); @@ -1751,7 +1751,7 @@ void MainWindow::paste() { for (QJsonValue event : events) { // paste the event to the map const QString typeString = event["event_type"].toString(); - Event::Type type = Event::eventTypeFromString(typeString); + Event::Type type = Event::typeFromString(typeString); if (this->editor->eventLimitReached(type)) { logWarn(QString("Cannot paste event, the limit for type '%1' has been reached.").arg(typeString)); @@ -2009,7 +2009,7 @@ void MainWindow::addNewEvent(Event::Type type) { void MainWindow::tryAddEventTab(QWidget * tab) { auto group = getEventGroupFromTabWidget(tab); if (editor->map->getNumEvents(group)) - ui->tabWidget_EventType->addTab(tab, QString("%1s").arg(Event::eventGroupToString(group))); + ui->tabWidget_EventType->addTab(tab, QString("%1s").arg(Event::groupToString(group))); } void MainWindow::displayEventTabs() { diff --git a/src/project.cpp b/src/project.cpp index 38b1810b..21dc5199 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -203,6 +203,21 @@ bool Project::readMapJson(const QString &mapName, QJsonDocument * out) { return true; } +bool Project::loadMapEvent(Map *map, const QJsonObject &json, Event::Type defaultType) { + QString typeString = ParseUtil::jsonToQString(json["type"]); + Event::Type type = typeString.isEmpty() ? defaultType : Event::typeFromString(typeString); + Event* event = Event::create(type); + if (!event) { + return false; + } + if (!event->loadFromJson(json, this)) { + delete event; + return false; + } + map->addEvent(event); + return true; +} + bool Project::loadMapData(Map* map) { if (!map->isPersistedToFile()) { return true; @@ -241,75 +256,22 @@ bool Project::loadMapData(Map* map) { // Events map->resetEvents(); - QJsonArray objectEventsArr = mapObj["object_events"].toArray(); - for (int i = 0; i < objectEventsArr.size(); i++) { - QJsonObject event = objectEventsArr[i].toObject(); - // If clone objects are not enabled then no type field is present - QString type = projectConfig.eventCloneObjectEnabled ? ParseUtil::jsonToQString(event["type"]) : "object"; - if (type.isEmpty() || type == "object") { - ObjectEvent *object = new ObjectEvent(); - object->loadFromJson(event, this); - map->addEvent(object); - } else if (type == "clone") { - CloneObjectEvent *clone = new CloneObjectEvent(); - if (clone->loadFromJson(event, this)) { - map->addEvent(clone); + static const QMap defaultEventTypes = { + // Map of the expected keys for each event group, and the default type of that group. + // If the default type is Type::None then each event must specify its type, or its an error. + {"object_events", Event::Type::Object}, + {"warp_events", Event::Type::Warp}, + {"coord_events", Event::Type::None}, + {"bg_events", Event::Type::None}, + }; + for (auto i = defaultEventTypes.constBegin(); i != defaultEventTypes.constEnd(); i++) { + QString eventGroupKey = i.key(); + Event::Type defaultType = i.value(); + const QJsonArray eventsJsonArr = mapObj[eventGroupKey].toArray(); + for (int i = 0; i < eventsJsonArr.size(); i++) { + if (!loadMapEvent(map, eventsJsonArr.at(i).toObject(), defaultType)) { + logError(QString("Failed to load event for %1, in %2 at index %3.").arg(map->name()).arg(eventGroupKey).arg(i)); } - else { - delete clone; - } - } else { - logError(QString("Map %1 object_event %2 has invalid type '%3'. Must be 'object' or 'clone'.").arg(map->name()).arg(i).arg(type)); - } - } - - QJsonArray warpEventsArr = mapObj["warp_events"].toArray(); - for (int i = 0; i < warpEventsArr.size(); i++) { - QJsonObject event = warpEventsArr[i].toObject(); - WarpEvent *warp = new WarpEvent(); - if (warp->loadFromJson(event, this)) { - map->addEvent(warp); - } - else { - delete warp; - } - } - - QJsonArray coordEventsArr = mapObj["coord_events"].toArray(); - for (int i = 0; i < coordEventsArr.size(); i++) { - QJsonObject event = coordEventsArr[i].toObject(); - QString type = ParseUtil::jsonToQString(event["type"]); - if (type == "trigger") { - TriggerEvent *coord = new TriggerEvent(); - coord->loadFromJson(event, this); - map->addEvent(coord); - } else if (type == "weather") { - WeatherTriggerEvent *coord = new WeatherTriggerEvent(); - coord->loadFromJson(event, this); - map->addEvent(coord); - } else { - logError(QString("Map %1 coord_event %2 has invalid type '%3'. Must be 'trigger' or 'weather'.").arg(map->name()).arg(i).arg(type)); - } - } - - QJsonArray bgEventsArr = mapObj["bg_events"].toArray(); - for (int i = 0; i < bgEventsArr.size(); i++) { - QJsonObject event = bgEventsArr[i].toObject(); - QString type = ParseUtil::jsonToQString(event["type"]); - if (type == "sign") { - SignEvent *bg = new SignEvent(); - bg->loadFromJson(event, this); - map->addEvent(bg); - } else if (type == "hidden_item") { - HiddenItemEvent *bg = new HiddenItemEvent(); - bg->loadFromJson(event, this); - map->addEvent(bg); - } else if (type == "secret_base") { - SecretBaseEvent *bg = new SecretBaseEvent(); - bg->loadFromJson(event, this); - map->addEvent(bg); - } else { - logError(QString("Map %1 bg_event %2 has invalid type '%3'. Must be 'sign', 'hidden_item', or 'secret_base'.").arg(map->name()).arg(i).arg(type)); } } From 7fc985fc1dc7071473ccb3ae31a5aa5ca96e15f7 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 19 Feb 2025 13:25:21 -0500 Subject: [PATCH 2/4] Recognize local_id field --- src/core/events.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/core/events.cpp b/src/core/events.cpp index 648fb760..3d2ef9d2 100644 --- a/src/core/events.cpp +++ b/src/core/events.cpp @@ -155,6 +155,7 @@ Event *ObjectEvent::duplicate() const { copy->setX(this->getX()); copy->setY(this->getY()); copy->setElevation(this->getElevation()); + copy->setIdName(this->getIdName()); copy->setGfx(this->getGfx()); copy->setMovement(this->getMovement()); copy->setRadiusX(this->getRadiusX()); @@ -182,6 +183,9 @@ OrderedJson::object ObjectEvent::buildEventJson(Project *) { if (projectConfig.eventCloneObjectEnabled) { objectJson["type"] = "object"; } + QString idName = this->getIdName(); + if (!idName.isEmpty()) + objectJson["local_id"] = idName; objectJson["graphics_id"] = this->getGfx(); objectJson["x"] = this->getX(); objectJson["y"] = this->getY(); @@ -202,6 +206,7 @@ bool ObjectEvent::loadFromJson(const QJsonObject &json, Project *) { this->setX(ParseUtil::jsonToInt(json["x"])); this->setY(ParseUtil::jsonToInt(json["y"])); this->setElevation(ParseUtil::jsonToInt(json["elevation"])); + this->setIdName(ParseUtil::jsonToQString(json["local_id"])); this->setGfx(ParseUtil::jsonToQString(json["graphics_id"])); this->setMovement(ParseUtil::jsonToQString(json["movement_type"])); this->setRadiusX(ParseUtil::jsonToInt(json["movement_range_x"])); @@ -229,6 +234,7 @@ void ObjectEvent::setDefaultValues(Project *project) { } const QSet expectedObjectFields = { + "local_id", "graphics_id", "elevation", "movement_type", @@ -334,6 +340,7 @@ Event *CloneObjectEvent::duplicate() const { copy->setX(this->getX()); copy->setY(this->getY()); copy->setElevation(this->getElevation()); + copy->setIdName(this->getIdName()); copy->setGfx(this->getGfx()); copy->setTargetID(this->getTargetID()); copy->setTargetMap(this->getTargetMap()); @@ -354,6 +361,9 @@ OrderedJson::object CloneObjectEvent::buildEventJson(Project *project) { OrderedJson::object cloneJson; cloneJson["type"] = "clone"; + QString idName = this->getIdName(); + if (!idName.isEmpty()) + cloneJson["local_id"] = idName; cloneJson["graphics_id"] = this->getGfx(); cloneJson["x"] = this->getX(); cloneJson["y"] = this->getY(); @@ -368,6 +378,7 @@ OrderedJson::object CloneObjectEvent::buildEventJson(Project *project) { bool CloneObjectEvent::loadFromJson(const QJsonObject &json, Project *project) { this->setX(ParseUtil::jsonToInt(json["x"])); this->setY(ParseUtil::jsonToInt(json["y"])); + this->setIdName(ParseUtil::jsonToQString(json["local_id"])); this->setGfx(ParseUtil::jsonToQString(json["graphics_id"])); this->setTargetID(ParseUtil::jsonToInt(json["target_local_id"])); @@ -390,6 +401,7 @@ void CloneObjectEvent::setDefaultValues(Project *project) { const QSet expectedCloneObjectFields = { "type", + "local_id", "graphics_id", "target_local_id", "target_map", From ac8db41299d04a88f41c3c25b7d882d87be0c5b8 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 16 Feb 2025 15:31:20 -0500 Subject: [PATCH 3/4] Add event group limit --- forms/projectsettingseditor.ui | 23 +++++++++ include/config.h | 2 + include/editor.h | 5 +- include/mainwindow.h | 1 - include/project.h | 5 +- src/config.cpp | 3 ++ src/editor.cpp | 81 +++++++++++++++++++------------- src/mainwindow.cpp | 49 +++++-------------- src/project.cpp | 19 +++++--- src/ui/projectsettingseditor.cpp | 3 ++ 10 files changed, 107 insertions(+), 84 deletions(-) diff --git a/forms/projectsettingseditor.ui b/forms/projectsettingseditor.ui index da006eff..a088d87e 100644 --- a/forms/projectsettingseditor.ui +++ b/forms/projectsettingseditor.ui @@ -1341,6 +1341,29 @@ + + + + + + + Maximum Events per Event group + + + + + + + <html><head/><body><p>Maps cannot have more than this number of events in each event group. Object events are additionally limited by 'define_obj_event_count' on the Identifiers tab.</p></body></html> + + + 1 + + + + + + diff --git a/include/config.h b/include/config.h index 7f263da0..d0c2ff9f 100644 --- a/include/config.h +++ b/include/config.h @@ -319,6 +319,7 @@ public: this->unusedTileNormal = 0x3014; this->unusedTileCovered = 0x0000; this->unusedTileSplit = 0x0000; + this->maxEventsPerGroup = 255; this->identifiers.clear(); this->readKeys.clear(); } @@ -388,6 +389,7 @@ public: int collisionSheetWidth; int collisionSheetHeight; QList warpBehaviors; + int maxEventsPerGroup; protected: virtual QString getConfigFilepath() override; diff --git a/include/editor.h b/include/editor.h index 689d2f4f..e2e09c42 100644 --- a/include/editor.h +++ b/include/editor.h @@ -110,9 +110,9 @@ public: DraggablePixmapItem *addEventPixmapItem(Event *event); void removeEventPixmapItem(Event *event); - bool eventLimitReached(Map *, Event::Type); + bool canAddEvents(const QList &events); void selectMapEvent(DraggablePixmapItem *item, bool toggle = false); - DraggablePixmapItem *addNewEvent(Event::Type type); + Event *addNewEvent(Event::Type type); void updateSelectedEvents(); void duplicateSelectedEvents(); void redrawAllEvents(); @@ -185,7 +185,6 @@ public: void shouldReselectEvents(); void scaleMapView(int); static void openInTextEditor(const QString &path, int lineNum = 0); - bool eventLimitReached(Event::Type type); void setCollisionGraphics(); public slots: diff --git a/include/mainwindow.h b/include/mainwindow.h index 805899a1..412362c5 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -218,7 +218,6 @@ private slots: void on_actionMove_triggered(); void on_actionMap_Shift_triggered(); - void addNewEvent(Event::Type type); void tryAddEventTab(QWidget * tab); void displayEventTabs(); void updateSelectedEvents(); diff --git a/include/project.h b/include/project.h index 97b9a698..c2707063 100644 --- a/include/project.h +++ b/include/project.h @@ -245,7 +245,7 @@ public: static int getMapDataSize(int width, int height); static bool mapDimensionsValid(int width, int height); bool calculateDefaultMapSize(); - static int getMaxObjectEvents(); + int getMaxEvents(Event::Group group); static QString getEmptyMapsecName(); static QString getMapGroupPrefix(); @@ -263,6 +263,8 @@ private: void ignoreWatchedFileTemporarily(QString filepath); void recordFileChange(const QString &filepath); + int maxEventsPerGroup; + int maxObjectEvents; static int num_tiles_primary; static int num_tiles_total; static int num_metatiles_primary; @@ -270,7 +272,6 @@ private: static int num_pals_total; static int max_map_data_size; static int default_map_dimension; - static int max_object_events; signals: void fileChanged(const QString &filepath); diff --git a/src/config.cpp b/src/config.cpp index b22972a4..89ab50f9 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -803,6 +803,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) { const QStringList behaviorList = value.split(",", Qt::SkipEmptyParts); for (auto s : behaviorList) this->warpBehaviors.append(getConfigUint32(key, s)); + } else if (key == "max_events_per_group") { + this->maxEventsPerGroup = getConfigInteger(key, value, 1, INT_MAX, 255); } else { logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); } @@ -898,6 +900,7 @@ QMap ProjectConfig::getKeyValueMap() { for (const auto &value : this->warpBehaviors) warpBehaviorStrs.append("0x" + QString("%1").arg(value, 2, 16, QChar('0')).toUpper()); map.insert("warp_behaviors", warpBehaviorStrs.join(",")); + map.insert("max_events_per_group", QString::number(this->maxEventsPerGroup)); return map; } diff --git a/src/editor.cpp b/src/editor.cpp index f654b805..a7ce2390 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1330,17 +1330,13 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i } else { // Left-clicking while in paint mode will add a new event of the // type of the first currently selected events. - // Disallow adding heal locations, deleting them is not possible yet Event::Type eventType = Event::Type::Object; if (this->selected_events->size() > 0) eventType = this->selected_events->first()->event->getEventType(); - DraggablePixmapItem *newEvent = addNewEvent(eventType); - if (newEvent) { - newEvent->move(pos.x(), pos.y()); - emit eventsChanged(); - selectMapEvent(newEvent); - } + Event* event = addNewEvent(eventType); + if (event && event->getPixmapItem()) + event->getPixmapItem()->moveTo(pos); } } else if (eventEditAction == EditAction::Select) { // do nothing here, at least for now @@ -2083,47 +2079,66 @@ void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) { } } -void Editor::duplicateSelectedEvents() { - if (!selected_events || !selected_events->length() || !map || !current_view || this->getEditingLayout()) - return; +bool Editor::canAddEvents(const QList &events) { + if (!this->project || !this->map) + return false; - QList selectedEvents; - for (int i = 0; i < selected_events->length(); i++) { - Event *original = selected_events->at(i)->event; - Event::Type eventType = original->getEventType(); - if (eventLimitReached(eventType)) { - logWarn(QString("Skipping duplication, the map limit for events of type '%1' has been reached.").arg(Event::typeToString(eventType))); - continue; + QMap newEventCounts; + for (const auto &event : events) { + Event::Group group = event->getEventGroup(); + int maxEvents = this->project->getMaxEvents(group); + if (this->map->getNumEvents(group) + newEventCounts[group]++ >= maxEvents) { + return false; } - Event *duplicate = original->duplicate(); - duplicate->setX(duplicate->getX() + 1); - duplicate->setY(duplicate->getY() + 1); - selectedEvents.append(duplicate); } - map->commit(new EventDuplicate(this, map, selectedEvents)); + return true; } -DraggablePixmapItem *Editor::addNewEvent(Event::Type type) { - if (!project || !map || eventLimitReached(type)) +void Editor::duplicateSelectedEvents() { + if (!selected_events || !selected_events->length() || !project || !map || !current_view || this->getEditingLayout()) + return; + + QList duplicatedEvents; + for (int i = 0; i < selected_events->length(); i++) { + duplicatedEvents.append(selected_events->at(i)->event->duplicate()); + } + if (!canAddEvents(duplicatedEvents)) { + WarningMessage::show(QStringLiteral("Unable to duplicate, the maximum number of events would be exceeded."), ui->graphicsView_Map); + qDeleteAll(duplicatedEvents); + return; + } + this->map->commit(new EventDuplicate(this, this->map, duplicatedEvents)); +} + +Event *Editor::addNewEvent(Event::Type type) { + if (!this->project || !this->map) return nullptr; + Event::Group group = Event::typeToGroup(type); + int maxEvents = this->project->getMaxEvents(group); + if (this->map->getNumEvents(group) >= maxEvents) { + WarningMessage::show(QString("The maximum number of %1 events (%2) has been reached.").arg(Event::groupToString(group)).arg(maxEvents), ui->graphicsView_Map); + return nullptr; + } + Event *event = Event::create(type); if (!event) return nullptr; event->setMap(this->map); event->setDefaultValues(this->project); - map->commit(new EventCreate(this, map, event)); - return event->getPixmapItem(); -} -// Currently only object events have an explicit limit -bool Editor::eventLimitReached(Event::Type event_type) { - if (project && map) { - if (Event::typeToGroup(event_type) == Event::Group::Object) - return map->getNumEvents(Event::Group::Object) >= project->getMaxObjectEvents(); + // This will add the event to the map, create the event pixmap item, and select the event. + this->map->commit(new EventCreate(this, this->map, event)); + + auto pixmapItem = event->getPixmapItem(); + if (pixmapItem) { + auto halfSize = ui->graphicsView_Map->size() / 2; + auto centerPos = ui->graphicsView_Map->mapToScene(halfSize.width(), halfSize.height()); + pixmapItem->moveTo(Metatile::coordFromPixmapCoord(centerPos)); } - return false; + + return event; } void Editor::deleteSelectedEvents() { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 785c77af..5c7e5cdb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -264,8 +264,6 @@ void MainWindow::initCustomUI() { } void MainWindow::initExtraSignals() { - // other signals - connect(ui->newEventToolButton, &NewEventToolButton::newEventAdded, this, &MainWindow::addNewEvent); connect(ui->tabWidget_EventType, &QTabWidget::currentChanged, this, &MainWindow::eventTabChanged); // Change pages on wild encounter groups @@ -343,6 +341,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->newEventToolButton, &NewEventToolButton::newEventAdded, this->editor, &Editor::addNewEvent); connect(ui->toolButton_deleteEvent, &QAbstractButton::clicked, this->editor, &Editor::deleteSelectedEvents); this->loadUserSettings(); @@ -1304,7 +1303,7 @@ void MainWindow::onNewMapCreated(Map *newMap, const QString &groupName) { logInfo(QString("Created a new map named %1.").arg(newMap->name())); if (newMap->needsHealLocation()) { - addNewEvent(Event::Type::HealLocation); + this->editor->addNewEvent(Event::Type::HealLocation); } // TODO: Creating a new map shouldn't be automatically saved. @@ -1750,14 +1749,7 @@ void MainWindow::paste() { QJsonArray events = pasteObject["events"].toArray(); for (QJsonValue event : events) { // paste the event to the map - const QString typeString = event["event_type"].toString(); - Event::Type type = Event::typeFromString(typeString); - - if (this->editor->eventLimitReached(type)) { - logWarn(QString("Cannot paste event, the limit for type '%1' has been reached.").arg(typeString)); - continue; - } - + Event::Type type = Event::typeFromString(event["event_type"].toString()); Event *pasteEvent = Event::create(type); if (!pasteEvent) continue; @@ -1766,12 +1758,16 @@ void MainWindow::paste() { pasteEvent->setMap(this->editor->map); newEvents.append(pasteEvent); } + if (newEvents.empty()) + return; - if (!newEvents.empty()) { - editor->map->commit(new EventPaste(this->editor, editor->map, newEvents)); - updateEvents(); + if (!this->editor->canAddEvents(newEvents)) { + WarningMessage::show(QStringLiteral("Unable to paste, the maximum number of events would be exceeded."), this); + qDeleteAll(newEvents); + return; } - + this->editor->map->commit(new EventPaste(this->editor, this->editor->map, newEvents)); + updateEvents(); break; } } @@ -1983,29 +1979,6 @@ void MainWindow::resetMapViewScale() { editor->scaleMapView(0); } -void MainWindow::addNewEvent(Event::Type type) { - if (editor && editor->project) { - DraggablePixmapItem *item = editor->addNewEvent(type); - if (item) { - auto halfSize = ui->graphicsView_Map->size() / 2; - auto centerPos = ui->graphicsView_Map->mapToScene(halfSize.width(), halfSize.height()); - item->moveTo(Metatile::coordFromPixmapCoord(centerPos)); - updateEvents(); - editor->selectMapEvent(item); - } else { - WarningMessage msgBox(QStringLiteral("Failed to add new event."), this); - if (Event::typeToGroup(type) == Event::Group::Object) { - msgBox.setInformativeText(QString("The limit for object events (%1) has been reached.\n\n" - "This limit can be adjusted with %2 in '%3'.") - .arg(editor->project->getMaxObjectEvents()) - .arg(projectConfig.getIdentifier(ProjectIdentifier::define_obj_event_count)) - .arg(projectConfig.getFilePath(ProjectFilePath::constants_global))); - } - msgBox.exec(); - } - } -} - void MainWindow::tryAddEventTab(QWidget * tab) { auto group = getEventGroupFromTabWidget(tab); if (editor->map->getNumEvents(group)) diff --git a/src/project.cpp b/src/project.cpp index 21dc5199..b25b3776 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -30,7 +30,6 @@ int Project::num_pals_primary = 6; int Project::num_pals_total = 13; int Project::max_map_data_size = 10240; // 0x2800 int Project::default_map_dimension = 20; -int Project::max_object_events = 64; Project::Project(QObject *parent) : QObject(parent) @@ -2578,21 +2577,22 @@ bool Project::readMiscellaneousConstants() { fileWatcher.addPath(root + "/" + filename); QMap defines = parser.readCDefinesByName(filename, {maxObjectEventsName}); + this->maxObjectEvents = 64; // Default value auto it = defines.find(maxObjectEventsName); if (it != defines.end()) { if (it.value() > 0) { - Project::max_object_events = it.value(); + this->maxObjectEvents = it.value(); } else { logWarn(QString("Value for '%1' is %2, must be greater than 0. Using default (%3) instead.") .arg(maxObjectEventsName) .arg(it.value()) - .arg(Project::max_object_events)); + .arg(this->maxObjectEvents)); } } else { logWarn(QString("Value for '%1' not found. Using default (%2) instead.") .arg(maxObjectEventsName) - .arg(Project::max_object_events)); + .arg(this->maxObjectEvents)); } return true; @@ -2943,9 +2943,14 @@ bool Project::calculateDefaultMapSize(){ return true; } -int Project::getMaxObjectEvents() -{ - return Project::max_object_events; +// Object events have their own limit specified by ProjectIdentifier::define_obj_event_count. +// The default value for this is 64. All events (object events included) are also limited by +// the data types of the event counters in the project. This would normally be u8, so the limit is 255. +// We let the users tell us this limit in case they change these data types. +int Project::getMaxEvents(Event::Group group) { + if (group == Event::Group::Object) + return qMin(this->maxObjectEvents, projectConfig.maxEventsPerGroup); + return projectConfig.maxEventsPerGroup; } QString Project::getEmptyMapDefineName() { diff --git a/src/ui/projectsettingseditor.cpp b/src/ui/projectsettingseditor.cpp index 1250e8dd..86614482 100644 --- a/src/ui/projectsettingseditor.cpp +++ b/src/ui/projectsettingseditor.cpp @@ -135,6 +135,7 @@ void ProjectSettingsEditor::initUi() { ui->spinBox_UnusedTileNormal->setMaximum(Tile::maxValue); ui->spinBox_UnusedTileCovered->setMaximum(Tile::maxValue); ui->spinBox_UnusedTileSplit->setMaximum(Tile::maxValue); + ui->spinBox_MaxEvents->setMaximum(INT_MAX); // The values for some of the settings we provide in this window can be determined using constants in the user's projects. // If the user has these constants we disable these settings in the UI -- they can modify them using their constants. @@ -464,6 +465,7 @@ void ProjectSettingsEditor::refresh() { ui->spinBox_UnusedTileNormal->setValue(projectConfig.unusedTileNormal); ui->spinBox_UnusedTileCovered->setValue(projectConfig.unusedTileCovered); ui->spinBox_UnusedTileSplit->setValue(projectConfig.unusedTileSplit); + ui->spinBox_MaxEvents->setValue(projectConfig.maxEventsPerGroup); // Set (and sync) border metatile IDs this->setBorderMetatileIds(false, projectConfig.newMapBorderMetatileIds); @@ -538,6 +540,7 @@ void ProjectSettingsEditor::save() { projectConfig.unusedTileNormal = ui->spinBox_UnusedTileNormal->value(); projectConfig.unusedTileCovered = ui->spinBox_UnusedTileCovered->value(); projectConfig.unusedTileSplit = ui->spinBox_UnusedTileSplit->value(); + projectConfig.maxEventsPerGroup = ui->spinBox_MaxEvents->value(); // Save line edit settings projectConfig.prefabFilepath = ui->lineEdit_PrefabsPath->text(); From 88f5a90b2feb097b5a4a464364ad948e28cba80b Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 16 Feb 2025 18:03:24 -0500 Subject: [PATCH 4/4] Convert selected_events from DraggablePixmapItem to Event --- include/core/map.h | 1 + include/editor.h | 7 ++- include/mainwindow.h | 2 +- src/core/editcommands.cpp | 21 ++------ src/core/map.cpp | 4 ++ src/editor.cpp | 91 +++++++++++++--------------------- src/mainwindow.cpp | 72 +++++++++++---------------- src/ui/draggablepixmapitem.cpp | 18 +++---- 8 files changed, 86 insertions(+), 130 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index b223536d..f68b4a2b 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -85,6 +85,7 @@ public: void removeEvent(Event *); void addEvent(Event *); int getIndexOfEvent(Event *) const; + bool hasEvent(Event *) const; void deleteConnections(); QList getConnections() const; diff --git a/include/editor.h b/include/editor.h index e2e09c42..0450cefe 100644 --- a/include/editor.h +++ b/include/editor.h @@ -111,14 +111,13 @@ public: DraggablePixmapItem *addEventPixmapItem(Event *event); void removeEventPixmapItem(Event *event); bool canAddEvents(const QList &events); - void selectMapEvent(DraggablePixmapItem *item, bool toggle = false); + void selectMapEvent(Event *event, bool toggle = false); Event *addNewEvent(Event::Type type); - void updateSelectedEvents(); + void updateEvents(); void duplicateSelectedEvents(); void redrawAllEvents(); void redrawEvents(const QList &events); void redrawEventPixmapItem(DraggablePixmapItem *item); - QList getEventPixmapItems(); qreal getEventOpacity(const Event *event) const; void updateCursorRectPos(int x, int y); @@ -153,7 +152,7 @@ public: CurrentSelectedMetatilesPixmapItem *current_metatile_selection_item = nullptr; QPointer movement_permissions_selector_item = nullptr; - QList *selected_events = nullptr; + QList selectedEvents; QPointer selected_connection_item = nullptr; QPointer connection_to_select = nullptr; diff --git a/include/mainwindow.h b/include/mainwindow.h index 412362c5..1aa0a413 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -332,7 +332,7 @@ private: MapHeaderForm *mapHeaderForm = nullptr; - QMap lastSelectedEvent; + QMap lastSelectedEvent; bool isProgrammaticEventTabChange; diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp index 94354896..0cc378fc 100644 --- a/src/core/editcommands.cpp +++ b/src/core/editcommands.cpp @@ -328,10 +328,7 @@ void EventCreate::redo() { map->addEvent(event); editor->addEventPixmapItem(event); - - // select this event - editor->selected_events->clear(); - editor->selectMapEvent(event->getPixmapItem()); + editor->selectMapEvent(event); } void EventCreate::undo() { @@ -374,9 +371,9 @@ void EventDelete::redo() { editor->removeEventPixmapItem(event); } - editor->selected_events->clear(); + editor->selectedEvents.clear(); if (nextSelectedEvent) - editor->selected_events->append(nextSelectedEvent->getPixmapItem()); + editor->selectedEvents.append(nextSelectedEvent); editor->shouldReselectEvents(); } @@ -386,11 +383,7 @@ void EventDelete::undo() { editor->addEventPixmapItem(event); } - // select these events - editor->selected_events->clear(); - for (Event *event : selectedEvents) { - editor->selected_events->append(event->getPixmapItem()); - } + editor->selectedEvents = selectedEvents; editor->shouldReselectEvents(); QUndoCommand::undo(); @@ -427,11 +420,7 @@ void EventDuplicate::redo() { editor->addEventPixmapItem(event); } - // select these events - editor->selected_events->clear(); - for (Event *event : selectedEvents) { - editor->selected_events->append(event->getPixmapItem()); - } + editor->selectedEvents = selectedEvents; editor->shouldReselectEvents(); } diff --git a/src/core/map.cpp b/src/core/map.cpp index d2ab8ef6..d45a4c1f 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -229,6 +229,10 @@ int Map::getIndexOfEvent(Event *event) const { return m_events.value(event->getEventGroup()).indexOf(event); } +bool Map::hasEvent(Event *event) const { + return getIndexOfEvent(event) >= 0; +} + void Map::deleteConnections() { qDeleteAll(m_ownedConnections); m_ownedConnections.clear(); diff --git a/src/editor.cpp b/src/editor.cpp index a7ce2390..ecc056f0 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -28,7 +28,6 @@ QList> Editor::collisionIcons; Editor::Editor(Ui::MainWindow* ui) { this->ui = ui; - this->selected_events = new QList; this->settings = new Settings(); this->playerViewRect = new MovableRect(&this->settings->playerViewRectEnabled, 30 * 8, 20 * 8, qRgb(255, 255, 255)); this->cursorMapTileRect = new CursorTileRect(&this->settings->cursorTileRectEnabled, qRgb(255, 255, 255)); @@ -40,7 +39,7 @@ Editor::Editor(Ui::MainWindow* ui) /// the index is changed. connect(&editGroup, &QUndoGroup::indexChanged, [this](int) { if (selectNewEvents) { - updateSelectedEvents(); + updateEvents(); selectNewEvents = false; } }); @@ -58,7 +57,6 @@ Editor::Editor(Ui::MainWindow* ui) Editor::~Editor() { - delete this->selected_events; delete this->settings; delete this->playerViewRect; delete this->cursorMapTileRect; @@ -1167,7 +1165,7 @@ bool Editor::setMap(QString map_name) { editGroup.addStack(map->editHistory()); editGroup.setActiveStack(map->editHistory()); - selected_events->clear(); + this->selectedEvents.clear(); if (!displayMap()) { return false; } @@ -1176,7 +1174,7 @@ bool Editor::setMap(QString map_name) { connect(map, &Map::openScriptRequested, this, &Editor::openScript); connect(map, &Map::connectionAdded, this, &Editor::displayConnection); connect(map, &Map::connectionRemoved, this, &Editor::removeConnectionPixmap); - updateSelectedEvents(); + updateEvents(); return true; } @@ -1331,8 +1329,8 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i // Left-clicking while in paint mode will add a new event of the // type of the first currently selected events. Event::Type eventType = Event::Type::Object; - if (this->selected_events->size() > 0) - eventType = this->selected_events->first()->event->getEventType(); + if (!this->selectedEvents.isEmpty()) + eventType = this->selectedEvents.first()->getEventType(); Event* event = addNewEvent(eventType); if (event && event->getPixmapItem()) @@ -1352,15 +1350,9 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i if (pos.x() != selection_origin.x() || pos.y() != selection_origin.y()) { int xDelta = pos.x() - selection_origin.x(); int yDelta = pos.y() - selection_origin.y(); - - QList selectedEvents; - - for (DraggablePixmapItem *pixmapItem : getEventPixmapItems()) { - selectedEvents.append(pixmapItem->event); - } selection_origin = QPoint(pos.x(), pos.y()); - map->commit(new EventShift(selectedEvents, xDelta, yDelta, this->eventShiftActionId)); + this->map->commit(new EventShift(this->map->getEvents(), xDelta, yDelta, this->eventShiftActionId)); } } } @@ -1661,7 +1653,7 @@ void Editor::clearMapEvents() { delete events_group; events_group = nullptr; } - selected_events->clear(); + this->selectedEvents.clear(); } void Editor::displayMapEvents() { @@ -1690,7 +1682,7 @@ void Editor::removeEventPixmapItem(Event *event) { if (!item) return; this->events_group->removeFromGroup(item); - this->selected_events->removeOne(item); + this->selectedEvents.removeOne(event); event->setPixmapItem(nullptr); delete item; @@ -1955,14 +1947,6 @@ void Editor::redrawEvents(const QList &events) { } } -QList Editor::getEventPixmapItems() { - QList list; - for (QGraphicsItem *child : events_group->childItems()) { - list.append(static_cast(child)); - } - return list; -} - qreal Editor::getEventOpacity(const Event *event) const { // There are 4 possible opacities for an event's sprite: // - Off the Events tab, and the event overlay is off (0.0) @@ -1982,7 +1966,7 @@ void Editor::redrawEventPixmapItem(DraggablePixmapItem *item) { item->setShapeMode(porymapConfig.eventSelectionShapeMode); if (this->editMode == EditMode::Events) { - if (selected_events && selected_events->contains(item)) { + if (this->selectedEvents.contains(item->event)) { // Draw the selection rectangle QImage image = item->pixmap().toImage(); QPainter painter(&image); @@ -2027,44 +2011,40 @@ void Editor::updateWarpEventWarning(Event *event) { void Editor::updateWarpEventWarnings() { if (porymapConfig.warpBehaviorWarningDisabled) return; - if (selected_events) { - for (auto selection : *selected_events) - updateWarpEventWarning(selection->event); - } + for (const auto &event : this->selectedEvents) + updateWarpEventWarning(event); } void Editor::shouldReselectEvents() { selectNewEvents = true; } -void Editor::updateSelectedEvents() { - for (DraggablePixmapItem *item : getEventPixmapItems()) { - redrawEventPixmapItem(item); - } - +// TODO: This is frequently used to do more work than necessary. +void Editor::updateEvents() { + redrawAllEvents(); emit eventsChanged(); } -void Editor::selectMapEvent(DraggablePixmapItem *item, bool toggle) { - if (!selected_events || !item) +void Editor::selectMapEvent(Event *event, bool toggle) { + if (!event) return; if (!toggle) { // Selecting just this event - selected_events->clear(); - selected_events->append(item); - } else if (!selected_events->contains(item)) { + this->selectedEvents.clear(); + this->selectedEvents.append(event); + } else if (!this->selectedEvents.contains(event)) { // Adding event to group selection - selected_events->append(item); - } else if (selected_events->length() > 1) { + this->selectedEvents.append(event); + } else if (this->selectedEvents.length() > 1) { // Removing event from group selection - selected_events->removeOne(item); + this->selectedEvents.removeOne(event); } else { // Attempting to toggle the only currently-selected event. // Unselecting an event this way would be unexpected, so we ignore it. return; } - updateSelectedEvents(); + updateEvents(); } void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) { @@ -2072,10 +2052,10 @@ void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) { index = index - event_offs; Event *event = this->map->getEvent(eventGroup, index); - if (event && event->getPixmapItem()) { - this->selectMapEvent(event->getPixmapItem()); + if (event) { + selectMapEvent(event); } else { - updateSelectedEvents(); + updateEvents(); } } @@ -2095,12 +2075,12 @@ bool Editor::canAddEvents(const QList &events) { } void Editor::duplicateSelectedEvents() { - if (!selected_events || !selected_events->length() || !project || !map || !current_view || this->getEditingLayout()) + if (this->selectedEvents.isEmpty() || !project || !map || !current_view || this->getEditingLayout()) return; QList duplicatedEvents; - for (int i = 0; i < selected_events->length(); i++) { - duplicatedEvents.append(selected_events->at(i)->event->duplicate()); + for (const auto &event : this->selectedEvents) { + duplicatedEvents.append(event->duplicate()); } if (!canAddEvents(duplicatedEvents)) { WarningMessage::show(QStringLiteral("Unable to duplicate, the maximum number of events would be exceeded."), ui->graphicsView_Map); @@ -2142,13 +2122,12 @@ Event *Editor::addNewEvent(Event::Type type) { } void Editor::deleteSelectedEvents() { - if (!this->selected_events || this->selected_events->length() == 0 || !this->map || this->editMode != EditMode::Events) + if (this->selectedEvents.isEmpty() || !this->map || this->editMode != EditMode::Events) return; QList eventsToDelete; bool skipWarning = porymapConfig.eventDeleteWarningDisabled; - for (DraggablePixmapItem *item : *this->selected_events) { - Event* event = item->event; + for (auto event : this->selectedEvents) { const QString idName = event->getIdName(); if (skipWarning || idName.isEmpty()) { eventsToDelete.append(event); @@ -2166,7 +2145,7 @@ void Editor::deleteSelectedEvents() { msgBox.setCheckBox(new QCheckBox(QStringLiteral("Don't warn me again"))); QAbstractButton* deleteAllButton = nullptr; - if (this->selected_events->length() > 1) { + if (this->selectedEvents.length() > 1) { deleteAllButton = msgBox.addButton(QStringLiteral("Delete All"), QMessageBox::DestructiveRole); msgBox.addButton(QStringLiteral("Skip"), QMessageBox::NoRole); } @@ -2191,7 +2170,7 @@ void Editor::deleteSelectedEvents() { } } // TODO: Are we just calling this to invalidate connections? - event->setPixmapItem(item); + event->setPixmapItem(event->getPixmapItem()); } if (eventsToDelete.isEmpty()) return; @@ -2308,9 +2287,9 @@ void Editor::eventsView_onMousePress(QMouseEvent *event) { } bool multiSelect = event->modifiers() & Qt::ControlModifier; - if (!selectingEvent && !multiSelect && selected_events->length() > 1) { + if (!selectingEvent && !multiSelect && this->selectedEvents.length() > 1) { // User is clearing group selection by clicking on the background - this->selectMapEvent(selected_events->first()); + this->selectMapEvent(this->selectedEvents.first()); } selectingEvent = false; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5c7e5cdb..ae39f6f8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1027,18 +1027,13 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_ // Select the target event. int index = event_id - Event::getIndexOffset(event_group); - Event* event = editor->map->getEvent(event_group, index); + Event* event = this->editor->map->getEvent(event_group, index); if (event) { - auto item = event->getPixmapItem(); - if (item) { - editor->selected_events->clear(); - editor->selected_events->append(item); - editor->updateSelectedEvents(); - return; - } + this->editor->selectMapEvent(event); + } 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)); } - // 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)); } void MainWindow::displayMapProperties() { @@ -1628,15 +1623,8 @@ void MainWindow::copy() { OrderedJson::object copyObject; copyObject["object"] = "events"; - QList events; - if (editor->selected_events && editor->selected_events->length()) { - events = *editor->selected_events; - } - OrderedJson::array eventsArray; - - for (auto item : events) { - Event *event = item->event; + for (const auto &event : this->editor->selectedEvents) { OrderedJson::object eventContainer; eventContainer["event_type"] = Event::typeToString(event->getEventType()); OrderedJson::object eventJson = event->buildEventJson(editor->project); @@ -1997,31 +1985,32 @@ void MainWindow::displayEventTabs() { } void MainWindow::updateEvents() { - QList items = editor->getEventPixmapItems(); - for (auto i = this->lastSelectedEvent.cbegin(), end = this->lastSelectedEvent.cend(); i != end; i++) { - if (i.value() && !items.contains(i.value())) - this->lastSelectedEvent.insert(i.key(), nullptr); + if (this->editor->map) { + for (auto i = this->lastSelectedEvent.begin(); i != this->lastSelectedEvent.end(); i++) { + if (i.value() && !this->editor->map->hasEvent(i.value())) + this->lastSelectedEvent.insert(i.key(), nullptr); + } } displayEventTabs(); updateSelectedEvents(); } void MainWindow::updateSelectedEvents() { - QList events; + QList events; - if (editor->selected_events && editor->selected_events->length()) { - events = *editor->selected_events; + if (!this->editor->selectedEvents.isEmpty()) { + events = this->editor->selectedEvents; } else { - QList all_events; - if (editor->map) { - all_events = editor->map->getEvents(); + QList allEvents; + if (this->editor->map) { + allEvents = this->editor->map->getEvents(); } - if (all_events.length()) { - DraggablePixmapItem *selectedEvent = all_events.first()->getPixmapItem(); + if (!allEvents.isEmpty()) { + Event *selectedEvent = allEvents.first(); if (selectedEvent) { - editor->selected_events->append(selectedEvent); - editor->redrawEventPixmapItem(selectedEvent); + this->editor->selectedEvents.append(selectedEvent); + this->editor->redrawEventPixmapItem(selectedEvent->getPixmapItem()); events.append(selectedEvent); } } @@ -2034,12 +2023,13 @@ void MainWindow::updateSelectedEvents() { if (events.length() == 1) { // single selected event case - Event *current = events[0]->event; + Event *current = events.constFirst(); Event::Group eventGroup = current->getEventGroup(); int event_offs = Event::getIndexOffset(eventGroup); - if (eventGroup != Event::Group::None) - this->lastSelectedEvent.insert(eventGroup, current->getPixmapItem()); + if (eventGroup != Event::Group::None) { + this->lastSelectedEvent.insert(eventGroup, current); + } switch (eventGroup) { case Event::Group::Object: { @@ -2110,8 +2100,7 @@ void MainWindow::updateSelectedEvents() { this->isProgrammaticEventTabChange = false; QList frames; - for (DraggablePixmapItem *item : events) { - Event *event = item->event; + for (auto event : events) { EventFrame *eventFrame = event->createEventFrame(); eventFrame->populate(this->editor->project); eventFrame->initialize(); @@ -2166,7 +2155,7 @@ Event::Group MainWindow::getEventGroupFromTabWidget(QWidget *tab) { void MainWindow::eventTabChanged(int index) { if (editor->map) { Event::Group group = getEventGroupFromTabWidget(ui->tabWidget_EventType->widget(index)); - DraggablePixmapItem *selectedItem = this->lastSelectedEvent.value(group, nullptr); + Event *selectedEvent = this->lastSelectedEvent.value(group, nullptr); switch (group) { case Event::Group::Object: @@ -2189,11 +2178,8 @@ void MainWindow::eventTabChanged(int index) { } if (!isProgrammaticEventTabChange) { - if (!selectedItem) { - Event *event = editor->map->getEvent(group, 0); - if (event) selectedItem = event->getPixmapItem(); - } - if (selectedItem) editor->selectMapEvent(selectedItem); + if (!selectedEvent) selectedEvent = this->editor->map->getEvent(group, 0); + this->editor->selectMapEvent(selectedEvent); } } diff --git a/src/ui/draggablepixmapitem.cpp b/src/ui/draggablepixmapitem.cpp index 4880f530..846cfb7e 100644 --- a/src/ui/draggablepixmapitem.cpp +++ b/src/ui/draggablepixmapitem.cpp @@ -8,11 +8,11 @@ static unsigned currentActionId = 0; void DraggablePixmapItem::updatePosition() { - int x = event->getPixelX(); - int y = event->getPixelY(); + int x = this->event->getPixelX(); + int y = this->event->getPixelY(); setX(x); setY(y); - if (editor->selected_events && editor->selected_events->contains(this)) { + if (this->editor->selectedEvents.contains(this->event)) { setZValue(event->getY() + 1); } else { setZValue(event->getY()); @@ -40,10 +40,10 @@ void DraggablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouse) { this->lastPos = Metatile::coordFromPixmapCoord(mouse->scenePos()); bool selectionToggle = mouse->modifiers() & Qt::ControlModifier; - if (selectionToggle || !editor->selected_events->contains(this)) { + if (selectionToggle || !this->editor->selectedEvents.contains(this->event)) { // User is either toggling this selection on/off as part of a group selection, // or they're newly selecting just this item. - this->editor->selectMapEvent(this, selectionToggle); + this->editor->selectMapEvent(this->event, selectionToggle); } else { // This item is already selected and the user isn't toggling the selection, so there are 4 possibilities: // 1. This is the only selected event, and the selection is pointless. @@ -84,10 +84,8 @@ void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) { emit this->editor->map_item->hoveredMapMetatileChanged(pos); QList selectedEvents; - if (editor->selected_events->contains(this)) { - for (DraggablePixmapItem *item : *editor->selected_events) { - selectedEvents.append(item->event); - } + if (this->editor->selectedEvents.contains(this->event)) { + selectedEvents = this->editor->selectedEvents; } else { selectedEvents.append(this->event); } @@ -103,7 +101,7 @@ void DraggablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouse) { if (this->releaseSelectionQueued) { this->releaseSelectionQueued = false; if (Metatile::coordFromPixmapCoord(mouse->scenePos()) == this->lastPos) - this->editor->selectMapEvent(this); + this->editor->selectMapEvent(this->event); } }