Take advantage of MapConnection as QObject

This commit is contained in:
GriffinR 2024-08-04 19:11:29 -04:00
parent b5c7f9f86b
commit 4af1c4d463
14 changed files with 374 additions and 382 deletions

View file

@ -98,6 +98,8 @@ public:
QStringList getScriptLabels(Event::Group group = Event::Group::None); QStringList getScriptLabels(Event::Group group = Event::Group::None);
void removeEvent(Event *); void removeEvent(Event *);
void addEvent(Event *); void addEvent(Event *);
bool removeConnection(MapConnection *);
void addConnection(MapConnection *);
QPixmap renderConnection(const QString &, MapLayout *); QPixmap renderConnection(const QString &, MapLayout *);
QPixmap renderBorder(bool ignoreCache = false); QPixmap renderBorder(bool ignoreCache = false);
void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);
@ -132,6 +134,7 @@ signals:
void mapDimensionsChanged(const QSize &size); void mapDimensionsChanged(const QSize &size);
void mapNeedsRedrawing(); void mapNeedsRedrawing();
void openScriptRequested(QString label); void openScriptRequested(QString label);
void connectionAdded(MapConnection*);
}; };
#endif // MAP_H #endif // MAP_H

View file

@ -4,6 +4,9 @@
#include <QString> #include <QString>
#include <QObject> #include <QObject>
#include <QMap>
class Project;
class MapConnection : public QObject class MapConnection : public QObject
{ {
@ -23,19 +26,32 @@ public:
int offset() const { return m_offset; } int offset() const { return m_offset; }
void setOffset(int offset); void setOffset(int offset);
MapConnection * createMirror();
bool isMirror(const MapConnection*); bool isMirror(const MapConnection*);
MapConnection* findMirror();
MapConnection* createMirror();
QPixmap getPixmap();
static QPointer<Project> project;
static const QMap<QString, QString> oppositeDirections;
static const QStringList cardinalDirections; static const QStringList cardinalDirections;
static bool isCardinal(const QString &direction); static bool isCardinal(const QString &direction);
static bool isHorizontal(const QString &direction); static bool isHorizontal(const QString &direction);
static bool isVertical(const QString &direction); static bool isVertical(const QString &direction);
static QString oppositeDirection(const QString &direction) { return oppositeDirections.value(direction, direction); }
private: private:
QString m_direction; QString m_direction;
QString m_hostMapName; QString m_hostMapName;
QString m_targetMapName; QString m_targetMapName;
int m_offset; int m_offset;
bool m_ignoreMirror;
void mirrorDirection(const QString &direction);
void mirrorHostMapName(const QString &hostMapName);
void mirrorTargetMapName(const QString &targetMapName);
void mirrorOffset(int offset);
void markMapEdited();
signals: signals:
void directionChanged(const QString &before, const QString &after); void directionChanged(const QString &before, const QString &after);

View file

@ -46,6 +46,7 @@ public:
QPointer<Project> project = nullptr; QPointer<Project> project = nullptr;
Map *map = nullptr; Map *map = nullptr;
Settings *settings; Settings *settings;
void setProject(Project * project);
void saveProject(); void saveProject();
void save(); void save();
void closeProject(); void closeProject();
@ -78,8 +79,8 @@ public:
void updateDiveEmergeVisibility(); void updateDiveEmergeVisibility();
void addNewConnection(); void addNewConnection();
void addConnection(MapConnection* connection, bool addMirror = true); void addConnection(MapConnection* connection, bool addMirror = true);
void removeConnection(MapConnection* connection, bool removeMirror = true); void removeConnection(MapConnection* connection, bool addMirror = true);
void removeConnectionItem(ConnectionPixmapItem* connectionItem); void removeConnectionPixmap(ConnectionPixmapItem* connectionItem);
void removeSelectedConnection(); void removeSelectedConnection();
void addNewWildMonGroup(QWidget *window); void addNewWildMonGroup(QWidget *window);
void deleteWildMonGroup(); void deleteWildMonGroup();
@ -186,15 +187,11 @@ private:
void clearWildMonTables(); void clearWildMonTables();
void updateBorderVisibility(); void updateBorderVisibility();
QPoint calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap); QPoint calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap);
QPixmap getConnectionPixmap(MapConnection *connection); void updateConnectionPixmap(ConnectionPixmapItem* connectionItem);
void updateConnectionItem(ConnectionPixmapItem* connectionItem); void updateConnectionPixmapPos(ConnectionPixmapItem* connectionItem);
void updateConnectionItemPos(ConnectionPixmapItem* connectionItem); void displayConnection(MapConnection* connection);
void createConnectionItem(MapConnection* connection); void displayDiveEmergeConnection(MapConnection* connection);
void createDiveEmergeConnection(MapConnection* connection);
void setDiveEmergeMapName(QString mapName, QString direction); void setDiveEmergeMapName(QString mapName, QString direction);
MapConnection* getMirroredConnection(MapConnection*);
void addMirroredConnection(MapConnection*);
void removeMirroredConnection(MapConnection*);
void updateEncounterFields(EncounterFields newFields); void updateEncounterFields(EncounterFields newFields);
QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
QString getMetatileDisplayMessage(uint16_t metatileId); QString getMetatileDisplayMessage(uint16_t metatileId);
@ -210,9 +207,6 @@ private slots:
void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event); void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event);
void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item); void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item);
void setConnectionOffset(MapConnection *connection, int offset);
void setConnectionMap(MapConnection *connection, const QString &mapName);
void setConnectionDirection(MapConnection *connection, const QString &direction);
void setSelectedConnection(ConnectionPixmapItem* connectionItem); void setSelectedConnection(ConnectionPixmapItem* connectionItem);
void onHoveredMovementPermissionChanged(uint16_t, uint16_t); void onHoveredMovementPermissionChanged(uint16_t, uint16_t);
void onHoveredMovementPermissionCleared(); void onHoveredMovementPermissionCleared();
@ -225,15 +219,15 @@ private slots:
void onSelectedMetatilesChanged(); void onSelectedMetatilesChanged();
void onWheelZoom(int); void onWheelZoom(int);
void onToggleGridClicked(bool); void onToggleGridClicked(bool);
void onMapConnectionDoubleClicked(MapConnection*);
signals: signals:
void objectsChanged(); void objectsChanged();
void connectionItemDoubleClicked(QString, QString); void openConnectedMap(QString, QString);
void wildMonDataChanged(); void wildMonDataChanged();
void warpEventDoubleClicked(QString, int, Event::Group); void warpEventDoubleClicked(QString, int, Event::Group);
void currentMetatilesSelectionChanged(); void currentMetatilesSelectionChanged();
void mapRulerStatusChanged(const QString &); void mapRulerStatusChanged(const QString &);
void editedMapData(Map*);
void tilesetUpdated(QString); void tilesetUpdated(QString);
}; };

