Implement deferred L-shaped belt drag placement

This commit is contained in:
2026-07-21 21:05:31 +02:00
parent 1cbc695bc5
commit b2c1ea34fd
8 changed files with 444 additions and 31 deletions

View File

@@ -0,0 +1,94 @@
#include "BeltDragPath.h"
#include <cstddef>
namespace
{
int signOf(int value)
{
if (value > 0) { return 1; }
if (value < 0) { return -1; }
return 0;
}
// Direction stepping from one tile to an orthogonally adjacent tile.
Rotation directionBetween(QPoint from, QPoint to)
{
const QPoint delta = to - from;
if (delta.x() > 0) { return Rotation::East; }
if (delta.x() < 0) { return Rotation::West; }
if (delta.y() > 0) { return Rotation::South; }
return Rotation::North;
}
}
std::vector<BeltPathTile> computeBeltDragPath(QPoint anchor, QPoint cursor,
Rotation orientation)
{
const bool horizontalFirst =
(orientation == Rotation::East || orientation == Rotation::West);
// Build the ordered tile coordinates: first leg along the primary axis to the
// corner, then the orthogonal leg to the cursor (no duplicated corner tile).
std::vector<QPoint> coords;
if (horizontalFirst)
{
const int stepX = signOf(cursor.x() - anchor.x());
for (int x = anchor.x(); ; x += stepX)
{
coords.push_back(QPoint(x, anchor.y()));
if (x == cursor.x() || stepX == 0) { break; }
}
const int stepY = signOf(cursor.y() - anchor.y());
if (stepY != 0)
{
for (int y = anchor.y() + stepY; ; y += stepY)
{
coords.push_back(QPoint(cursor.x(), y));
if (y == cursor.y()) { break; }
}
}
}
else
{
const int stepY = signOf(cursor.y() - anchor.y());
for (int y = anchor.y(); ; y += stepY)
{
coords.push_back(QPoint(anchor.x(), y));
if (y == cursor.y() || stepY == 0) { break; }
}
const int stepX = signOf(cursor.x() - anchor.x());
if (stepX != 0)
{
for (int x = anchor.x() + stepX; ; x += stepX)
{
coords.push_back(QPoint(x, cursor.y()));
if (x == cursor.x()) { break; }
}
}
}
// Assign each tile the direction toward the next tile; the last tile keeps its
// incoming step direction, and a single-tile path keeps the belt orientation.
std::vector<BeltPathTile> path;
path.reserve(coords.size());
const std::size_t count = coords.size();
for (std::size_t index = 0; index < count; ++index)
{
Rotation rotation;
if (count == 1)
{
rotation = orientation;
}
else if (index + 1 < count)
{
rotation = directionBetween(coords[index], coords[index + 1]);
}
else
{
rotation = directionBetween(coords[index - 1], coords[index]);
}
path.push_back(BeltPathTile{ coords[index], rotation });
}
return path;
}