MapConnection to QObject

This commit is contained in:
GriffinR 2024-08-04 16:08:16 -04:00
parent 7eb3c17f4a
commit 4e04e57c05
11 changed files with 238 additions and 186 deletions

View file

@ -98,7 +98,7 @@ 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 *);
QPixmap renderConnection(const MapConnection&, 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);
void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false); void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);

View file

@ -3,32 +3,45 @@
#define MAPCONNECTION_H #define MAPCONNECTION_H
#include <QString> #include <QString>
#include <QHash> #include <QObject>
class Map; class MapConnection : public QObject
{
class MapConnection { Q_OBJECT
public: public:
QString direction; MapConnection(const QString &direction, const QString &hostMapName, const QString &targetMapName, int offset = 0);
int offset;
QString map_name; QString direction() const { return m_direction; }
void setDirection(const QString &direction);
QString hostMapName() const { return m_hostMapName; }
void setHostMapName(const QString &hostMapName);
QString targetMapName() const { return m_targetMapName; }
void setTargetMapName(const QString &targetMapName);
int offset() const { return m_offset; }
void setOffset(int offset);
MapConnection * createMirror();
bool isMirror(const MapConnection*);
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 MapConnection mirror(const MapConnection &source, const QString &mapName);
};
struct MapConnectionMirror { private:
MapConnection * connection = nullptr; QString m_direction;
Map * map = nullptr; QString m_hostMapName;
}; QString m_targetMapName;
int m_offset;
inline bool operator==(const MapConnection &c1, const MapConnection &c2) { signals:
return c1.direction == c2.direction && void directionChanged(const QString &before, const QString &after);
c1.offset == c2.offset && void targetMapNameChanged(const QString &before, const QString &after);
c1.map_name == c2.map_name; void hostMapNameChanged(const QString &before, const QString &after);
} void offsetChanged(int before, int after);
};
#endif // MAPCONNECTION_H #endif // MAPCONNECTION_H

View file

@ -77,8 +77,8 @@ public:
void setConnectionsVisibility(bool visible); void setConnectionsVisibility(bool visible);
void updateDiveEmergeVisibility(); void updateDiveEmergeVisibility();
void addNewConnection(); void addNewConnection();
void addConnection(Map* map, MapConnection* connection, bool addMirror = true); void addConnection(MapConnection* connection, bool addMirror = true);
void removeConnection(Map* map, MapConnection* connection, bool removeMirror = true); void removeConnection(MapConnection* connection, bool removeMirror = true);
void removeConnectionItem(ConnectionPixmapItem* connectionItem); void removeConnectionItem(ConnectionPixmapItem* connectionItem);
void removeSelectedConnection(); void removeSelectedConnection();
void addNewWildMonGroup(QWidget *window); void addNewWildMonGroup(QWidget *window);
@ -185,14 +185,14 @@ private:
void clearMapGrid(); void clearMapGrid();
void clearWildMonTables(); void clearWildMonTables();
void updateBorderVisibility(); void updateBorderVisibility();
QPoint calculateConnectionPosition(const MapConnection &connection, const QPixmap &pixmap); QPoint calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap);
QPixmap getConnectionPixmap(const MapConnection &connection); QPixmap getConnectionPixmap(MapConnection *connection);
void updateConnectionItem(ConnectionPixmapItem* connectionItem); void updateConnectionItem(ConnectionPixmapItem* connectionItem);
void updateConnectionItemPos(ConnectionPixmapItem* connectionItem); void updateConnectionItemPos(ConnectionPixmapItem* connectionItem);
void createConnectionItem(MapConnection* connection); void createConnectionItem(MapConnection* connection);
void createDiveEmergeConnection(MapConnection* connection); void createDiveEmergeConnection(MapConnection* connection);
void setDiveEmergeMapName(QString mapName, QString direction); void setDiveEmergeMapName(QString mapName, QString direction);
MapConnectionMirror getMirroredConnection(MapConnection*); MapConnection* getMirroredConnection(MapConnection*);
void addMirroredConnection(MapConnection*); void addMirroredConnection(MapConnection*);
void removeMirroredConnection(MapConnection*); void removeMirroredConnection(MapConnection*);
void updateEncounterFields(EncounterFields newFields); void updateEncounterFields(EncounterFields newFields);

View file