View file

@ -178,13 +178,14 @@ private slots:
void copy(); void copy();
void paste(); void paste();
void onConnectionItemDoubleClicked(QString, QString); void onOpenConnectedMap(QString, QString);
void onMapNeedsRedrawing(); void onMapNeedsRedrawing();
void onTilesetsSaved(QString, QString); void onTilesetsSaved(QString, QString);
void onWildMonDataChanged(); void onWildMonDataChanged();
void openNewMapPopupWindow(); void openNewMapPopupWindow();
void onNewMapCreated(); void onNewMapCreated();
void onMapCacheCleared(); void onMapCacheCleared();
void onMapLoaded(Map *map);
void importMapFromAdvanceMap1_92(); void importMapFromAdvanceMap1_92();
void onMapRulerStatusChanged(const QString &); void onMapRulerStatusChanged(const QString &);
void applyUserShortcuts(); void applyUserShortcuts();

View file

@ -257,6 +257,7 @@ signals:
void reloadProject(); void reloadProject();
void uncheckMonitorFilesAction(); void uncheckMonitorFilesAction();
void mapCacheCleared(); void mapCacheCleared();
void mapLoaded(Map *map);
}; };
#endif // PROJECT_H #endif // PROJECT_H

View file

@ -4,6 +4,7 @@
#include "mapconnection.h" #include "mapconnection.h"
#include <QGraphicsPixmapItem> #include <QGraphicsPixmapItem>
#include <QPainter> #include <QPainter>
#include <QPointer>
class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem { class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT Q_OBJECT
@ -18,11 +19,10 @@ public:
this->initialX = x; this->initialX = x;
this->initialY = y; this->initialY = y;
this->initialOffset = connection->offset(); this->initialOffset = connection->offset();
this->setX(x); this->setPos(x, y);
this->setY(y);
} }
QPixmap basePixmap; QPixmap basePixmap;
MapConnection* connection; QPointer<MapConnection> connection;
int initialX; int initialX;
int initialY; int initialY;
int initialOffset; int initialOffset;
@ -41,8 +41,7 @@ protected:
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
signals: signals:
void connectionItemDoubleClicked(ConnectionPixmapItem* connectionItem); void connectionItemDoubleClicked(MapConnection*);
void connectionMoved(MapConnection *, int newOffset);
void selectionChanged(bool selected); void selectionChanged(bool selected);
}; };

View file

@ -5,6 +5,7 @@
#include <QFrame> #include <QFrame>
#include <QMouseEvent> #include <QMouseEvent>
#include <QPointer>
namespace Ui { namespace Ui {
class ConnectionsListItem; class ConnectionsListItem;
@ -25,7 +26,7 @@ public:
void updateUI(); void updateUI();
void setSelected(bool selected); void setSelected(bool selected);
MapConnection * connection; QPointer<MapConnection> connection;
private: private:
Ui::ConnectionsListItem *ui; Ui::ConnectionsListItem *ui;
@ -36,12 +37,9 @@ protected:
void mouseDoubleClickEvent(QMouseEvent *); void mouseDoubleClickEvent(QMouseEvent *);
signals: signals:
void editedOffset(MapConnection *connection, int newOffset); void removed(MapConnection*);
void editedDirection(MapConnection *connection, const QString &direction);
void editedMapName(MapConnection *connection, const QString &mapName);
void removed();
void selected(); void selected();
void doubleClicked(const QString &mapName); void doubleClicked(MapConnection*);
private slots: private slots:
void on_comboBox_Direction_currentTextChanged(const QString &direction); void on_comboBox_Direction_currentTextChanged(const QString &direction);

View file

@ -218,6 +218,9 @@ QPixmap Map::renderBorder(bool ignoreCache) {
} }
QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) { QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) {
if (direction == "dive" || direction == "emerge")
return render();
if (!MapConnection::isCardinal(direction)) if (!MapConnection::isCardinal(direction))
return QPixmap(); return QPixmap();
@ -510,6 +513,22 @@ void Map::addEvent(Event *event) {
if (!ownedEvents.contains(event)) ownedEvents.append(event); if (!ownedEvents.contains(event)) ownedEvents.append(event);
} }
bool Map::removeConnection(MapConnection *connection) {
if (connections.removeOne(connection)) {
modify();
return true;
}
return false;
}
void Map::addConnection(MapConnection *connection) {
if (!connection || connections.contains(connection))
return;
connections.append(connection);
modify();
emit connectionAdded(connection);
}
void Map::modify() { void Map::modify() {
emit modified(); emit modified();
} }

View file

