dedupe tunnel lookup and key tunnel tiles by QPoint

This commit is contained in:
2026-08-03 21:02:06 +02:00
parent ca727bef35
commit 932b57720c
2 changed files with 29 additions and 25 deletions

View File

@@ -960,29 +960,39 @@ BuildingType GameWorldView::effectiveBuilderType() const
return inTunnelMode() ? m_tunnelGhostType : *m_builderType; return inTunnelMode() ? m_tunnelGhostType : *m_builderType;
} }
std::map<std::pair<int, int>, TunnelTileInfo> GameWorldView::collectTunnelTiles() const TunnelTileMap GameWorldView::collectTunnelTiles() const
{ {
// Index every tunnel entry/exit — built or still a construction site — by its // Index every tunnel entry/exit — built or still a construction site — by its
// single-cell tile, so a just-placed tunnel (not yet constructed) is matchable // single-cell tile, so a just-placed tunnel (not yet constructed) is matchable
// (REQ-BLD-TUNNEL-MODE, REQ-BLD-TUNNEL-SELECT-HIGHLIGHT). // (REQ-BLD-TUNNEL-MODE, REQ-BLD-TUNNEL-SELECT-HIGHLIGHT).
std::map<std::pair<int, int>, TunnelTileInfo> tunnels; TunnelTileMap tunnels;
for (const Building& b : m_sim->getBuildings().getAllBuildings()) for (const Building& b : m_sim->getBuildings().getAllBuildings())
{ {
if (b.type == BuildingType::TunnelEntry || b.type == BuildingType::TunnelExit) if (b.type == BuildingType::TunnelEntry || b.type == BuildingType::TunnelExit)
{ {
tunnels[{b.anchor.x(), b.anchor.y()}] = TunnelTileInfo{b.type, b.rotation}; tunnels[b.anchor] = TunnelTileInfo{b.type, b.rotation};
} }
} }
for (const ConstructionSite& s : m_sim->getBuildings().getAllSites()) for (const ConstructionSite& s : m_sim->getBuildings().getAllSites())
{ {
if (s.type == BuildingType::TunnelEntry || s.type == BuildingType::TunnelExit) if (s.type == BuildingType::TunnelEntry || s.type == BuildingType::TunnelExit)
{ {
tunnels[{s.anchor.x(), s.anchor.y()}] = TunnelTileInfo{s.type, s.rotation}; tunnels[s.anchor] = TunnelTileInfo{s.type, s.rotation};
} }
} }
return tunnels; return tunnels;
} }
TunnelLookup GameWorldView::makeTunnelLookup(const TunnelTileMap& tunnels)
{
return [&tunnels](QPoint tile) -> std::optional<TunnelTileInfo>
{
const TunnelTileMap::const_iterator it = tunnels.find(tile);
if (it == tunnels.end()) { return std::nullopt; }
return it->second;
};
}
void GameWorldView::updateTunnelGhost() void GameWorldView::updateTunnelGhost()
{ {
m_tunnelGhostType = BuildingType::TunnelEntry; m_tunnelGhostType = BuildingType::TunnelEntry;
@@ -995,14 +1005,8 @@ void GameWorldView::updateTunnelGhost()
return; return;
} }
const std::map<std::pair<int, int>, TunnelTileInfo> tunnels = collectTunnelTiles(); const TunnelTileMap tunnels = collectTunnelTiles();
const TunnelLookup lookup = [&tunnels](QPoint tile) -> std::optional<TunnelTileInfo> const TunnelLookup lookup = makeTunnelLookup(tunnels);
{
const std::map<std::pair<int, int>, TunnelTileInfo>::const_iterator it =
tunnels.find({tile.x(), tile.y()});
if (it == tunnels.end()) { return std::nullopt; }
return it->second;
};
const TunnelCompletion completion = const TunnelCompletion completion =
resolveTunnelCompletion(lookup, m_ghostTile, m_ghostRotation, resolveTunnelCompletion(lookup, m_ghostTile, m_ghostRotation,
@@ -1979,21 +1983,15 @@ void GameWorldView::drawSelectedTunnelConnections(QPainter& painter)
{ {
if (m_selectedBuildingIds.empty()) { return; } if (m_selectedBuildingIds.empty()) { return; }
const std::map<std::pair<int, int>, TunnelTileInfo> tunnels = collectTunnelTiles(); const TunnelTileMap tunnels = collectTunnelTiles();
if (tunnels.empty()) { return; } if (tunnels.empty()) { return; }
const TunnelLookup lookup = [&tunnels](QPoint tile) -> std::optional<TunnelTileInfo> const TunnelLookup lookup = makeTunnelLookup(tunnels);
{
const std::map<std::pair<int, int>, TunnelTileInfo>::const_iterator it =
tunnels.find({tile.x(), tile.y()});
if (it == tunnels.end()) { return std::nullopt; }
return it->second;
};
// Collect the tiles to highlight in a set so a connection selected from both ends // Collect the tiles to highlight in a set so a connection selected from both ends
// (or overlapping runs) is filled exactly once — filling a semi-transparent green // (or overlapping runs) is filled exactly once — filling a semi-transparent green
// twice would darken it (REQ-BLD-TUNNEL-SELECT-HIGHLIGHT). // twice would darken it (REQ-BLD-TUNNEL-SELECT-HIGHLIGHT).
std::set<std::pair<int, int>> highlightTiles; std::set<QPoint, QPointCompare> highlightTiles;
for (const BuildingId id : m_selectedBuildingIds) for (const BuildingId id : m_selectedBuildingIds)
{ {
std::optional<QPoint> anchor; std::optional<QPoint> anchor;
@@ -2023,15 +2021,15 @@ void GameWorldView::drawSelectedTunnelConnections(QPainter& painter)
(delta.y() > 0) - (delta.y() < 0)); (delta.y() > 0) - (delta.y() < 0));
for (QPoint t = *anchor; ; t += stepDir) for (QPoint t = *anchor; ; t += stepDir)
{ {
highlightTiles.insert({t.x(), t.y()}); highlightTiles.insert(t);
if (t == *partner) { break; } if (t == *partner) { break; }
} }
} }
const QColor green = m_visuals->overlays.tunnelPreview; const QColor green = m_visuals->overlays.tunnelPreview;
for (const std::pair<int, int>& tile : highlightTiles) for (const QPoint& tile : highlightTiles)
{ {
painter.fillRect(tileRect(QPoint(tile.first, tile.second)), green); painter.fillRect(tileRect(tile), green);
} }
} }

