Reveal port items in a thin margin at machine edges
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <QPolygonF>
|
||||
#include <QRegion>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
|
||||
@@ -402,12 +403,12 @@ void GameWorldView::paintGL()
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
drawTiles(painter);
|
||||
// Port items are drawn before the buildings so the building body occludes the
|
||||
// portion still inside the footprint: items appear to slide out of the output
|
||||
// port (REQ-MAT-OUTPUT-EMERGE) and into the input port (REQ-MAT-INPUT-INTAKE)
|
||||
// rather than popping in or out of existence.
|
||||
drawPortItems(painter);
|
||||
drawBuildings(painter);
|
||||
// Port items are drawn over the buildings but clipped to a thin margin at each
|
||||
// machine's edges (see drawPortItems), so items appear to emerge from / sink
|
||||
// into the port and stay visible while crossing directly between two touching
|
||||
// buildings (REQ-MAT-OUTPUT-EMERGE, REQ-MAT-INPUT-INTAKE, REQ-MAT-DIRECT-COUPLE).
|
||||
drawPortItems(painter);
|
||||
drawCopyConfigFeedback(painter);
|
||||
drawStations(painter);
|
||||
drawBeltItems(painter);
|
||||
@@ -1162,9 +1163,39 @@ void GameWorldView::drawPortItems(QPainter& painter)
|
||||
{
|
||||
const float halfPx = tilePx() * 0.5f * 0.5f;
|
||||
|
||||
// Shared with belt items (REQ-GW-TILE-SIZE): a half-tile filled square with an
|
||||
// outline, occluded by the building drawn afterwards so the item slides out of
|
||||
// (REQ-MAT-OUTPUT-EMERGE) or into (REQ-MAT-INPUT-INTAKE) the port.
|
||||
// Port items are drawn over the buildings (drawBuildings runs first) but clipped
|
||||
// to a thin margin at each machine's edges: the clip region is the whole view
|
||||
// minus every machine's interior (its footprint inset by kPortMarginTiles). So a
|
||||
// transiting item shows only near the port edge — appearing to emerge from / sink
|
||||
// into the machine (REQ-MAT-OUTPUT-EMERGE, REQ-MAT-INPUT-INTAKE) and staying
|
||||
// visible in the ~2×margin band at a seam between two touching buildings
|
||||
// (REQ-MAT-DIRECT-COUPLE). Transport tiles are not machines and never occlude, so
|
||||
// items on belts stay fully visible.
|
||||
constexpr double kPortMarginTiles = 0.2;
|
||||
const double margin = kPortMarginTiles * static_cast<double>(tilePx());
|
||||
|
||||
QRegion clip(rect());
|
||||
for (const Building& b : m_sim->buildings().allBuildings())
|
||||
{
|
||||
if (b.type == BuildingType::Belt || b.type == BuildingType::Splitter
|
||||
|| b.type == BuildingType::TunnelEntry || b.type == BuildingType::TunnelExit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const std::set<QPoint, QPointCompare> cells(b.bodyCells.begin(), b.bodyCells.end());
|
||||
for (const QPoint& cell : b.bodyCells)
|
||||
{
|
||||
// Inset an edge only where the neighbouring cell is not part of the same
|
||||
// building, so interior cell seams stay filled (handles L-shaped footprints).
|
||||
const double l = cells.count(cell + QPoint(-1, 0)) ? 0.0 : margin;
|
||||
const double t = cells.count(cell + QPoint( 0, -1)) ? 0.0 : margin;
|
||||
const double r = cells.count(cell + QPoint( 1, 0)) ? 0.0 : margin;
|
||||
const double d = cells.count(cell + QPoint( 0, 1)) ? 0.0 : margin;
|
||||
clip = clip.subtracted(QRegion(tileRect(cell).adjusted(l, t, -r, -d).toRect()));
|
||||
}
|
||||
}
|
||||
|
||||
// Shared with belt items (REQ-GW-TILE-SIZE): a half-tile filled square + outline.
|
||||
const std::function<void(const ItemType&, QPointF)> drawItem =
|
||||
[&](const ItemType& type, QPointF worldPos)
|
||||
{
|
||||
@@ -1175,16 +1206,19 @@ void GameWorldView::drawPortItems(QPainter& painter)
|
||||
const QPointF center = worldToWidget(
|
||||
QVector2D(static_cast<float>(worldPos.x()),
|
||||
static_cast<float>(worldPos.y())));
|
||||
const QRectF rect(center.x() - halfPx, center.y() - halfPx,
|
||||
halfPx * 2, halfPx * 2);
|
||||
painter.fillRect(rect, it->second.fill);
|
||||
const QRectF itemRect(center.x() - halfPx, center.y() - halfPx,
|
||||
halfPx * 2, halfPx * 2);
|
||||
painter.fillRect(itemRect, it->second.fill);
|
||||
painter.setPen(QPen(it->second.outline, 1));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawRect(rect);
|
||||
painter.drawRect(itemRect);
|
||||
};
|
||||
|
||||
painter.save();
|
||||
painter.setClipRegion(clip);
|
||||
m_sim->buildings().forEachEmergingItem(drawItem);
|
||||
m_sim->buildings().forEachIncomingItem(drawItem);
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
void GameWorldView::drawBeltItems(QPainter& painter)
|
||||
|
||||
Reference in New Issue
Block a user