@ -1,7 +1,9 @@
#include <QMap>
#include "mapconnection.h" #include "mapconnection.h"
#include "project.h"
const QMap<QString, QString> oppositeDirections = { QPointer<Project> MapConnection::project = nullptr;
const QMap<QString, QString> MapConnection::oppositeDirections = {
{"up", "down"}, {"down", "up"}, {"up", "down"}, {"down", "up"},
{"right", "left"}, {"left", "right"}, {"right", "left"}, {"left", "right"},
{"dive", "emerge"}, {"emerge", "dive"} {"dive", "emerge"}, {"emerge", "dive"}
@ -12,47 +14,7 @@ MapConnection::MapConnection(const QString &direction, const QString &hostMapNam
m_hostMapName = hostMapName; m_hostMapName = hostMapName;
m_targetMapName = targetMapName; m_targetMapName = targetMapName;
m_offset = offset; m_offset = offset;
} m_ignoreMirror = false;
void MapConnection::setDirection(const QString &direction) {
if (direction == m_direction)
return;
auto before = m_direction;
m_direction = direction;
emit directionChanged(before, m_direction);
}
void MapConnection::setHostMapName(const QString &hostMapName) {
if (hostMapName == m_hostMapName)
return;
auto before = m_hostMapName;
m_hostMapName = hostMapName;
emit hostMapNameChanged(before, m_hostMapName);
}
void MapConnection::setTargetMapName(const QString &targetMapName) {
if (targetMapName == m_targetMapName)
return;
auto before = m_targetMapName;
m_targetMapName = targetMapName;
emit targetMapNameChanged(before, m_targetMapName);
}
void MapConnection::setOffset(int offset) {
if (offset == m_offset)
return;
auto before = m_offset;
m_offset = offset;
emit offsetChanged(before, m_offset);
}
MapConnection * MapConnection::createMirror() {
return new MapConnection(oppositeDirections.value(m_direction, m_direction), m_targetMapName, m_hostMapName, -m_offset);
} }
bool MapConnection::isMirror(const MapConnection* other) { bool MapConnection::isMirror(const MapConnection* other) {
@ -62,7 +24,138 @@ bool MapConnection::isMirror(const MapConnection* other) {
return m_hostMapName == other->m_targetMapName return m_hostMapName == other->m_targetMapName
&& m_targetMapName == other->m_hostMapName && m_targetMapName == other->m_hostMapName
&& m_offset == -other->m_offset && m_offset == -other->m_offset
&& m_direction == oppositeDirections.value(other->m_direction, other->m_direction); && m_direction == oppositeDirection(other->m_direction);
}
MapConnection* MapConnection::findMirror() {
if (!porymapConfig.mirrorConnectingMaps || !project || m_ignoreMirror)
return nullptr;
Map *connectedMap = project->getMap(m_targetMapName);
if (!connectedMap)
return nullptr;
// Find the matching connection in the connected map.
// Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed
// to always get the same MapConnection if there are multiple identical copies.
for (auto connection : connectedMap->connections) {
if (this != connection && this->isMirror(connection))
return connection;
}
return nullptr;
}
MapConnection * MapConnection::createMirror() {
if (!porymapConfig.mirrorConnectingMaps)
return nullptr;
return new MapConnection(oppositeDirection(m_direction), m_targetMapName, m_hostMapName, -m_offset);
}
void MapConnection::markMapEdited() {
if (project) {
Map * map = project->getMap(m_hostMapName);
if (map) map->modify();
}
}
QPixmap MapConnection::getPixmap() {
if (!project)
return QPixmap();
Map *hostMap = project->getMap(m_hostMapName);
Map *targetMap = project->getMap(m_targetMapName);
if (!hostMap || !targetMap)
return QPixmap();
return targetMap->renderConnection(m_direction, hostMap->layout);
}
void MapConnection::setDirection(const QString &direction) {
if (direction == m_direction)
return;
mirrorDirection(direction);
auto before = m_direction;
m_direction = direction;
emit directionChanged(before, m_direction);
markMapEdited();
}
void MapConnection::mirrorDirection(const QString &direction) {
MapConnection * mirror = findMirror();
if (!mirror)
return;
mirror->m_ignoreMirror = true;
mirror->setDirection(oppositeDirection(direction));
mirror->m_ignoreMirror = false;
}
void MapConnection::setHostMapName(const QString &hostMapName) {
if (hostMapName == m_hostMapName)
return;
mirrorHostMapName(hostMapName);
auto before = m_hostMapName;
m_hostMapName = hostMapName;
if (project) {
// TODO: This is probably unexpected design, esp because creating a MapConnection doesn't insert to host map
// Reassign connection to new host map
Map * oldMap = project->getMap(before);
Map * newMap = project->getMap(m_hostMapName);
if (oldMap) oldMap->removeConnection(this);
if (newMap) newMap->addConnection(this);
}
emit hostMapNameChanged(before, m_hostMapName);
}
void MapConnection::mirrorHostMapName(const QString &hostMapName) {
MapConnection * mirror = findMirror();
if (!mirror)
return;
mirror->m_ignoreMirror = true;
mirror->setTargetMapName(hostMapName);
mirror->m_ignoreMirror = false;
}
void MapConnection::setTargetMapName(const QString &targetMapName) {
if (targetMapName == m_targetMapName)
return;
mirrorTargetMapName(targetMapName);
auto before = m_targetMapName;
m_targetMapName = targetMapName;
emit targetMapNameChanged(before, m_targetMapName);
markMapEdited();
}
void MapConnection::mirrorTargetMapName(const QString &targetMapName) {
MapConnection * mirror = findMirror();
if (!mirror)
return;
mirror->m_ignoreMirror = true;
mirror->setHostMapName(targetMapName);
mirror->m_ignoreMirror = false;
}
void MapConnection::setOffset(int offset) {
if (offset == m_offset)
return;
mirrorOffset(offset);
auto before = m_offset;
m_offset = offset;
emit offsetChanged(before, m_offset);
markMapEdited();
}
void MapConnection::mirrorOffset(int offset) {
MapConnection * mirror = findMirror();
if (!mirror)
return;
mirror->m_ignoreMirror = true;
mirror->setOffset(-offset);
mirror->m_ignoreMirror = false;
} }
const QStringList MapConnection::cardinalDirections = { const QStringList MapConnection::cardinalDirections = {

View file

@ -78,6 +78,14 @@ void Editor::saveUiFields() {
saveEncounterTabData(); saveEncounterTabData();
} }
void Editor::setProject(Project * project) {
if (this->project) {
closeProject();
}
this->project = project;
MapConnection::project = project;
}
void Editor::closeProject() { void Editor::closeProject() {
if (!this->project) if (!this->project)
return; return;
@ -725,70 +733,83 @@ void Editor::updateEncounterFields(EncounterFields newFields) {
project->wildMonFields = newFields; project->wildMonFields = newFields;
} }
void Editor::createConnectionItem(MapConnection* connection) { void Editor::displayConnection(MapConnection* connection) {
if (!connection) if (!connection)
return; return;
// It's possible for a map connection to be displayed repeatedly if it's being
// updated by mirroring and the target map is changing to/from the current map.
connection->disconnect();
if (connection->direction() == "dive" || connection->direction() == "emerge") {
displayDiveEmergeConnection(connection);
return;
}
// Create connection image // Create connection image
QPixmap pixmap = getConnectionPixmap(connection); QPixmap pixmap = connection->getPixmap();
QPoint pos = calculateConnectionPosition(connection, pixmap); QPoint pos = calculateConnectionPosition(connection, pixmap);
ConnectionPixmapItem *connectionItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); ConnectionPixmapItem *pixmapItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y());
connectionItem->render(); pixmapItem->render();
scene->addItem(connectionItem); scene->addItem(pixmapItem);
// Create item for the list panel // Create item for the list panel
ConnectionsListItem *listItem = new ConnectionsListItem(ui->scrollAreaContents_ConnectionsList, connectionItem->connection, project->mapNames); ConnectionsListItem *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 ui->layout_ConnectionsList->insertWidget(ui->layout_ConnectionsList->count() - 1, listItem); // Insert above the vertical spacer
connect(connectionItem, &ConnectionPixmapItem::selectionChanged, [this, connectionItem](bool selected) { // Double clicking the list item or pixmap opens the connected map
if (selected) setSelectedConnection(connectionItem); connect(listItem, &ConnectionsListItem::doubleClicked, this, &Editor::onMapConnectionDoubleClicked);
connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::onMapConnectionDoubleClicked);
// Sync the selection highlight between the list UI and the pixmap
connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [this, listItem, pixmapItem](bool selected) {
listItem->setSelected(selected);
if (selected) setSelectedConnection(pixmapItem);
}); });
connect(connectionItem, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, connectionItem] { connect(listItem, &ConnectionsListItem::selected, [this, pixmapItem] {
emit this->connectionItemDoubleClicked(connectionItem->connection->targetMapName(), map->name); setSelectedConnection(pixmapItem);
}); });
// Sync the selection highlight between the list UI and the graphical map connection // Sync edits to 'offset' between the list UI and the pixmap
connect(connectionItem, &ConnectionPixmapItem::selectionChanged, listItem, &ConnectionsListItem::setSelected); connect(connection, &MapConnection::offsetChanged, [this, listItem, pixmapItem](int, int) {
connect(listItem, &ConnectionsListItem::selected, [this, connectionItem] {
setSelectedConnection(connectionItem);
});
// Sync edits to 'offset' between the list UI and the graphical map connection
connect(connectionItem, &ConnectionPixmapItem::connectionMoved, [this, listItem](MapConnection* connection, int offset) {
setConnectionOffset(connection, offset);
listItem->updateUI(); listItem->updateUI();
}); updateConnectionPixmapPos(pixmapItem);
connect (listItem, &ConnectionsListItem::editedOffset, [this, connectionItem](MapConnection* connection, int offset) {
setConnectionOffset(connection, offset);
updateConnectionItemPos(connectionItem);
}); });
// Sync edits to 'direction' or 'map' between the list UI and the graphical map connection. // Sync edits to 'direction' between the list UI and the pixmap
// These are 1-way because the direction and map cannot be edited graphically, only via the list UI. connect(connection, &MapConnection::directionChanged, [this, listItem, pixmapItem](QString before, QString after) {
connect(listItem, &ConnectionsListItem::editedDirection, [this, connectionItem, listItem](MapConnection* connection, QString direction) { if (MapConnection::isHorizontal(before) != MapConnection::isHorizontal(after)
setConnectionDirection(connection, direction); || MapConnection::isVertical(before) != MapConnection::isVertical(after)) {
updateConnectionItem(connectionItem); // TODO: Simplify // If the direction has changed between vertical/horizontal then the old offset may not make sense, so we reset it
listItem->updateUI(); // Changing direction may have changed our offset too pixmapItem->connection->setOffset(0);
}); }
connect(listItem, &ConnectionsListItem::editedMapName, [this, connectionItem](MapConnection* connection, QString mapName) { listItem->updateUI();
setConnectionMap(connection, mapName); updateConnectionPixmap(pixmapItem);
updateConnectionItem(connectionItem);
}); });
// Sync deleting the map connection // Sync edits to 'map' between the list UI and the pixmap
connect(connectionItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater); connect(connection, &MapConnection::targetMapNameChanged, [this, listItem, pixmapItem](QString, QString) {
connect(listItem, &ConnectionsListItem::removed, [this, connectionItem] { listItem->updateUI();
// 'Remove' button has been clicked. Delete the pixmap. updateConnectionPixmap(pixmapItem);
// The list item will be deleted via the above connection to the pixmap's 'destroyed' signal.
removeConnectionItem(connectionItem);
}); });
// Double clicking the list item opens the connected map connect(connection, &MapConnection::hostMapNameChanged, [this, pixmapItem](QString before, QString) {
connect(listItem, &ConnectionsListItem::doubleClicked, [this](QString connectedMapName) { // A connection was removed from the current map by reassignment. We're deleting the UI elements,
emit connectionItemDoubleClicked(connectedMapName, map->name); // but not the associated connection (it still exists, but now it belongs to a different map).
// At the moment this is only possible when updating the mirror for a map connected to itself,
// users have no other way (or need) to relocate a map connection like this.
if (before == this->map->name)
removeConnectionPixmap(pixmapItem);
}); });
connection_items.append(connectionItem); // User manually deleting connection via the remove button
connect(listItem, &ConnectionsListItem::removed, [this](MapConnection* connection) { removeConnection(connection); });
// Sync removing the UI elements. They may be removed when deleting connections or when displaying a new map.
connect(connection, &MapConnection::destroyed, [this, pixmapItem] { removeConnectionPixmap(pixmapItem); });
connect(pixmapItem, &ConnectionPixmapItem::destroyed, listItem, &ConnectionsListItem::deleteLater);
connection_items.append(pixmapItem);
} }
@ -821,33 +842,38 @@ void Editor::addConnection(MapConnection * connection, bool addMirror) {
if (!connection) if (!connection)
return; return;
if (addMirror) if (addMirror) addConnection(connection->createMirror(), false);
addMirroredConnection(connection);
Map *map = project->getMap(connection->hostMapName()); Map *map = project->getMap(connection->hostMapName());
if (!map) if (map) map->addConnection(connection);
return; // TODO: Edit history
map->connections.append(connection);
if (map == this->map) {
// Adding a connection to the current map, we need to display it visually.
if (connection->direction() == "dive" || connection->direction() == "emerge") {
createDiveEmergeConnection(connection);
} else {
createConnectionItem(connection);
}
}
emit editedMapData(map);
} }
void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem) { void Editor::removeConnection(MapConnection* connection, bool removeMirror) {
if (!connectionItem) if (!connection)
return; return;
int index = connection_items.indexOf(connectionItem); if (removeMirror) removeConnection(connection->findMirror(), false);
Map* map = project->getMap(connection->hostMapName());
if (map) map->removeConnection(connection);
delete connection;
// TODO: Edit history
}
void Editor::removeSelectedConnection() {
if (selected_connection_item)
removeConnection(selected_connection_item->connection);
}
void Editor::removeConnectionPixmap(ConnectionPixmapItem* pixmapItem) {
if (!pixmapItem)
return;
int index = connection_items.indexOf(pixmapItem);
if (index >= 0) { if (index >= 0) {
connection_items.removeAt(index); connection_items.removeAt(index);
if (connectionItem == selected_connection_item) { if (pixmapItem == selected_connection_item) {
// This was the selected connection, select the next one up in the list. // This was the selected connection, select the next one up in the list.
selected_connection_item = nullptr; selected_connection_item = nullptr;
if (index != 0) index--; if (index != 0) index--;
@ -856,117 +882,53 @@ void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem) {
} }
} }
if (connectionItem->scene()) if (pixmapItem->scene())
connectionItem->scene()->removeItem(connectionItem); pixmapItem->scene()->removeItem(pixmapItem);
removeConnection(connectionItem->connection); delete pixmapItem;
delete connectionItem;
}
void Editor::removeSelectedConnection() {
removeConnectionItem(selected_connection_item);
}
void Editor::removeConnection(MapConnection* connection, bool removeMirror) {
if (!connection)
return;
if (removeMirror)
removeMirroredConnection(connection);
Map* map = project->getMap(connection->hostMapName());
if (!map)
return;
if (map == this->map) {
// The connection to delete is displayed on the currently-opened map, we need to delete it visually as well.
if (connection->direction() == "dive") {
clearDiveMap();
} else if (connection->direction() == "emerge") {
clearEmergeMap();
} else {
// Find and delete the matching connection graphics.
// If this was called via removeConnectionItem we rely on
// the item having already been removed from this list.
for (auto item :connection_items) {
if (item->connection == connection) {
item->connection = nullptr;
removeConnectionItem(item);
break;
}
}
}
}
map->connections.removeOne(connection);
delete connection;
emit editedMapData(map);
}
MapConnection* Editor::getMirroredConnection(MapConnection* source) {
if (!source || !porymapConfig.mirrorConnectingMaps)
return nullptr;
// Note: It's possible (and ok) for connectedMap == this->map
Map *connectedMap = project->getMap(source->targetMapName());
if (!connectedMap)
return nullptr;
// Find the matching connection in the connected map.
// Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed
// to always get the same MapConnection if there are multiple identical copies.
for (auto connection : connectedMap->connections) {
if (connection != source && connection->isMirror(source))
return connection;
}
return nullptr;
}
void Editor::addMirroredConnection(MapConnection* source) {
if (!source || !porymapConfig.mirrorConnectingMaps)
return;
addConnection(source->createMirror(), false);
}
void Editor::removeMirroredConnection(MapConnection* source) {
removeConnection(getMirroredConnection(source), false);
} }
// TODO: Self-connecting a Dive/Emerge map connection will not actually replace any existing Dive/Emerge connection, if there is one. // TODO: Self-connecting a Dive/Emerge map connection will not actually replace any existing Dive/Emerge connection, if there is one.
void Editor::createDiveEmergeConnection(MapConnection* connection) { void Editor::displayDiveEmergeConnection(MapConnection* connection) {
if (!connection) if (!connection)
return; return;
// Create image of Dive/Emerge map // Note: We only support editing 1 Dive and Emerge connection per map.
QPixmap pixmap; // In a vanilla game only the first Dive/Emerge connection is considered, so allowing
Map *connectedMap = project->getMap(connection->targetMapName()); // users to have multiple is likely to lead to confusion. In case users have changed
if (!connectedMap || connectedMap == this->map) { // this we won't delete extra diving connections, but we'll only display the first one.
// There's no point in rendering a map on top of itself. if (connection->direction() == "dive") {
// We create an empty image anyway to allow for changes later. if (dive_map_overlay) return;
pixmap = QPixmap(); } else if (connection->direction() == "emerge") {
if (emerge_map_overlay) return;
} else { } else {
pixmap = connectedMap->render(); // Invalid direction
return;
} }
// Create image of Dive/Emerge map (unless we'd be rendering the current map on top of itself)
QPixmap pixmap = (connection->targetMapName() == this->map->name) ? QPixmap() : connection->getPixmap();
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
scene->addItem(item); scene->addItem(item);
if (connection->direction() == "dive") { if (connection->direction() == "dive") {
clearDiveMap();
dive_map_overlay = item; dive_map_overlay = item;
const QSignalBlocker blocker(ui->comboBox_DiveMap); const QSignalBlocker blocker(ui->comboBox_DiveMap);
ui->comboBox_DiveMap->setCurrentText(connection->targetMapName()); ui->comboBox_DiveMap->setCurrentText(connection->targetMapName());
} else if (connection->direction() == "emerge") { connect(connection, &MapConnection::destroyed, this, &Editor::clearDiveMap);
clearEmergeMap(); connect(connection, &MapConnection::hostMapNameChanged, this, &Editor::clearDiveMap);
} else {
emerge_map_overlay = item; emerge_map_overlay = item;
const QSignalBlocker blocker(ui->comboBox_EmergeMap); const QSignalBlocker blocker(ui->comboBox_EmergeMap);
ui->comboBox_EmergeMap->setCurrentText(connection->targetMapName()); ui->comboBox_EmergeMap->setCurrentText(connection->targetMapName());
} else { connect(connection, &MapConnection::destroyed, this, &Editor::clearEmergeMap);
// Shouldn't happen connect(connection, &MapConnection::hostMapNameChanged, this, &Editor::clearEmergeMap);
scene->removeItem(item);
delete item;
} }
// Update pixmap if the connected map is swapped
connect(connection, &MapConnection::targetMapNameChanged, [this, item, connection] {
item->setPixmap((connection->targetMapName() == this->map->name) ? QPixmap() : connection->getPixmap());
});
} }
void Editor::updateDiveMap(QString mapName) { void Editor::updateDiveMap(QString mapName) {
@ -978,11 +940,6 @@ void Editor::updateEmergeMap(QString mapName) {
} }
void Editor::setDiveEmergeMapName(QString mapName, QString direction) { void Editor::setDiveEmergeMapName(QString mapName, QString direction) {
if (!mapName.isEmpty() && !project->mapNamesToMapConstants.contains(mapName)) {
logError(QString("Invalid %1 connection map name: '%2'").arg(direction).arg(mapName));
return;
}
// Only the first Dive/Emerge map (if present) is considered, as in-game. // Only the first Dive/Emerge map (if present) is considered, as in-game.
MapConnection* connection = nullptr; MapConnection* connection = nullptr;
for (MapConnection* conn : map->connections) { for (MapConnection* conn : map->connections) {
@ -996,13 +953,13 @@ void Editor::setDiveEmergeMapName(QString mapName, QString direction) {
// Update existing connection // Update existing connection
if (mapName.isEmpty()) { if (mapName.isEmpty()) {
removeConnection(connection); removeConnection(connection);
// TODO: Queue up another Dive/Emerge map if there is one
} else { } else {
setConnectionMap(connection, mapName); connection->setTargetMapName(mapName);
} }
} else if (!mapName.isEmpty()) { } else if (!mapName.isEmpty()) {
// Create new connection // Create new connection
connection = new MapConnection(direction, map->name, mapName); addConnection(new MapConnection(direction, map->name, mapName));
addConnection(connection);
} }
updateDiveEmergeVisibility(); updateDiveEmergeVisibility();
} }
@ -1024,6 +981,7 @@ void Editor::updateDiveEmergeVisibility() {
} }
} }
// TODO: Fold into PixmapItem
QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap) { QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap) {
const QString direction = connection->direction(); const QString direction = connection->direction();
int offset = connection->offset(); int offset = connection->offset();
@ -1045,132 +1003,46 @@ QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPix
return QPoint(x, y); return QPoint(x, y);
} }
QPixmap Editor::getConnectionPixmap(MapConnection *connection) { void Editor::updateConnectionPixmap(ConnectionPixmapItem* pixmapItem) {
Map *connectedMap = project->getMap(connection->targetMapName()); if (!pixmapItem || !pixmapItem->connection)
// connectedMap will be null for MAP_DYNAMIC and any map that fails to load.
// The connection will be editable from the list, but no image will be displayed on the map.
if (!connectedMap)
return QPixmap();
return connectedMap->renderConnection(connection->direction(), this->map->layout);
}
void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) {
if (!connectionItem || !connectionItem->connection)
return; return;
const QString mapName = connectionItem->connection->targetMapName(); pixmapItem->initialOffset = pixmapItem->connection->offset();
if (mapName.isEmpty()) pixmapItem->basePixmap = pixmapItem->connection->getPixmap();
return; QPoint pos = calculateConnectionPosition(pixmapItem->connection, pixmapItem->basePixmap);
if (!project->mapNames.contains(mapName)) { const QSignalBlocker blocker(pixmapItem);
logError(QString("Invalid map name '%1' specified for connection.").arg(mapName)); pixmapItem->setPixmap(pixmapItem->basePixmap);
return; pixmapItem->initialX = pos.x();
} pixmapItem->initialY = pos.y();
pixmapItem->setPos(pos);
connectionItem->initialOffset = connectionItem->connection->offset(); pixmapItem->render();
connectionItem->basePixmap = getConnectionPixmap(connectionItem->connection);
QPoint pos = calculateConnectionPosition(connectionItem->connection, connectionItem->basePixmap);
const QSignalBlocker blocker(connectionItem);
connectionItem->setPixmap(connectionItem->basePixmap);
connectionItem->initialX = pos.x();
connectionItem->initialY = pos.y();
connectionItem->setX(pos.x());
connectionItem->setY(pos.y());
connectionItem->render();
maskNonVisibleConnectionTiles(); maskNonVisibleConnectionTiles();
} }
void Editor::updateConnectionItemPos(ConnectionPixmapItem* connectionItem) { void Editor::updateConnectionPixmapPos(ConnectionPixmapItem* pixmapItem) {
if (!connectionItem || !connectionItem->connection) if (!pixmapItem || !pixmapItem->connection)
return; return;
const QSignalBlocker blocker(connectionItem); const QSignalBlocker blocker(pixmapItem);
MapConnection *connection = connectionItem->connection; MapConnection *connection = pixmapItem->connection;
if (MapConnection::isVertical(connection->direction())) { if (MapConnection::isVertical(connection->direction())) {
connectionItem->setX(connectionItem->initialX + (connection->offset() - connectionItem->initialOffset) * 16); qreal x = pixmapItem->initialX + (connection->offset() - pixmapItem->initialOffset) * 16;
if (x != pixmapItem->x()) pixmapItem->setX(x);
} else if (MapConnection::isHorizontal(connection->direction())) { } else if (MapConnection::isHorizontal(connection->direction())) {
connectionItem->setY(connectionItem->initialY + (connection->offset() - connectionItem->initialOffset) * 16); qreal y = pixmapItem->initialY + (connection->offset() - pixmapItem->initialOffset) * 16;
if (y != pixmapItem->y()) pixmapItem->setY(y);
} }
maskNonVisibleConnectionTiles(); maskNonVisibleConnectionTiles();
} }
void Editor::setConnectionOffset(MapConnection *connection, int offset) { void Editor::setSelectedConnection(ConnectionPixmapItem* pixmapItem) {
if (!connection || !this->map || connection->offset() == offset || !MapConnection::isCardinal(connection->direction())) if (!pixmapItem || pixmapItem == selected_connection_item)
return;
MapConnection *mirror = getMirroredConnection(connection);
if (mirror) {
mirror->setOffset(-offset);
Map *connectedMap = project->getMap(mirror->hostMapName());
if (connectedMap != this->map) {
emit editedMapData(connectedMap);
} else {
// TODO: Remove, this will be handled by connecting to the MapConnection
// The mirror is displayed on the current map, update its graphics
for (auto item :connection_items) {
if (item->connection == mirror) {
updateConnectionItemPos(item);
break;
}
}
for (auto listItem : ui->scrollAreaContents_ConnectionsList->findChildren<ConnectionsListItem*>()) {
if (listItem->connection == mirror){
listItem->updateUI();
break;
}
}
}
}
connection->setOffset(offset);
emit editedMapData(this->map);
// TODO: This is likely the source of the visual masking bug while dragging (this happens after the move)
maskNonVisibleConnectionTiles();
}
void Editor::setConnectionMap(MapConnection *connection, const QString &mapName) {
if (!connection || !map || connection->targetMapName() == mapName)
return;
removeMirroredConnection(connection);
connection->setTargetMapName(mapName);
addMirroredConnection(connection);
emit editedMapData(map);
}
void Editor::setConnectionDirection(MapConnection *connection, const QString &direction) {
if (!connection || !map || connection->direction() == direction)
return;
// TODO: Lazy
removeMirroredConnection(connection);
if (MapConnection::isHorizontal(connection->direction()) != MapConnection::isHorizontal(direction)
|| MapConnection::isVertical(connection->direction()) != MapConnection::isVertical(direction)) {
// If the direction has changed between vertical/horizontal then the old offset may not make sense, so we reset it
setConnectionOffset(connection, 0);
}
connection->setDirection(direction);
addMirroredConnection(connection);
emit editedMapData(map);
}
void Editor::setSelectedConnection(ConnectionPixmapItem* connectionItem) {
if (!connectionItem || connectionItem == selected_connection_item)
return; return;
if (selected_connection_item) selected_connection_item->setSelected(false); if (selected_connection_item) selected_connection_item->setSelected(false);
selected_connection_item = connectionItem; selected_connection_item = pixmapItem;
selected_connection_item->setSelected(true); selected_connection_item->setSelected(true);
} }
@ -1185,6 +1057,10 @@ void Editor::setSelectedConnectionFromMap(QString mapName) {
} }
} }
void Editor::onMapConnectionDoubleClicked(MapConnection* connection) {
emit openConnectedMap(connection->targetMapName(), connection->hostMapName());
}
void Editor::onBorderMetatilesChanged() { void Editor::onBorderMetatilesChanged() {
displayMapBorder(); displayMapBorder();
updateBorderVisibility(); // TODO: Why do we need to call this here updateBorderVisibility(); // TODO: Why do we need to call this here
@ -1368,6 +1244,8 @@ bool Editor::setMap(QString map_name) {
// multiple times if set again in the future // multiple times if set again in the future
if (map) { if (map) {
map->disconnect(this); map->disconnect(this);
for (auto connection : map->connections)
connection->disconnect();
} }
if (project) { if (project) {
@ -1387,6 +1265,7 @@ bool Editor::setMap(QString map_name) {
map_ruler->setMapDimensions(QSize(map->getWidth(), map->getHeight())); map_ruler->setMapDimensions(QSize(map->getWidth(), map->getHeight()));
connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions); connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions);
connect(map, &Map::openScriptRequested, this, &Editor::openScript); connect(map, &Map::openScriptRequested, this, &Editor::openScript);
connect(map, &Map::connectionAdded, this, &Editor::displayConnection);
updateSelectedEvents(); updateSelectedEvents();
} }
@ -1907,23 +1786,8 @@ void Editor::clearEmergeMap() {
void Editor::displayMapConnections() { void Editor::displayMapConnections() {
clearMapConnections(); clearMapConnections();
// Note: We only support editing 1 Dive and Emerge connection per map. for (MapConnection *connection : map->connections)
// In a vanilla game only the first Dive/Emerge connection is considered, so allowing displayConnection(connection);
// users to have multiple is likely to lead to confusion. In case users have changed
// this we won't delete extra diving connections, but we'll only display the first one.
// TODO: Move text check to inside createDiveEmergeConnection?
for (MapConnection *connection : map->connections) {
if (connection->direction() == "dive") {
if (ui->comboBox_DiveMap->currentText().isEmpty())
createDiveEmergeConnection(connection);
} else if (connection->direction() == "emerge") {
if (ui->comboBox_EmergeMap->currentText().isEmpty())
createDiveEmergeConnection(connection);
} else {
// We allow any unknown direction names here. They'll be editable from the list menu.
createConnectionItem(connection);
}
}
if (!connection_items.empty()) if (!connection_items.empty())
setSelectedConnection(connection_items.first()); setSelectedConnection(connection_items.first());
@ -2001,7 +1865,7 @@ void Editor::updateMapConnections() {
for (auto item : connection_items) { for (auto item : connection_items) {
if (!item->connection) if (!item->connection)
continue; continue;
item->basePixmap = getConnectionPixmap(item->connection); item->basePixmap = item->connection->getPixmap();
item->render(); item->render();
} }
@ -2107,7 +1971,7 @@ void Editor::updateBorderVisibility() {
void Editor::updateCustomMapHeaderValues(QTableWidget *table) void Editor::updateCustomMapHeaderValues(QTableWidget *table)
{ {
map->customHeaders = CustomAttributesTable::getAttributes(table); map->customHeaders = CustomAttributesTable::getAttributes(table);
emit editedMapData(map); map->modify();
} }
Tileset* Editor::getCurrentMapPrimaryTileset() Tileset* Editor::getCurrentMapPrimaryTileset()

View file

@ -306,12 +306,11 @@ void MainWindow::checkForUpdates(bool) {}
void MainWindow::initEditor() { void MainWindow::initEditor() {
this->editor = new Editor(ui); this->editor = new Editor(ui);
connect(this->editor, &Editor::objectsChanged, this, &MainWindow::updateObjects); connect(this->editor, &Editor::objectsChanged, this, &MainWindow::updateObjects);
connect(this->editor, &Editor::connectionItemDoubleClicked, this, &MainWindow::onConnectionItemDoubleClicked); connect(this->editor, &Editor::openConnectedMap, this, &MainWindow::onOpenConnectedMap);
connect(this->editor, &Editor::warpEventDoubleClicked, this, &MainWindow::openWarpMap); connect(this->editor, &Editor::warpEventDoubleClicked, this, &MainWindow::openWarpMap);
connect(this->editor, &Editor::currentMetatilesSelectionChanged, this, &MainWindow::currentMetatilesSelectionChanged); connect(this->editor, &Editor::currentMetatilesSelectionChanged, this, &MainWindow::currentMetatilesSelectionChanged);
connect(this->editor, &Editor::wildMonDataChanged, this, &MainWindow::onWildMonDataChanged); connect(this->editor, &Editor::wildMonDataChanged, this, &MainWindow::onWildMonDataChanged);
connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged); connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged);
connect(this->editor, &Editor::editedMapData, [this](Map* map) { this->markMapEdited(map); });
connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated); connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated);
connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this->editor, &Editor::openMapScripts); connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this->editor, &Editor::openMapScripts);
connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this->editor, &Editor::openProjectInTextEditor); connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this->editor, &Editor::openProjectInTextEditor);
@ -569,15 +568,17 @@ bool MainWindow::openProject(QString dir, bool initial) {
Scripting::init(this); Scripting::init(this);
// Create the project // Create the project
this->editor->project = new Project(this); auto project = new Project(this);
QObject::connect(this->editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered); project->set_root(dir);
QObject::connect(this->editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared); QObject::connect(project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered);
QObject::connect(this->editor->project, &Project::uncheckMonitorFilesAction, [this]() { QObject::connect(project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared);
QObject::connect(project, &Project::mapLoaded, this, &MainWindow::onMapLoaded);
QObject::connect(project, &Project::uncheckMonitorFilesAction, [this]() {
porymapConfig.monitorFiles = false; porymapConfig.monitorFiles = false;
if (this->preferenceEditor) if (this->preferenceEditor)
this->preferenceEditor->updateFields(); this->preferenceEditor->updateFields();
}); });
this->editor->project->set_root(dir); this->editor->setProject(project);
// Make sure project looks reasonable before attempting to load it // Make sure project looks reasonable before attempting to load it
if (!checkProjectSanity()) { if (!checkProjectSanity()) {
@ -805,7 +806,6 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) {
showWindowTitle(); showWindowTitle();
connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing); connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing);
connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); });
userConfig.recentMap = map_name; userConfig.recentMap = map_name;
updateMapList(); updateMapList();
@ -2526,7 +2526,7 @@ void MainWindow::clickToolButtonFromEditMode(QString editMode) {
} }
} }
void MainWindow::onConnectionItemDoubleClicked(QString mapName, QString fromMapName) { void MainWindow::onOpenConnectedMap(QString mapName, QString fromMapName) {
if (mapName != fromMapName && userSetMap(mapName, true)) if (mapName != fromMapName && userSetMap(mapName, true))
editor->setSelectedConnectionFromMap(fromMapName); editor->setSelectedConnectionFromMap(fromMapName);
} }
@ -2539,6 +2539,10 @@ void MainWindow::onMapCacheCleared() {
editor->map = nullptr; editor->map = nullptr;
} }
void MainWindow::onMapLoaded(Map *map) {
connect(map, &Map::modified, [this, map] { this->markMapEdited(map); });
}
void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) { void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) {
// If saved tilesets are currently in-use, update them and redraw // If saved tilesets are currently in-use, update them and redraw
// Otherwise overwrite the cache for the saved tileset // Otherwise overwrite the cache for the saved tileset

View file

@ -186,10 +186,13 @@ Map* Project::loadMap(QString map_name) {
map->setName(map_name); map->setName(map_name);
} }
if (!(loadMapData(map) && loadMapLayout(map))) if (!(loadMapData(map) && loadMapLayout(map))){
delete map;
return nullptr; return nullptr;
}
mapCache.insert(map_name, map); mapCache.insert(map_name, map);
emit mapLoaded(map);
return map; return map;
} }

