From 2991a9584f89c2c0b00e1563dddd27d428e78209 Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Mon, 20 Apr 2026 21:37:41 +0200 Subject: [PATCH] show ports --- src/lib/sim/BuildingSystem.cpp | 12 +++--- src/lib/sim/BuildingSystem.h | 8 +++- src/ui/GameWorldView.cpp | 79 ++++++++++++++++++++++++++++++++++ src/ui/GameWorldView.h | 3 ++ 4 files changed, 95 insertions(+), 7 deletions(-) diff --git a/src/lib/sim/BuildingSystem.cpp b/src/lib/sim/BuildingSystem.cpp index 336a668..ffcf55c 100644 --- a/src/lib/sim/BuildingSystem.cpp +++ b/src/lib/sim/BuildingSystem.cpp @@ -173,7 +173,7 @@ EntityId BuildingSystem::place(BuildingType type, QPoint anchor, { m_belts.placeBelt(anchor, rotation); m_tileOccupancy[{anchor.x(), anchor.y()}] = id; - m_beltEntities[id] = BeltEntry{anchor, BuildingType::Belt}; + m_beltEntities[id] = BeltEntry{anchor, BuildingType::Belt, rotation, rotation}; return id; } @@ -187,7 +187,7 @@ EntityId BuildingSystem::place(BuildingType type, QPoint anchor, const Rotation outB = mask.outputPorts[1].direction; m_belts.placeSplitter(anchor, outA, outB); m_tileOccupancy[{anchor.x(), anchor.y()}] = id; - m_beltEntities[id] = BeltEntry{anchor, BuildingType::Splitter}; + m_beltEntities[id] = BeltEntry{anchor, BuildingType::Splitter, outA, outB}; return id; } @@ -663,9 +663,11 @@ std::vector BuildingSystem::allBeltTiles() const for (const std::map::value_type& kv : m_beltEntities) { BeltTileInfo info; - info.id = kv.first; - info.tile = kv.second.tile; - info.type = kv.second.type; + info.id = kv.first; + info.tile = kv.second.tile; + info.type = kv.second.type; + info.directionA = kv.second.directionA; + info.directionB = kv.second.directionB; result.push_back(info); } return result; diff --git a/src/lib/sim/BuildingSystem.h b/src/lib/sim/BuildingSystem.h index 2c6f5bd..cde75e5 100644 --- a/src/lib/sim/BuildingSystem.h +++ b/src/lib/sim/BuildingSystem.h @@ -59,7 +59,9 @@ public: { EntityId id; QPoint tile; - BuildingType type; // Belt or Splitter + BuildingType type; // Belt or Splitter + Rotation directionA; // Belt: its direction; Splitter: first output + Rotation directionB; // Splitter: second output; Belt: same as directionA }; const Building* findBuilding(EntityId id) const; @@ -104,7 +106,9 @@ private: struct BeltEntry { QPoint tile; - BuildingType type; // Belt or Splitter + BuildingType type; // Belt or Splitter + Rotation directionA; // Belt: its direction; Splitter: first output + Rotation directionB; // Splitter: second output; Belt: same as directionA }; const BuildingDef* findBuildingDef(BuildingType type) const; diff --git a/src/ui/GameWorldView.cpp b/src/ui/GameWorldView.cpp index 427545e..c12038e 100644 --- a/src/ui/GameWorldView.cpp +++ b/src/ui/GameWorldView.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include #include @@ -84,6 +86,18 @@ QString toDisplayName(const std::string& id) return result; } +QPoint portBodyTile(QPoint portTile, Rotation direction) +{ + switch (direction) + { + case Rotation::East: return portTile + QPoint(-1, 0); + case Rotation::West: return portTile + QPoint( 1, 0); + case Rotation::North: return portTile + QPoint( 0, 1); + case Rotation::South: return portTile + QPoint( 0, -1); + } + return portTile; +} + } // namespace @@ -452,6 +466,40 @@ void GameWorldView::placeAtTile(QPoint tile) } } +// --------------------------------------------------------------------------- +// Port glyph helper +// --------------------------------------------------------------------------- + +void GameWorldView::drawPortGlyph(QPainter& painter, QPoint bodyTile, + Rotation direction, const QColor& color) +{ + const float px = tilePx(); + const QRectF tr = tileRect(bodyTile); + const QPointF center(tr.x() + static_cast(px) * 0.5, + tr.y() + static_cast(px) * 0.5); + + QPointF offset; + const char* ch; + switch (direction) + { + case Rotation::East: offset = QPointF(px * 0.25f, 0); ch = ">"; break; + case Rotation::West: offset = QPointF(-px * 0.25f, 0); ch = "<"; break; + case Rotation::North: offset = QPointF(0, -px * 0.25f); ch = "^"; break; + case Rotation::South: offset = QPointF(0, px * 0.25f); ch = "v"; break; + default: return; + } + + const qreal half = static_cast(px) * 0.3; + const QPointF pos = center + offset; + const QRectF textRect(pos.x() - half, pos.y() - half, half * 2.0, half * 2.0); + + QFont f = painter.font(); + f.setPixelSize(std::max(6, static_cast(px * 0.4f))); + painter.setFont(f); + painter.setPen(color); + painter.drawText(textRect, Qt::AlignCenter, QString::fromLatin1(ch)); +} + // --------------------------------------------------------------------------- // Rendering // --------------------------------------------------------------------------- @@ -505,6 +553,12 @@ void GameWorldView::drawBuildings(QPainter& painter) painter.drawText(bboxRect, Qt::AlignCenter, bv.glyph); } + for (const Port& port : b.outputPorts) + { + drawPortGlyph(painter, portBodyTile(port.tile, port.direction), + port.direction, bv.outline); + } + bool selected = false; for (EntityId selId : m_selectedIds) { @@ -531,6 +585,12 @@ void GameWorldView::drawBuildings(QPainter& painter) painter.setPen(QPen(bv.outline, 1)); painter.setBrush(Qt::NoBrush); painter.drawRect(tileRect(info.tile)); + + drawPortGlyph(painter, info.tile, info.directionA, bv.outline); + if (info.type == BuildingType::Splitter) + { + drawPortGlyph(painter, info.tile, info.directionB, bv.outline); + } } painter.setOpacity(0.5); @@ -553,6 +613,19 @@ void GameWorldView::drawBuildings(QPainter& painter) painter.setPen(QPen(bv.outline, 1, Qt::DashLine)); painter.setBrush(Qt::NoBrush); painter.drawRect(bboxRect); + + const BuildingDef* siteDef = findBuildingDef(s.type); + if (siteDef) + { + const ParsedSurfaceMask siteMask = + parseSurfaceMask(siteDef->surfaceMask, s.rotation); + for (const Port& port : siteMask.outputPorts) + { + const QPoint absBody = s.anchor + + portBodyTile(port.tile, port.direction); + drawPortGlyph(painter, absBody, port.direction, bv.outline); + } + } } painter.setOpacity(1.0); } @@ -655,6 +728,12 @@ void GameWorldView::drawOverlays(QPainter& painter) { painter.fillRect(tileRect(m_ghostTile + cell), ghostColor); } + for (const Port& port : parsed.outputPorts) + { + const QPoint absBody = m_ghostTile + + portBodyTile(port.tile, port.direction); + drawPortGlyph(painter, absBody, port.direction, Qt::white); + } } } diff --git a/src/ui/GameWorldView.h b/src/ui/GameWorldView.h index 41b2b33..46bb6e7 100644 --- a/src/ui/GameWorldView.h +++ b/src/ui/GameWorldView.h @@ -90,6 +90,9 @@ private: const BuildingDef* findBuildingDef(BuildingType type) const; EntityId buildingAtTile(QPoint tile) const; + void drawPortGlyph(QPainter& painter, QPoint bodyTile, + Rotation direction, const QColor& color); + std::optional entityPosition(EntityId id) const; void stepSpeed(int delta); void placeAtTile(QPoint tile);