@ -17,7 +17,7 @@ public:
setFlag(ItemSendsGeometryChanges); setFlag(ItemSendsGeometryChanges);
this->initialX = x; this->initialX = x;
this->initialY = y; this->initialY = y;
this->initialOffset = connection->offset; this->initialOffset = connection->offset();
this->setX(x); this->setX(x);
this->setY(y); this->setY(y);
} }

View file

@ -217,20 +217,20 @@ QPixmap Map::renderBorder(bool ignoreCache) {
return layout->border_pixmap; return layout->border_pixmap;
} }
QPixmap Map::renderConnection(const MapConnection &connection, MapLayout * fromLayout) { QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) {
if (!MapConnection::isCardinal(connection.direction)) if (!MapConnection::isCardinal(direction))
return QPixmap(); return QPixmap();
int x = 0, y = 0, w = getWidth(), h = getHeight(); int x = 0, y = 0, w = getWidth(), h = getHeight();
if (connection.direction == "up") { if (direction == "up") {
y = getHeight() - BORDER_DISTANCE; y = getHeight() - BORDER_DISTANCE;
h = BORDER_DISTANCE; h = BORDER_DISTANCE;
} else if (connection.direction == "down") { } else if (direction == "down") {
h = BORDER_DISTANCE; h = BORDER_DISTANCE;
} else if (connection.direction == "left") { } else if (direction == "left") {
x = getWidth() - BORDER_DISTANCE; x = getWidth() - BORDER_DISTANCE;
w = BORDER_DISTANCE; w = BORDER_DISTANCE;
} else if (connection.direction == "right") { } else if (direction == "right") {
w = BORDER_DISTANCE; w = BORDER_DISTANCE;
} }

View file

@ -1,25 +1,74 @@
#include <QMap>
#include "mapconnection.h" #include "mapconnection.h"
#include "map.h"
const QMap<QString, QString> oppositeDirections = {
{"up", "down"}, {"down", "up"},
{"right", "left"}, {"left", "right"},
{"dive", "emerge"}, {"emerge", "dive"}
};
MapConnection::MapConnection(const QString &direction, const QString &hostMapName, const QString &targetMapName, int offset) {
m_direction = direction;
m_hostMapName = hostMapName;
m_targetMapName = targetMapName;
m_offset = offset;
}
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) {
if (!other)
return false;
return m_hostMapName == other->m_targetMapName
&& m_targetMapName == other->m_hostMapName
&& m_offset == -other->m_offset
&& m_direction == oppositeDirections.value(other->m_direction, other->m_direction);
}
const QStringList MapConnection::cardinalDirections = { const QStringList MapConnection::cardinalDirections = {
"up", "down", "left", "right" "up", "down", "left", "right"
}; };
MapConnection MapConnection::mirror(const MapConnection &source, const QString &mapName) {
static const QMap<QString, QString> oppositeDirections = {
{"up", "down"}, {"down", "up"},
{"right", "left"}, {"left", "right"},
{"dive", "emerge"}, {"emerge", "dive"}
};
MapConnection mirror;
mirror.direction = oppositeDirections.value(source.direction, source.direction);
mirror.map_name = mapName;
mirror.offset = -source.offset;
return mirror;
}
bool MapConnection::isHorizontal(const QString &direction) { bool MapConnection::isHorizontal(const QString &direction) {
return direction == "left" || direction == "right"; return direction == "left" || direction == "right";
} }

View file