View file

@ -51,8 +51,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari
y = this->initialY; y = this->initialY;
} }
if (this->connection->offset() != newOffset) this->connection->setOffset(newOffset);
emit connectionMoved(this->connection, newOffset);
return QPointF(x, y); return QPointF(x, y);
} }
else { else {
@ -84,5 +83,5 @@ void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) {
} }
void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) { void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
emit connectionItemDoubleClicked(this); emit connectionItemDoubleClicked(this->connection);
} }

View file

@ -56,27 +56,25 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) {
} }
void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) { void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) {
emit doubleClicked(this->connection->targetMapName()); emit doubleClicked(this->connection);
} }
void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) { void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(const QString &direction) {
this->setSelected(true); this->setSelected(true);
if (this->connection->direction() != direction) this->connection->setDirection(direction);
emit this->editedDirection(this->connection, direction);
} }
void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) { void ConnectionsListItem::on_comboBox_Map_currentTextChanged(const QString &mapName) {
this->setSelected(true); this->setSelected(true);
if (ui->comboBox_Map->findText(mapName) >= 0 && this->connection->targetMapName() != mapName) if (ui->comboBox_Map->findText(mapName) >= 0)
emit this->editedMapName(this->connection, mapName); this->connection->setTargetMapName(mapName);
} }
void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) { void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) {
this->setSelected(true); this->setSelected(true);
if (this->connection->offset() != offset) this->connection->setOffset(offset);
emit editedOffset(this->connection, offset);
} }
void ConnectionsListItem::on_button_Delete_clicked() { void ConnectionsListItem::on_button_Delete_clicked() {
emit this->removed(); emit this->removed(this->connection);
} }