diff --git a/include/core/map.h b/include/core/map.h index 9cc2a69b..b223536d 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -91,7 +91,7 @@ public: void removeConnection(MapConnection *); void addConnection(MapConnection *); void loadConnection(MapConnection *); - QRect getConnectionRect(const QString &direction, Layout *fromLayout = nullptr); + QRect getConnectionRect(const QString &direction, Layout *fromLayout = nullptr) const; QPixmap renderConnection(const QString &direction, Layout *fromLayout = nullptr); QUndoStack* editHistory() const { return m_editHistory; } diff --git a/include/editor.h b/include/editor.h index f5e94d28..434415e9 100644 --- a/include/editor.h +++ b/include/editor.h @@ -135,7 +135,7 @@ public: QList borderItems; QGraphicsItemGroup *mapGrid = nullptr; - MapRuler *map_ruler = nullptr; + QPointer map_ruler = nullptr; MovableRect *playerViewRect = nullptr; CursorTileRect *cursorMapTileRect = nullptr; @@ -221,10 +221,7 @@ private: void clearMapGrid(); void clearWildMonTables(); void updateBorderVisibility(); - void disconnectMapConnection(MapConnection *connection); - QPoint getConnectionOrigin(MapConnection *connection); void removeConnectionPixmap(MapConnection *connection); - void updateConnectionPixmap(ConnectionPixmapItem *connectionItem); void displayConnection(MapConnection *connection); void displayDivingConnection(MapConnection *connection); void setDivingMapName(QString mapName, QString direction); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index 183f2d79..26b83aa6 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -10,22 +10,20 @@ class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: - ConnectionPixmapItem(MapConnection* connection, int originX, int originY); - ConnectionPixmapItem(MapConnection* connection, QPoint origin); + ConnectionPixmapItem(MapConnection* connection); const QPointer connection; - void setOrigin(int x, int y); - void setOrigin(QPoint pos); - void setEditable(bool editable); bool getEditable(); void setSelected(bool selected); - void updatePos(); void render(bool ignoreCache = false); +signals: + void positionChanged(qreal x, qreal y); + private: QPixmap basePixmap; qreal originX; @@ -36,6 +34,10 @@ private: static const int mWidth = 16; static const int mHeight = 16; + void updatePos(); + void updateOrigin(); + void refresh(); + protected: virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; virtual void mousePressEvent(QGraphicsSceneMouseEvent*) override; diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index 7ba6a9d8..b63922a9 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -23,7 +23,6 @@ public: explicit ConnectionsListItem(QWidget *parent, MapConnection *connection, const QStringList &mapNames); ~ConnectionsListItem(); - void updateUI(); void setSelected(bool selected); private: @@ -33,6 +32,8 @@ private: bool isSelected = false; unsigned actionId = 0; + void updateUI(); + protected: virtual void mousePressEvent(QMouseEvent*) override; virtual void focusInEvent(QFocusEvent*) override; diff --git a/src/core/map.cpp b/src/core/map.cpp index a42faa27..aac20138 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -90,7 +90,7 @@ int Map::getBorderHeight() const { // Get the portion of the map that can be rendered when rendered as a map connection. // Cardinal connections render the nearest segment of their map and within the bounds of the border draw distance, // Dive/Emerge connections are rendered normally within the bounds of their parent map. -QRect Map::getConnectionRect(const QString &direction, Layout * fromLayout) { +QRect Map::getConnectionRect(const QString &direction, Layout * fromLayout) const { int x = 0, y = 0; int w = getWidth(), h = getHeight(); diff --git a/src/editor.cpp b/src/editor.cpp index c22068d2..9dd9d190 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -779,14 +779,6 @@ void Editor::updateEncounterFields(EncounterFields newFields) { project->wildMonFields = newFields; } -void Editor::disconnectMapConnection(MapConnection *connection) { - // Disconnect MapConnection's signals used by the display. - // It'd be nice if we could just 'connection->disconnect(this)' but that doesn't account for lambda functions. - QObject::disconnect(connection, &MapConnection::targetMapNameChanged, nullptr, nullptr); - QObject::disconnect(connection, &MapConnection::directionChanged, nullptr, nullptr); - QObject::disconnect(connection, &MapConnection::offsetChanged, nullptr, nullptr); -} - void Editor::displayConnection(MapConnection *connection) { if (!connection) return; @@ -797,13 +789,13 @@ void Editor::displayConnection(MapConnection *connection) { } // Create connection image - ConnectionPixmapItem *pixmapItem = new ConnectionPixmapItem(connection, getConnectionOrigin(connection)); - pixmapItem->render(); + auto pixmapItem = new ConnectionPixmapItem(connection); scene->addItem(pixmapItem); maskNonVisibleConnectionTiles(); + connect(pixmapItem, &ConnectionPixmapItem::positionChanged, this, &Editor::maskNonVisibleConnectionTiles); // Create item for the list panel - ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, pixmapItem->connection, project->mapNames); + auto listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, pixmapItem->connection, project->mapNames); ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer // Double clicking the pixmap or clicking the list item's map button opens the connected map @@ -822,25 +814,6 @@ void Editor::displayConnection(MapConnection *connection) { setSelectedConnectionItem(pixmapItem); }); - // Sync edits to 'offset' between the list UI and the pixmap - connect(connection, &MapConnection::offsetChanged, [=](int, int) { - listItem->updateUI(); - pixmapItem->updatePos(); - maskNonVisibleConnectionTiles(); - }); - - // Sync edits to 'direction' between the list UI and the pixmap - connect(connection, &MapConnection::directionChanged, [=](QString, QString) { - listItem->updateUI(); - updateConnectionPixmap(pixmapItem); - }); - - // Sync edits to 'map' between the list UI and the pixmap - connect(connection, &MapConnection::targetMapNameChanged, [=](QString, QString) { - listItem->updateUI(); - updateConnectionPixmap(pixmapItem); - }); - // When the pixmap is deleted, remove its associated list item connect(pixmapItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); @@ -875,8 +848,6 @@ void Editor::removeConnectionPixmap(MapConnection *connection) { if (!connection) return; - disconnectMapConnection(connection); - if (MapConnection::isDiving(connection->direction())) { removeDivingMapPixmap(connection); return; @@ -1011,39 +982,6 @@ void Editor::updateDivingMapsVisibility() { } } -// Get the 'origin' point for the connection's pixmap, i.e. where it should be positioned in the editor when connection->offset() == 0. -// This differs depending on the connection's direction and the dimensions of its target map or parent map. -QPoint Editor::getConnectionOrigin(MapConnection *connection) { - if (!connection) - return QPoint(0, 0); - - Map *parentMap = connection->parentMap(); - Map *targetMap = connection->targetMap(); - const QString direction = connection->direction(); - int x = 0, y = 0; - - if (direction == "right") { - if (parentMap) x = parentMap->getWidth(); - } else if (direction == "down") { - if (parentMap) y = parentMap->getHeight(); - } else if (direction == "left") { - if (targetMap) x = -targetMap->getConnectionRect(direction).width(); - } else if (direction == "up") { - if (targetMap) y = -targetMap->getConnectionRect(direction).height(); - } - return QPoint(x * 16, y * 16); -} - -void Editor::updateConnectionPixmap(ConnectionPixmapItem *pixmapItem) { - if (!pixmapItem) - return; - - pixmapItem->setOrigin(getConnectionOrigin(pixmapItem->connection)); - pixmapItem->render(true); // Full render to reflect map changes - - maskNonVisibleConnectionTiles(); -} - void Editor::setSelectedConnectionItem(ConnectionPixmapItem *pixmapItem) { if (!pixmapItem || pixmapItem == selected_connection_item) return; @@ -1245,8 +1183,6 @@ void Editor::unsetMap() { if (this->map) { this->map->pruneEditHistory(); this->map->disconnect(this); - for (const auto &connection : this->map->getConnections()) - disconnectMapConnection(connection); } clearMapConnections(); @@ -1546,7 +1482,10 @@ void Editor::clearMap() { map = nullptr; // These are normally preserved between map displays, we only delete them now. - delete scene; + if (scene) { + scene->removeItem(this->map_ruler); + delete scene; + } delete metatile_selector_item; delete movement_permissions_selector_item; } @@ -1575,9 +1514,10 @@ bool Editor::displayLayout() { scene->installEventFilter(filter); connect(filter, &MapSceneEventFilter::wheelZoom, this, &Editor::onWheelZoom); scene->installEventFilter(this->map_ruler); + this->map_ruler->setZValue(1000); + scene->addItem(this->map_ruler); } - clearConnectionMask(); displayMetatileSelector(); displayMapMetatiles(); displayMovementPermissionSelector(); @@ -1586,9 +1526,7 @@ bool Editor::displayLayout() { displayCurrentMetatilesSelection(); displayMapBorder(); displayMapGrid(); - - this->map_ruler->setZValue(1000); - scene->addItem(this->map_ruler); + maskNonVisibleConnectionTiles(); if (map_item) { map_item->setVisible(false); @@ -1638,7 +1576,6 @@ void Editor::clearMapMetatiles() { if (map_item && scene) { scene->removeItem(map_item); delete map_item; - scene->removeItem(this->map_ruler); } } diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index d3ff13ae..e22b0fab 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -4,19 +4,25 @@ #include -ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection, int x, int y) +ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection) : QGraphicsPixmapItem(connection->getPixmap()), connection(connection) { this->setEditable(true); setFlag(ItemIsFocusable, true); this->basePixmap = pixmap(); - this->setOrigin(x, y); + refresh(); + + // If the connection changes externally we want to update the pixmap to reflect the change. + connect(connection, &MapConnection::offsetChanged, this, &ConnectionPixmapItem::updatePos); + connect(connection, &MapConnection::directionChanged, this, &ConnectionPixmapItem::refresh); + connect(connection, &MapConnection::targetMapNameChanged, this, &ConnectionPixmapItem::refresh); } -ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection, QPoint pos) - : ConnectionPixmapItem(connection, pos.x(), pos.y()) -{} +void ConnectionPixmapItem::refresh() { + updateOrigin(); + render(true); +} // Render additional visual effects on top of the base map image. void ConnectionPixmapItem::render(bool ignoreCache) { @@ -77,8 +83,6 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari // If connection->offset changed externally we call this to correct our position. void ConnectionPixmapItem::updatePos() { - const QSignalBlocker blocker(this); - qreal x = this->originX; qreal y = this->originY; @@ -89,17 +93,28 @@ void ConnectionPixmapItem::updatePos() { } this->setPos(x, y); + emit positionChanged(x, y); } -// Set the pixmap's external origin point, i.e. the pixmap's position when connection->offset == 0 -void ConnectionPixmapItem::setOrigin(int x, int y) { - this->originX = x; - this->originY = y; +void ConnectionPixmapItem::updateOrigin() { + const Map *parentMap = connection->parentMap(); + const Map *targetMap = connection->targetMap(); + const QString direction = connection->direction(); + int x = 0, y = 0; + + if (direction == "right") { + if (parentMap) x = parentMap->getWidth(); + } else if (direction == "down") { + if (parentMap) y = parentMap->getHeight(); + } else if (direction == "left") { + if (targetMap) x = -targetMap->getConnectionRect(direction).width(); + } else if (direction == "up") { + if (targetMap) y = -targetMap->getConnectionRect(direction).height(); + } + this->originX = x * this->mWidth; + this->originY = y * this->mHeight; updatePos(); } -void ConnectionPixmapItem::setOrigin(QPoint pos) { - this->setOrigin(pos.x(), pos.y()); -} void ConnectionPixmapItem::setEditable(bool editable) { setFlag(ItemIsMovable, editable); diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index dcff253c..5b21a12c 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -38,6 +38,11 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec // Distinguish between move actions for the edit history connect(ui->spinBox_Offset, &QSpinBox::editingFinished, [this] { this->actionId++; }); + // If the connection changes externally we want to update to reflect the change. + connect(connection, &MapConnection::offsetChanged, this, &ConnectionsListItem::updateUI); + connect(connection, &MapConnection::directionChanged, this, &ConnectionsListItem::updateUI); + connect(connection, &MapConnection::targetMapNameChanged, this, &ConnectionsListItem::updateUI); + this->connection = connection; this->map = connection->parentMap(); this->updateUI();