@ -730,8 +730,8 @@ void Editor::createConnectionItem(MapConnection* connection) {
return; return;
// Create connection image // Create connection image
QPixmap pixmap = getConnectionPixmap(*connection); QPixmap pixmap = getConnectionPixmap(connection);
QPoint pos = calculateConnectionPosition(*connection, pixmap); QPoint pos = calculateConnectionPosition(connection, pixmap);
ConnectionPixmapItem *connectionItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y()); ConnectionPixmapItem *connectionItem = new ConnectionPixmapItem(pixmap, connection, pos.x(), pos.y());
connectionItem->render(); connectionItem->render();
scene->addItem(connectionItem); scene->addItem(connectionItem);
@ -744,7 +744,7 @@ void Editor::createConnectionItem(MapConnection* connection) {
if (selected) setSelectedConnection(connectionItem); if (selected) setSelectedConnection(connectionItem);
}); });
connect(connectionItem, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, connectionItem] { connect(connectionItem, &ConnectionPixmapItem::connectionItemDoubleClicked, [this, connectionItem] {
emit this->connectionItemDoubleClicked(connectionItem->connection->map_name, map->name); emit this->connectionItemDoubleClicked(connectionItem->connection->targetMapName(), map->name);
}); });
// Sync the selection highlight between the list UI and the graphical map connection // Sync the selection highlight between the list UI and the graphical map connection
@ -796,7 +796,7 @@ void Editor::addNewConnection() {
// Find direction with least number of connections. // Find direction with least number of connections.
QMap<QString, int> directionCounts; QMap<QString, int> directionCounts;
for (MapConnection* connection : map->connections) { for (MapConnection* connection : map->connections) {
directionCounts[connection->direction]++; directionCounts[connection->direction()]++;
} }
QString minDirection = "up"; QString minDirection = "up";
int minCount = INT_MAX; int minCount = INT_MAX;
@ -813,25 +813,25 @@ void Editor::addNewConnection() {
defaultMapName = project->mapNames.at(1); defaultMapName = project->mapNames.at(1);
} }
MapConnection* newConnection = new MapConnection; addConnection(new MapConnection(minDirection, map->name, defaultMapName));
newConnection->direction = minDirection;
newConnection->offset = 0;
newConnection->map_name = defaultMapName;
addConnection(map, newConnection);
setSelectedConnection(connection_items.last()); setSelectedConnection(connection_items.last());
} }
void Editor::addConnection(Map* map, MapConnection * connection, bool addMirror) { void Editor::addConnection(MapConnection * connection, bool addMirror) {
if (!map || !connection) if (!connection)
return; return;
if (addMirror) if (addMirror)
addMirroredConnection(connection); addMirroredConnection(connection);
Map *map = project->getMap(connection->hostMapName());
if (!map)
return;
map->connections.append(connection); map->connections.append(connection);
if (map == this->map) { if (map == this->map) {
// Adding a connection to the current map, we need to display it visually. // Adding a connection to the current map, we need to display it visually.
if (connection->direction == "dive" || connection->direction == "emerge") { if (connection->direction() == "dive" || connection->direction() == "emerge") {
createDiveEmergeConnection(connection); createDiveEmergeConnection(connection);
} else { } else {
createConnectionItem(connection); createConnectionItem(connection);
@ -859,7 +859,7 @@ void Editor::removeConnectionItem(ConnectionPixmapItem* connectionItem) {
if (connectionItem->scene()) if (connectionItem->scene())
connectionItem->scene()->removeItem(connectionItem); connectionItem->scene()->removeItem(connectionItem);
removeConnection(map, connectionItem->connection); removeConnection(connectionItem->connection);
delete connectionItem; delete connectionItem;
} }
@ -868,18 +868,22 @@ void Editor::removeSelectedConnection() {
removeConnectionItem(selected_connection_item); removeConnectionItem(selected_connection_item);
} }
void Editor::removeConnection(Map* map, MapConnection* connection, bool removeMirror) { void Editor::removeConnection(MapConnection* connection, bool removeMirror) {
if (!map || !connection) if (!connection)
return; return;
if (removeMirror) if (removeMirror)
removeMirroredConnection(connection); removeMirroredConnection(connection);
Map* map = project->getMap(connection->hostMapName());
if (!map)
return;
if (map == this->map) { if (map == this->map) {
// The connection to delete is displayed on the currently-opened map, we need to delete it visually as well. // The connection to delete is displayed on the currently-opened map, we need to delete it visually as well.
if (connection->direction == "dive") { if (connection->direction() == "dive") {
clearDiveMap(); clearDiveMap();
} else if (connection->direction == "emerge") { } else if (connection->direction() == "emerge") {
clearEmergeMap(); clearEmergeMap();
} else { } else {
// Find and delete the matching connection graphics. // Find and delete the matching connection graphics.
@ -900,46 +904,34 @@ void Editor::removeConnection(Map* map, MapConnection* connection, bool removeMi
emit editedMapData(map); emit editedMapData(map);
} }
MapConnectionMirror Editor::getMirroredConnection(MapConnection* source) { MapConnection* Editor::getMirroredConnection(MapConnection* source) {
MapConnectionMirror mirror; if (!source || !ui->checkBox_MirrorConnections->isChecked())
if (!map || !source || !ui->checkBox_MirrorConnections->isChecked()) return nullptr;
return mirror;
// Note: It's possible (and ok) for mirror.map == this->map // Note: It's possible (and ok) for connectedMap == this->map
mirror.map = project->getMap(source->map_name); Map *connectedMap = project->getMap(source->targetMapName());
if (!mirror.map) if (!connectedMap)
return mirror; return nullptr;
// Find the matching connection in the connected map. // Find the matching connection in the connected map.
// Note: There is no strict source -> mirror pairing, i.e. we are not guaranteed // 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. // to always get the same MapConnection if there are multiple identical copies.
MapConnection target = MapConnection::mirror(*source, map->name); for (auto connection : connectedMap->connections) {
for (auto connection : mirror.map->connections) { if (connection != source && connection->isMirror(source))
if (*connection == target && connection != source) { return connection;
mirror.connection = connection;
break;
}
} }
return mirror;
return nullptr;
} }
void Editor::addMirroredConnection(MapConnection* source) { void Editor::addMirroredConnection(MapConnection* source) {
if (!map || !source || !ui->checkBox_MirrorConnections->isChecked()) if (!source || !ui->checkBox_MirrorConnections->isChecked())
return; return;
addConnection(source->createMirror(), false);
// Note: It's possible (and ok) for connectedMap == this->map
Map* connectedMap = project->getMap(source->map_name);
if (!connectedMap)
return;
MapConnection *mirror = new MapConnection;
*mirror = MapConnection::mirror(*source, map->name);
addConnection(connectedMap, mirror, false);
} }
void Editor::removeMirroredConnection(MapConnection* source) { void Editor::removeMirroredConnection(MapConnection* source) {
MapConnectionMirror mirror = getMirroredConnection(source); removeConnection(getMirroredConnection(source), false);
removeConnection(mirror.map, mirror.connection, 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.
@ -949,7 +941,7 @@ void Editor::createDiveEmergeConnection(MapConnection* connection) {
// Create image of Dive/Emerge map // Create image of Dive/Emerge map
QPixmap pixmap; QPixmap pixmap;
Map *connectedMap = project->getMap(connection->map_name); Map *connectedMap = project->getMap(connection->targetMapName());
if (!connectedMap || connectedMap == this->map) { if (!connectedMap || connectedMap == this->map) {
// There's no point in rendering a map on top of itself. // There's no point in rendering a map on top of itself.
// We create an empty image anyway to allow for changes later. // We create an empty image anyway to allow for changes later.
@ -960,16 +952,16 @@ void Editor::createDiveEmergeConnection(MapConnection* connection) {
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(); 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->map_name); ui->comboBox_DiveMap->setCurrentText(connection->targetMapName());
} else if (connection->direction == "emerge") { } else if (connection->direction() == "emerge") {
clearEmergeMap(); clearEmergeMap();
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->map_name); ui->comboBox_EmergeMap->setCurrentText(connection->targetMapName());
} else { } else {
// Shouldn't happen // Shouldn't happen
scene->removeItem(item); scene->removeItem(item);
@ -994,7 +986,7 @@ void Editor::setDiveEmergeMapName(QString mapName, QString direction) {
// 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) {
if (conn->direction == direction) { if (conn->direction() == direction) {
connection = conn; connection = conn;
break; break;
} }
@ -1003,17 +995,14 @@ void Editor::setDiveEmergeMapName(QString mapName, QString direction) {
if (connection) { if (connection) {
// Update existing connection // Update existing connection
if (mapName.isEmpty()) { if (mapName.isEmpty()) {
removeConnection(map, connection); removeConnection(connection);
} else { } else {
setConnectionMap(connection, mapName); setConnectionMap(connection, mapName);
} }
} else if (!mapName.isEmpty()) { } else if (!mapName.isEmpty()) {
// Create new connection // Create new connection
connection = new MapConnection; connection = new MapConnection(direction, map->name, mapName);
connection->direction = direction; addConnection(connection);
connection->offset = 0;
connection->map_name = mapName;
addConnection(map, connection);
} }
updateDiveEmergeVisibility(); updateDiveEmergeVisibility();
} }
@ -1035,41 +1024,43 @@ void Editor::updateDiveEmergeVisibility() {
} }
} }
QPoint Editor::calculateConnectionPosition(const MapConnection &connection, const QPixmap &pixmap) { QPoint Editor::calculateConnectionPosition(MapConnection *connection, const QPixmap &pixmap) {
const QString direction = connection->direction();
int offset = connection->offset();
int x = 0, y = 0; int x = 0, y = 0;
const int mWidth = 16, mHeight = 16; const int mWidth = 16, mHeight = 16;
if (connection.direction == "up") { if (direction == "up") {
x = connection.offset * mWidth; x = offset * mWidth;
y = -pixmap.height(); y = -pixmap.height();
} else if (connection.direction == "down") { } else if (direction == "down") {
x = connection.offset * mWidth; x = offset * mWidth;
y = map->getHeight() * mHeight; y = map->getHeight() * mHeight;
} else if (connection.direction == "left") { } else if (direction == "left") {
x = -pixmap.width(); x = -pixmap.width();
y = connection.offset * mHeight; y = offset * mHeight;
} else if (connection.direction == "right") { } else if (direction == "right") {
x = map->getWidth() * mWidth; x = map->getWidth() * mWidth;
y = connection.offset * mHeight; y = offset * mHeight;
} }
return QPoint(x, y); return QPoint(x, y);
} }
QPixmap Editor::getConnectionPixmap(const MapConnection &connection) { QPixmap Editor::getConnectionPixmap(MapConnection *connection) {
Map *connectedMap = project->getMap(connection.map_name); Map *connectedMap = project->getMap(connection->targetMapName());
// connectedMap will be null for MAP_DYNAMIC and any map that fails to load. // 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. // The connection will be editable from the list, but no image will be displayed on the map.
if (!connectedMap) if (!connectedMap)
return QPixmap(); return QPixmap();
return connectedMap->renderConnection(connection, map->layout); return connectedMap->renderConnection(connection->direction(), this->map->layout);
} }
void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) { void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) {
if (!connectionItem || !connectionItem->connection) if (!connectionItem || !connectionItem->connection)
return; return;
const QString mapName = connectionItem->connection->map_name; const QString mapName = connectionItem->connection->targetMapName();
if (mapName.isEmpty()) if (mapName.isEmpty())
return; return;
@ -1078,18 +1069,17 @@ void Editor::updateConnectionItem(ConnectionPixmapItem* connectionItem) {
return; return;
} }
connectionItem->initialOffset = connectionItem->connection->offset; connectionItem->initialOffset = connectionItem->connection->offset();
connectionItem->basePixmap = getConnectionPixmap(*connectionItem->connection); connectionItem->basePixmap = getConnectionPixmap(connectionItem->connection);
QPoint pos = calculateConnectionPosition(*connectionItem->connection, connectionItem->basePixmap); QPoint pos = calculateConnectionPosition(connectionItem->connection, connectionItem->basePixmap);
connectionItem->blockSignals(true); const QSignalBlocker blocker(connectionItem);
connectionItem->setPixmap(connectionItem->basePixmap); connectionItem->setPixmap(connectionItem->basePixmap);
connectionItem->initialX = pos.x(); connectionItem->initialX = pos.x();
connectionItem->initialY = pos.y(); connectionItem->initialY = pos.y();
connectionItem->setX(pos.x()); connectionItem->setX(pos.x());
connectionItem->setY(pos.y()); connectionItem->setY(pos.y());
connectionItem->render(); connectionItem->render();
connectionItem->blockSignals(false);
maskNonVisibleConnectionTiles(); maskNonVisibleConnectionTiles();
} }
@ -1098,37 +1088,39 @@ void Editor::updateConnectionItemPos(ConnectionPixmapItem* connectionItem) {
if (!connectionItem || !connectionItem->connection) if (!connectionItem || !connectionItem->connection)
return; return;
const QSignalBlocker blocker(connectionItem);
MapConnection *connection = connectionItem->connection; MapConnection *connection = connectionItem->connection;
connectionItem->blockSignals(true); if (MapConnection::isVertical(connection->direction())) {
if (MapConnection::isVertical(connection->direction)) { connectionItem->setX(connectionItem->initialX + (connection->offset() - connectionItem->initialOffset) * 16);
connectionItem->setX(connectionItem->initialX + (connection->offset - connectionItem->initialOffset) * 16); } else if (MapConnection::isHorizontal(connection->direction())) {
} else if (MapConnection::isHorizontal(connection->direction)) { connectionItem->setY(connectionItem->initialY + (connection->offset() - connectionItem->initialOffset) * 16);
connectionItem->setY(connectionItem->initialY + (connection->offset - connectionItem->initialOffset) * 16);
} }
connectionItem->blockSignals(false);
maskNonVisibleConnectionTiles(); maskNonVisibleConnectionTiles();
} }
void Editor::setConnectionOffset(MapConnection *connection, int offset) { void Editor::setConnectionOffset(MapConnection *connection, int offset) {
if (!connection || !map || connection->offset == offset || !MapConnection::isCardinal(connection->direction)) if (!connection || !this->map || connection->offset() == offset || !MapConnection::isCardinal(connection->direction()))
return; return;
MapConnectionMirror mirror = getMirroredConnection(connection); MapConnection *mirror = getMirroredConnection(connection);
if (mirror.connection && mirror.map) { if (mirror) {
mirror.connection->offset = -offset; mirror->setOffset(-offset);
if (mirror.map != map) {
emit editedMapData(mirror.map); Map *connectedMap = project->getMap(mirror->hostMapName());
if (connectedMap != this->map) {
emit editedMapData(connectedMap);
} else { } else {
// TODO: Remove, this will be handled by connecting to the MapConnection
// The mirror is displayed on the current map, update its graphics // The mirror is displayed on the current map, update its graphics
for (auto item :connection_items) { for (auto item :connection_items) {
if (item->connection == mirror.connection) { if (item->connection == mirror) {
updateConnectionItemPos(item); updateConnectionItemPos(item);
break; break;
} }
} }
// TODO: We should be signaling to the list item from the pixmap item, rather than searching for it.
for (auto listItem : ui->scrollAreaContents_ConnectionsList->findChildren<ConnectionsListItem*>()) { for (auto listItem : ui->scrollAreaContents_ConnectionsList->findChildren<ConnectionsListItem*>()) {
if (listItem->connection == mirror.connection){ if (listItem->connection == mirror){
listItem->updateUI(); listItem->updateUI();
break; break;
} }
@ -1136,37 +1128,37 @@ void Editor::setConnectionOffset(MapConnection *connection, int offset) {
} }
} }
connection->offset = offset; connection->setOffset(offset);
emit editedMapData(map); emit editedMapData(this->map);
// TODO: This is likely the source of the visual masking bug while dragging (this happens after the move) // TODO: This is likely the source of the visual masking bug while dragging (this happens after the move)
maskNonVisibleConnectionTiles(); maskNonVisibleConnectionTiles();
} }
void Editor::setConnectionMap(MapConnection *connection, const QString &mapName) { void Editor::setConnectionMap(MapConnection *connection, const QString &mapName) {
if (!connection || !map || connection->map_name == mapName) if (!connection || !map || connection->targetMapName() == mapName)
return; return;
removeMirroredConnection(connection); removeMirroredConnection(connection);
connection->map_name = mapName; connection->setTargetMapName(mapName);
addMirroredConnection(connection); addMirroredConnection(connection);
emit editedMapData(map); emit editedMapData(map);
} }
void Editor::setConnectionDirection(MapConnection *connection, const QString &direction) { void Editor::setConnectionDirection(MapConnection *connection, const QString &direction) {
if (!connection || !map || connection->direction == direction) if (!connection || !map || connection->direction() == direction)
return; return;
// TODO: Lazy // TODO: Lazy
removeMirroredConnection(connection); removeMirroredConnection(connection);
if (MapConnection::isHorizontal(connection->direction) != MapConnection::isHorizontal(direction) if (MapConnection::isHorizontal(connection->direction()) != MapConnection::isHorizontal(direction)
|| MapConnection::isVertical(connection->direction) != MapConnection::isVertical(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 // If the direction has changed between vertical/horizontal then the old offset may not make sense, so we reset it
setConnectionOffset(connection, 0); setConnectionOffset(connection, 0);
} }
connection->direction = direction; connection->setDirection(direction);
addMirroredConnection(connection); addMirroredConnection(connection);
@ -1184,9 +1176,9 @@ void Editor::setSelectedConnection(ConnectionPixmapItem* connectionItem) {
// TODO: Inaccurate if there are multiple connections from the same map // TODO: Inaccurate if there are multiple connections from the same map
void Editor::setSelectedConnectionFromMap(QString mapName) { void Editor::setSelectedConnectionFromMap(QString mapName) {
// Search for the first connection that connects to the given map map. // Search for the first connection that connects to the given map.
for (ConnectionPixmapItem* item : connection_items) { for (ConnectionPixmapItem* item : connection_items) {
if (item->connection->map_name == mapName) { if (item->connection->targetMapName() == mapName) {
setSelectedConnection(item); setSelectedConnection(item);
break; break;
} }
@ -1921,10 +1913,10 @@ void Editor::displayMapConnections() {
// this we won't delete extra diving connections, but we'll only display the first one. // this we won't delete extra diving connections, but we'll only display the first one.
// TODO: Move text check to inside createDiveEmergeConnection? // TODO: Move text check to inside createDiveEmergeConnection?
for (MapConnection *connection : map->connections) { for (MapConnection *connection : map->connections) {
if (connection->direction == "dive") { if (connection->direction() == "dive") {
if (ui->comboBox_DiveMap->currentText().isEmpty()) if (ui->comboBox_DiveMap->currentText().isEmpty())
createDiveEmergeConnection(connection); createDiveEmergeConnection(connection);
} else if (connection->direction == "emerge") { } else if (connection->direction() == "emerge") {
if (ui->comboBox_EmergeMap->currentText().isEmpty()) if (ui->comboBox_EmergeMap->currentText().isEmpty())
createDiveEmergeConnection(connection); createDiveEmergeConnection(connection);
} else { } else {
@ -2009,7 +2001,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 = getConnectionPixmap(item->connection);
item->render(); item->render();
} }

View file

@ -370,12 +370,12 @@ bool Project::loadMapData(Map* map) {
if (!connectionsArr.isEmpty()) { if (!connectionsArr.isEmpty()) {
for (int i = 0; i < connectionsArr.size(); i++) { for (int i = 0; i < connectionsArr.size(); i++) {
QJsonObject connectionObj = connectionsArr[i].toObject(); QJsonObject connectionObj = connectionsArr[i].toObject();
MapConnection *connection = new MapConnection; const QString direction = ParseUtil::jsonToQString(connectionObj["direction"]);
connection->direction = ParseUtil::jsonToQString(connectionObj["direction"]); int offset = ParseUtil::jsonToInt(connectionObj["offset"]);
connection->offset = ParseUtil::jsonToInt(connectionObj["offset"]); const QString mapConstant = ParseUtil::jsonToQString(connectionObj["map"]);
QString mapConstant = ParseUtil::jsonToQString(connectionObj["map"]);
if (mapConstantsToMapNames.contains(mapConstant)) { if (mapConstantsToMapNames.contains(mapConstant)) {
connection->map_name = mapConstantsToMapNames.value(mapConstant); // Successully read map connection
MapConnection *connection = new MapConnection(direction, map->name, mapConstantsToMapNames.value(mapConstant), offset);
map->connections.append(connection); map->connections.append(connection);
} else { } else {
logError(QString("Failed to find connected map for map constant '%1'").arg(mapConstant)); logError(QString("Failed to find connected map for map constant '%1'").arg(mapConstant));
@ -1280,14 +1280,14 @@ void Project::saveMap(Map *map) {
if (map->connections.length() > 0) { if (map->connections.length() > 0) {
OrderedJson::array connectionsArr; OrderedJson::array connectionsArr;
for (MapConnection* connection : map->connections) { for (MapConnection* connection : map->connections) {
if (mapNamesToMapConstants.contains(connection->map_name)) { if (mapNamesToMapConstants.contains(connection->targetMapName())) {
OrderedJson::object connectionObj; OrderedJson::object connectionObj;
connectionObj["map"] = this->mapNamesToMapConstants.value(connection->map_name); connectionObj["map"] = this->mapNamesToMapConstants.value(connection->targetMapName());
connectionObj["offset"] = connection->offset; connectionObj["offset"] = connection->offset();
connectionObj["direction"] = connection->direction; connectionObj["direction"] = connection->direction();
connectionsArr.append(connectionObj); connectionsArr.append(connectionObj);
} else { } else {
logError(QString("Failed to write map connection. '%1' is not a valid map name").arg(connection->map_name)); logError(QString("Failed to write map connection. '%1' is not a valid map name").arg(connection->targetMapName()));
} }
} }
mapObj["connections"] = connectionsArr; mapObj["connections"] = connectionsArr;

View file

@ -33,7 +33,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari
qreal x, y; qreal x, y;
int newOffset = this->initialOffset; int newOffset = this->initialOffset;
if (MapConnection::isVertical(this->connection->direction)) { if (MapConnection::isVertical(this->connection->direction())) {
x = round(newPos.x() / 16) * 16; x = round(newPos.x() / 16) * 16;
newOffset += (x - initialX) / 16; newOffset += (x - initialX) / 16;
x = newOffset * 16; x = newOffset * 16;
@ -42,7 +42,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari
x = this->initialX; x = this->initialX;
} }
if (MapConnection::isHorizontal(this->connection->direction)) { if (MapConnection::isHorizontal(this->connection->direction())) {
y = round(newPos.y() / 16) * 16; y = round(newPos.y() / 16) * 16;
newOffset += (y - this->initialY) / 16; newOffset += (y - this->initialY) / 16;
y = newOffset * 16; y = newOffset * 16;
@ -51,7 +51,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari
y = this->initialY; y = this->initialY;
} }
if (this->connection->offset != newOffset) if (this->connection->offset() != newOffset)
emit connectionMoved(this->connection, newOffset); emit connectionMoved(this->connection, newOffset);
return QPointF(x, y); return QPointF(x, y);
} }

View file

@ -35,9 +35,9 @@ void ConnectionsListItem::updateUI() {
const QSignalBlocker blocker2(ui->comboBox_Map); const QSignalBlocker blocker2(ui->comboBox_Map);
const QSignalBlocker blocker3(ui->spinBox_Offset); const QSignalBlocker blocker3(ui->spinBox_Offset);
ui->comboBox_Direction->setTextItem(this->connection->direction); ui->comboBox_Direction->setTextItem(this->connection->direction());
ui->comboBox_Map->setTextItem(this->connection->map_name); ui->comboBox_Map->setTextItem(this->connection->targetMapName());
ui->spinBox_Offset->setValue(this->connection->offset); ui->spinBox_Offset->setValue(this->connection->offset());
} }
// TODO: Frame shifts slightly when style changes // TODO: Frame shifts slightly when style changes
@ -56,31 +56,27 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) {
} }
void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) { void ConnectionsListItem::mouseDoubleClickEvent(QMouseEvent *) {
emit doubleClicked(this->connection->map_name); emit doubleClicked(this->connection->targetMapName());
} }
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) if (this->connection->direction() != direction)
emit this->editedDirection(this->connection, 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->map_name != mapName) if (ui->comboBox_Map->findText(mapName) >= 0 && this->connection->targetMapName() != mapName)
emit this->editedMapName(this->connection, mapName); emit this->editedMapName(this->connection, 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) if (this->connection->offset() != offset)
emit editedOffset(this->connection, offset); emit editedOffset(this->connection, offset);
} }
void ConnectionsListItem::on_button_Delete_clicked() void ConnectionsListItem::on_button_Delete_clicked() {
{
emit this->removed(); emit this->removed();
} }

View file

@ -239,24 +239,26 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu
stitchedMaps.append(cur); stitchedMaps.append(cur);
for (MapConnection *connection : cur.map->connections) { for (MapConnection *connection : cur.map->connections) {
if (connection->direction == "dive" || connection->direction == "emerge") const QString direction = connection->direction();
continue;
int x = cur.x; int x = cur.x;
int y = cur.y; int y = cur.y;
int offset = connection->offset; int offset = connection->offset();
Map *connectionMap = this->editor->project->loadMap(connection->map_name); Map *connectionMap = this->editor->project->loadMap(connection->targetMapName());
if (connection->direction == "up") { if (direction == "up") {
x += offset; x += offset;
y -= connectionMap->getHeight(); y -= connectionMap->getHeight();
} else if (connection->direction == "down") { } else if (direction == "down") {
x += offset; x += offset;
y += cur.map->getHeight(); y += cur.map->getHeight();
} else if (connection->direction == "left") { } else if (direction == "left") {
x -= connectionMap->getWidth(); x -= connectionMap->getWidth();
y += offset; y += offset;
} else if (connection->direction == "right") { } else if (direction == "right") {
x += cur.map->getWidth(); x += cur.map->getWidth();
y += offset; y += offset;
} else {
// Ignore Dive/Emerge connections and unrecognized directions
continue;
} }
unvisited.append(StitchedMap{x, y, connectionMap}); unvisited.append(StitchedMap{x, y, connectionMap});
} }
@ -397,7 +399,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
// if showing connections, draw on outside of image // if showing connections, draw on outside of image
QPainter connectionPainter(&pixmap); QPainter connectionPainter(&pixmap);
for (auto connectionItem : editor->connection_items) { for (auto connectionItem : editor->connection_items) {
QString direction = connectionItem->connection->direction; const QString direction = connectionItem->connection->direction();
if ((showUpConnections && direction == "up") if ((showUpConnections && direction == "up")
|| (showDownConnections && direction == "down") || (showDownConnections && direction == "down")
|| (showLeftConnections && direction == "left") || (showLeftConnections && direction == "left")