draw glyph for output port at the target tile during build mode

This commit is contained in:
2026-07-19 22:21:33 +02:00
parent f205136e21
commit 1cdafb7bcd
3 changed files with 50 additions and 19 deletions

View File

@@ -895,31 +895,39 @@ void GameWorldView::placeAtTile(QPoint tile)
// Port glyph helper
// ---------------------------------------------------------------------------
void GameWorldView::drawPortGlyph(QPainter& painter, QPoint bodyTile,
Rotation direction, const QColor& color)
void GameWorldView::drawPortGlyph(QPainter& painter, QPoint tile,
Rotation direction, const QColor& color,
bool centered)
{
const float px = getTilePx();
const QRectF tr = tileRect(bodyTile);
const QRectF tr = tileRect(tile);
const QPointF center(tr.x() + static_cast<qreal>(px) * 0.5,
tr.y() + static_cast<qreal>(px) * 0.5);
QPointF offset;
QPointF edgeOffset;
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;
case Rotation::East: edgeOffset = QPointF(px * 0.25f, 0); ch = ">"; break;
case Rotation::West: edgeOffset = QPointF(-px * 0.25f, 0); ch = "<"; break;
case Rotation::North: edgeOffset = QPointF(0, -px * 0.25f); ch = "^"; break;
case Rotation::South: edgeOffset = QPointF(0, px * 0.25f); ch = "v"; break;
default: return;
}
const qreal half = static_cast<qreal>(px) * 0.3;
// Centered glyphs sit in the middle of the tile (used for a port's target
// cell, REQ-UI-PORT-TARGET-GLYPH) and are drawn 150% larger to stand out;
// otherwise offset toward the exit edge of the port's body tile
// (REQ-UI-PORT-GLYPH).
const QPointF offset = centered ? QPointF(0.0, 0.0) : edgeOffset;
const qreal glyphScale = centered ? 1.5 : 1.0;
const qreal half = static_cast<qreal>(px) * 0.3 * glyphScale;
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)));
f.setPixelSize(std::max(6, static_cast<int>(px * 0.4f * glyphScale)));
painter.setFont(f);
painter.setPen(color);
painter.drawText(textRect, Qt::AlignCenter, QString::fromLatin1(ch));
@@ -991,7 +999,7 @@ void GameWorldView::drawBuildings(QPainter& painter)
for (const Port& port : b.outputPorts)
{
drawPortGlyph(painter, portBodyTile(port.tile, port.direction),
port.direction, bv.outline);
port.direction, bv.outline, /*centered*/ false);
}
// HP bar below the HQ footprint; the HQ's HP lives on its proxy entity.
@@ -1070,7 +1078,8 @@ void GameWorldView::drawBuildings(QPainter& painter)
{
const QPoint absBody = s.anchor
+ portBodyTile(port.tile, port.direction);
drawPortGlyph(painter, absBody, port.direction, bv.outline);
drawPortGlyph(painter, absBody, port.direction, bv.outline,
/*centered*/ false);
}
}
}
@@ -1571,7 +1580,8 @@ void GameWorldView::drawOverlays(QPainter& painter)
if (m_builderType.has_value())
{
drawBuildingGhost(painter, *m_builderType, m_ghostTile,
m_ghostRotation, m_ghostValid);
m_ghostRotation, m_ghostValid,
/*showPortTargetGlyphs*/ true);
}
// Blueprint placement ghost
@@ -1581,7 +1591,8 @@ void GameWorldView::drawOverlays(QPainter& painter)
{
const QPoint anchor = m_blueprintGhostTile + bb.offset;
const bool valid = isValidPlacement(bb.type, anchor, bb.rotation);
drawBuildingGhost(painter, bb.type, anchor, bb.rotation, valid);
drawBuildingGhost(painter, bb.type, anchor, bb.rotation, valid,
/*showPortTargetGlyphs*/ false);
}
}
@@ -1634,7 +1645,7 @@ void GameWorldView::drawOverlays(QPainter& painter)
void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
QPoint anchorTile, Rotation rotation,
bool valid)
bool valid, bool showPortTargetGlyphs)
{
const BuildingDef* def = findBuildingDef(type);
if (!def) { return; }
@@ -1688,7 +1699,24 @@ void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
for (const Port& port : parsed.outputPorts)
{
drawPortGlyph(painter, anchorTile + portBodyTile(port.tile, port.direction),
port.direction, lineColor);
port.direction, lineColor, /*centered*/ false);
}
// REQ-UI-PORT-TARGET-GLYPH: while in builder mode, additionally mark each
// output port's target cell (the cell just outside the footprint the port
// pushes into) with a directional glyph, previewing where output will flow.
// The Tunnel Entry is excluded — it receives items from any of its non-mouth
// edges rather than emitting into a single adjacent cell. The Shipyard is
// excluded too — it spawns a ship rather than emitting a belt item.
if (showPortTargetGlyphs
&& type != BuildingType::TunnelEntry
&& type != BuildingType::Shipyard)
{
for (const Port& port : parsed.outputPorts)
{
drawPortGlyph(painter, anchorTile + port.tile, port.direction,
lineColor, /*centered*/ true);
}
}
painter.setOpacity(1.0);