View File

@@ -67,6 +67,9 @@ struct QPointCompare
} }
}; };
// Tunnel entries/exits indexed by their single-cell tile (REQ-BLD-TUNNEL-MODE).
using TunnelTileMap = std::map<QPoint, TunnelTileInfo, QPointCompare>;
class GameWorldView : public QOpenGLWidget, class GameWorldView : public QOpenGLWidget,
public CombinedEventHandler<BeamFiredEvent, public CombinedEventHandler<BeamFiredEvent,
BuildingTypeSelectedEvent, BuildingTypeSelectedEvent,
@@ -242,7 +245,10 @@ private:
void updateTunnelGhost(); void updateTunnelGhost();
// Indexes every tunnel entry/exit — built or still a construction site — by its // Indexes every tunnel entry/exit — built or still a construction site — by its
// single-cell tile. Shared by the placement preview and the selection highlight. // single-cell tile. Shared by the placement preview and the selection highlight.
std::map<std::pair<int, int>, TunnelTileInfo> collectTunnelTiles() const; TunnelTileMap collectTunnelTiles() const;
// Wraps a tunnel tile index in the lookup functor the TunnelCompletion helpers
// take. The returned functor references `tunnels`, which must outlive it.
static TunnelLookup makeTunnelLookup(const TunnelTileMap& tunnels);
// Draws the green connection highlight for every selected tunnel end that has a // Draws the green connection highlight for every selected tunnel end that has a
// matching end (REQ-BLD-TUNNEL-SELECT-HIGHLIGHT). // matching end (REQ-BLD-TUNNEL-SELECT-HIGHLIGHT).
void drawSelectedTunnelConnections(QPainter& painter); void drawSelectedTunnelConnections(QPainter& painter);