Snap belt-drag end tile to a building's input edge

This commit is contained in:
2026-07-21 21:09:07 +02:00
parent 0c4eb480be
commit 4ca5b332cd
6 changed files with 210 additions and 5 deletions

View File

@@ -937,7 +937,61 @@ void GameWorldView::placeAtTile(QPoint tile)
void GameWorldView::recomputeBeltDragPath(QPoint cursorTile)
{
m_beltDragPath = computeBeltDragPath(m_beltDragAnchor, cursorTile, m_ghostRotation);
QPoint endTile = cursorTile;
std::optional<Rotation> forcedEndRotation;
// If the cursor is over a non-belt building or construction site, snap the end
// tile to the input-capable adjacent tile closest to the cursor, pointing into
// the target (REQ-BLD-BELT-DRAG).
std::optional<BuildingId> targetId = buildingAtTile(cursorTile);
std::optional<BuildingType> targetType;
if (targetId.has_value())
{
if (const Building* building = m_sim->getBuildings().findBuilding(*targetId))
{
targetType = building->type;
}
}
else if (std::optional<BuildingId> siteId = siteAtTile(cursorTile); siteId.has_value())
{
targetId = siteId;
if (const ConstructionSite* site = m_sim->getBuildings().findSite(*siteId))
{
targetType = site->type;
}
}
if (targetId.has_value() && targetType.has_value()
&& *targetType != BuildingType::Belt)
{
const std::vector<Port> inputPorts = m_sim->getBuildings().getInputPorts(*targetId);
std::optional<Port> best;
float bestDistanceSq = 0.0f;
for (const Port& port : inputPorts)
{
const QVector2D center(static_cast<float>(port.tile.x()) + 0.5f,
static_cast<float>(port.tile.y()) + 0.5f);
const float distanceSq = (center - m_cursorWorldPos).lengthSquared();
if (!best.has_value() || distanceSq < bestDistanceSq)
{
best = port;
bestDistanceSq = distanceSq;
}
}
if (best.has_value())
{
endTile = best->tile;
forcedEndRotation = best->direction;
}
}
m_beltDragPath = computeBeltDragPath(m_beltDragAnchor, endTile, m_ghostRotation);
if (forcedEndRotation.has_value() && !m_beltDragPath.empty())
{
// The end tile points into the target, overriding its incoming-step
// orientation (REQ-BLD-BELT-DRAG "Snapping to a building").
m_beltDragPath.back().rotation = *forcedEndRotation;
}
}
std::vector<GameWorldView::BeltDragResolved> GameWorldView::resolveBeltDragPath() const
@@ -2187,6 +2241,7 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
// is placed until release (REQ-BLD-BELT-DRAG).
m_dragging = true;
m_beltDragAnchor = tile;
m_cursorWorldPos = widgetToWorld(event->pos());
recomputeBeltDragPath(tile);
}
else
@@ -2350,6 +2405,7 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
void GameWorldView::mouseMoveEvent(QMouseEvent* event)
{
const QPoint tile = widgetToTile(event->pos());
m_cursorWorldPos = widgetToWorld(event->pos());
if (m_builderType.has_value())
{