Snap belt-drag end tile to a building's input edge
This commit is contained in:
@@ -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())
|
||||
{
|
||||
|
||||
@@ -279,6 +279,9 @@ private:
|
||||
// on release. Empty unless a belt drag is in progress.
|
||||
std::vector<BeltPathTile> m_beltDragPath;
|
||||
QPoint m_beltDragAnchor;
|
||||
// Last known cursor position in world (tile) units; used to pick the belt-drag
|
||||
// end tile closest to the cursor when snapping to a building (REQ-BLD-BELT-DRAG).
|
||||
QVector2D m_cursorWorldPos;
|
||||
bool m_dragging;
|
||||
|
||||
std::optional<Blueprint> m_blueprintMode;
|
||||
|
||||
Reference in New Issue
Block a user