show ports

This commit is contained in:
2026-04-20 21:37:41 +02:00
parent 50d505c886
commit 2991a9584f
4 changed files with 95 additions and 7 deletions

View File

@@ -173,7 +173,7 @@ EntityId BuildingSystem::place(BuildingType type, QPoint anchor,
{ {
m_belts.placeBelt(anchor, rotation); m_belts.placeBelt(anchor, rotation);
m_tileOccupancy[{anchor.x(), anchor.y()}] = id; 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; return id;
} }
@@ -187,7 +187,7 @@ EntityId BuildingSystem::place(BuildingType type, QPoint anchor,
const Rotation outB = mask.outputPorts[1].direction; const Rotation outB = mask.outputPorts[1].direction;
m_belts.placeSplitter(anchor, outA, outB); m_belts.placeSplitter(anchor, outA, outB);
m_tileOccupancy[{anchor.x(), anchor.y()}] = id; 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; return id;
} }
@@ -663,9 +663,11 @@ std::vector<BuildingSystem::BeltTileInfo> BuildingSystem::allBeltTiles() const
for (const std::map<EntityId, BeltEntry>::value_type& kv : m_beltEntities) for (const std::map<EntityId, BeltEntry>::value_type& kv : m_beltEntities)
{ {
BeltTileInfo info; BeltTileInfo info;
info.id = kv.first; info.id = kv.first;
info.tile = kv.second.tile; info.tile = kv.second.tile;
info.type = kv.second.type; info.type = kv.second.type;
info.directionA = kv.second.directionA;
info.directionB = kv.second.directionB;
result.push_back(info); result.push_back(info);
} }
return result; return result;

View File

@@ -59,7 +59,9 @@ public:
{ {
EntityId id; EntityId id;
QPoint tile; 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; const Building* findBuilding(EntityId id) const;
@@ -104,7 +106,9 @@ private:
struct BeltEntry struct BeltEntry
{ {
QPoint tile; 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; const BuildingDef* findBuildingDef(BuildingType type) const;

View File

@@ -6,6 +6,8 @@
#include <map> #include <map>
#include <string> #include <string>
#include <QColor>
#include <QFont>
#include <QKeyEvent> #include <QKeyEvent>
#include <QMessageBox> #include <QMessageBox>
#include <QMouseEvent> #include <QMouseEvent>
@@ -84,6 +86,18 @@ QString toDisplayName(const std::string& id)
return result; 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 } // 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<qreal>(px) * 0.5,
tr.y() + static_cast<qreal>(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<qreal>(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<int>(px * 0.4f)));
painter.setFont(f);
painter.setPen(color);
painter.drawText(textRect, Qt::AlignCenter, QString::fromLatin1(ch));
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Rendering // Rendering
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -505,6 +553,12 @@ void GameWorldView::drawBuildings(QPainter& painter)
painter.drawText(bboxRect, Qt::AlignCenter, bv.glyph); 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; bool selected = false;
for (EntityId selId : m_selectedIds) for (EntityId selId : m_selectedIds)
{ {
@@ -531,6 +585,12 @@ void GameWorldView::drawBuildings(QPainter& painter)
painter.setPen(QPen(bv.outline, 1)); painter.setPen(QPen(bv.outline, 1));
painter.setBrush(Qt::NoBrush); painter.setBrush(Qt::NoBrush);
painter.drawRect(tileRect(info.tile)); 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); painter.setOpacity(0.5);
@@ -553,6 +613,19 @@ void GameWorldView::drawBuildings(QPainter& painter)
painter.setPen(QPen(bv.outline, 1, Qt::DashLine)); painter.setPen(QPen(bv.outline, 1, Qt::DashLine));
painter.setBrush(Qt::NoBrush); painter.setBrush(Qt::NoBrush);
painter.drawRect(bboxRect); 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); painter.setOpacity(1.0);
} }
@@ -655,6 +728,12 @@ void GameWorldView::drawOverlays(QPainter& painter)
{ {
painter.fillRect(tileRect(m_ghostTile + cell), ghostColor); 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);
}
} }
} }

View File

@@ -90,6 +90,9 @@ private:
const BuildingDef* findBuildingDef(BuildingType type) const; const BuildingDef* findBuildingDef(BuildingType type) const;
EntityId buildingAtTile(QPoint tile) const; EntityId buildingAtTile(QPoint tile) const;
void drawPortGlyph(QPainter& painter, QPoint bodyTile,
Rotation direction, const QColor& color);
std::optional<QVector2D> entityPosition(EntityId id) const; std::optional<QVector2D> entityPosition(EntityId id) const;
void stepSpeed(int delta); void stepSpeed(int delta);
void placeAtTile(QPoint tile); void placeAtTile(QPoint tile);