extract the world<->widget transform into WorldCoordinates
This commit is contained in:
@@ -379,7 +379,8 @@ void GameWorldView::onFrame()
|
||||
// so refresh the box-select rectangle even though no mouse move fires.
|
||||
if (m_boxSelecting && m_scrollXTiles != scrollBefore)
|
||||
{
|
||||
m_boxCurrentTile = widgetToTile(mapFromGlobal(QCursor::pos()));
|
||||
m_boxCurrentTile =
|
||||
getCoordinates().widgetToTile(mapFromGlobal(QCursor::pos()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,26 +489,30 @@ void GameWorldView::paintGL()
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
drawTiles(painter);
|
||||
drawBuildings(painter);
|
||||
// One transform snapshot for the whole frame; every world-space draw below
|
||||
// reads the viewport through it.
|
||||
const WorldCoordinates coordinates = getCoordinates();
|
||||
|
||||
drawTiles(painter, coordinates);
|
||||
drawBuildings(painter, coordinates);
|
||||
// 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);
|
||||
drawDebris(painter);
|
||||
drawPortItems(painter, coordinates);
|
||||
drawCopyConfigFeedback(painter, coordinates);
|
||||
drawStations(painter, coordinates);
|
||||
drawBeltItems(painter, coordinates);
|
||||
drawDebris(painter, coordinates);
|
||||
if (m_debugDraw)
|
||||
{
|
||||
drawDebugSensorRanges(painter);
|
||||
drawDebugTargetLines(painter);
|
||||
drawDebugSensorRanges(painter, coordinates);
|
||||
drawDebugTargetLines(painter, coordinates);
|
||||
drawDebugOverlay(painter);
|
||||
}
|
||||
drawShips(painter);
|
||||
drawBeams(painter);
|
||||
drawOverlays(painter);
|
||||
drawShips(painter, coordinates);
|
||||
drawBeams(painter, coordinates);
|
||||
drawOverlays(painter, coordinates);
|
||||
drawScreenSpace(painter);
|
||||
drawPauseBorder(painter);
|
||||
drawDeconstructBorder(painter);
|
||||
@@ -518,63 +523,9 @@ void GameWorldView::paintGL()
|
||||
// Coordinate helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
float GameWorldView::getTilePx() const
|
||||
WorldCoordinates GameWorldView::getCoordinates() const
|
||||
{
|
||||
if (m_config->world.heightTiles <= 0) { return 1.0f; }
|
||||
return static_cast<float>(height()) / static_cast<float>(m_config->world.heightTiles);
|
||||
}
|
||||
|
||||
float GameWorldView::getViewportWidthTiles() const
|
||||
{
|
||||
return static_cast<float>(width()) / getTilePx();
|
||||
}
|
||||
|
||||
float GameWorldView::getViewLeftTiles() const
|
||||
{
|
||||
return m_scrollXTiles - getViewportWidthTiles() / 2.0f;
|
||||
}
|
||||
|
||||
QPointF GameWorldView::worldToWidget(QVector2D worldPos) const
|
||||
{
|
||||
return QPointF(
|
||||
static_cast<qreal>((worldPos.x() - getViewLeftTiles()) * getTilePx()),
|
||||
static_cast<qreal>(worldPos.y() * getTilePx()));
|
||||
}
|
||||
|
||||
QPointF GameWorldView::tileToWidget(QPoint tile) const
|
||||
{
|
||||
return worldToWidget(QVector2D(static_cast<float>(tile.x()),
|
||||
static_cast<float>(tile.y())));
|
||||
}
|
||||
|
||||
QPoint GameWorldView::widgetToTile(QPoint widgetPt) const
|
||||
{
|
||||
const float wx = static_cast<float>(widgetPt.x()) / getTilePx() + getViewLeftTiles();
|
||||
const float wy = static_cast<float>(widgetPt.y()) / getTilePx();
|
||||
return QPoint(static_cast<int>(std::floor(wx)), static_cast<int>(std::floor(wy)));
|
||||
}
|
||||
|
||||
QVector2D GameWorldView::widgetToWorld(QPoint widgetPt) const
|
||||
{
|
||||
const float wx = static_cast<float>(widgetPt.x()) / getTilePx() + getViewLeftTiles();
|
||||
const float wy = static_cast<float>(widgetPt.y()) / getTilePx();
|
||||
return QVector2D(wx, wy);
|
||||
}
|
||||
|
||||
QRectF GameWorldView::tileRect(QPoint tile) const
|
||||
{
|
||||
const QPointF tl = tileToWidget(tile);
|
||||
return QRectF(tl.x(), tl.y(),
|
||||
static_cast<qreal>(getTilePx()), static_cast<qreal>(getTilePx()));
|
||||
}
|
||||
|
||||
QRect GameWorldView::getViewportRect() const
|
||||
{
|
||||
const int left = static_cast<int>(std::floor(getViewLeftTiles())) - 1;
|
||||
const int top = 0;
|
||||
const int right = static_cast<int>(std::ceil(getViewLeftTiles() + getViewportWidthTiles())) + 1;
|
||||
const int bottom = m_config->world.heightTiles;
|
||||
return QRect(left, top, right - left, bottom - top);
|
||||
return WorldCoordinates(size(), m_config->world.heightTiles, m_scrollXTiles);
|
||||
}
|
||||
|
||||
float GameWorldView::getAsteroidLeftEdge() const
|
||||
@@ -1178,12 +1129,13 @@ void GameWorldView::applyBeltDragPath()
|
||||
// Port glyph helper
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void GameWorldView::drawPortGlyph(QPainter& painter, QPoint tile,
|
||||
Rotation direction, const QColor& color,
|
||||
bool centered)
|
||||
void GameWorldView::drawPortGlyph(QPainter& painter,
|
||||
const WorldCoordinates& coordinates, QPoint tile,
|
||||
Rotation direction, const QColor& color,
|
||||
bool centered)
|
||||
{
|
||||
const float px = getTilePx();
|
||||
const QRectF tr = tileRect(tile);
|
||||
const float px = coordinates.getTilePx();
|
||||
const QRectF tr = coordinates.tileRect(tile);
|
||||
const QPointF center(tr.x() + static_cast<qreal>(px) * 0.5,
|
||||
tr.y() + static_cast<qreal>(px) * 0.5);
|
||||
|
||||
@@ -1220,10 +1172,11 @@ void GameWorldView::drawPortGlyph(QPainter& painter, QPoint tile,
|
||||
// Rendering
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void GameWorldView::drawTiles(QPainter& painter)
|
||||
void GameWorldView::drawTiles(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
const int leftTile = static_cast<int>(std::floor(getViewLeftTiles())) - 1;
|
||||
const int rightTile = leftTile + static_cast<int>(std::ceil(getViewportWidthTiles())) + 2;
|
||||
const int leftTile = static_cast<int>(std::floor(coordinates.getViewLeftTiles())) - 1;
|
||||
const int rightTile = leftTile
|
||||
+ static_cast<int>(std::ceil(coordinates.getViewportWidthTiles())) + 2;
|
||||
const int bottomTile = m_config->world.heightTiles;
|
||||
|
||||
// Asteroid columns left of the buildable edge are not yet unlocked by
|
||||
@@ -1239,7 +1192,7 @@ void GameWorldView::drawTiles(QPainter& painter)
|
||||
const bool locked = (x < buildableLeftX);
|
||||
for (int y = 0; y < bottomTile; ++y)
|
||||
{
|
||||
const QRectF rect = tileRect(QPoint(x, y));
|
||||
const QRectF rect = coordinates.tileRect(QPoint(x, y));
|
||||
painter.fillRect(rect, fill);
|
||||
if (locked)
|
||||
{
|
||||
@@ -1273,7 +1226,9 @@ void GameWorldView::loadBuildingIcons(const std::string& configDir)
|
||||
}
|
||||
}
|
||||
|
||||
bool GameWorldView::drawBuildingIcon(QPainter& painter, BuildingType type,
|
||||
bool GameWorldView::drawBuildingIcon(QPainter& painter,
|
||||
const WorldCoordinates& coordinates,
|
||||
BuildingType type,
|
||||
const QRectF& box, const QColor& fill) const
|
||||
{
|
||||
const std::map<BuildingType, BuildingIconRenderers>::const_iterator it =
|
||||
@@ -1282,7 +1237,7 @@ bool GameWorldView::drawBuildingIcon(QPainter& painter, BuildingType type,
|
||||
|
||||
// Every icon is the same fixed on-screen size, centered on the footprint,
|
||||
// regardless of footprint size (REQ-UI-WORLD-ICON).
|
||||
const qreal side = static_cast<qreal>(getTilePx()) * kWorldIconTileFactor;
|
||||
const qreal side = static_cast<qreal>(coordinates.getTilePx()) * kWorldIconTileFactor;
|
||||
const QRectF target(box.center().x() - side / 2.0,
|
||||
box.center().y() - side / 2.0, side, side);
|
||||
QSvgRenderer* renderer = isLightFill(fill) ? it->second.dark.get()
|
||||
@@ -1297,7 +1252,7 @@ bool GameWorldView::drawBuildingIcon(QPainter& painter, BuildingType type,
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameWorldView::drawBuildings(QPainter& painter)
|
||||
void GameWorldView::drawBuildings(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
for (const Building& b : getAllBuildings(m_sim->getFactoryState()))
|
||||
{
|
||||
@@ -1309,13 +1264,13 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
painter.setPen(Qt::NoPen);
|
||||
for (const QPoint& cell : b.bodyCells)
|
||||
{
|
||||
painter.fillRect(tileRect(cell), bv.fill);
|
||||
painter.fillRect(coordinates.tileRect(cell), bv.fill);
|
||||
}
|
||||
|
||||
const QPointF tl = tileToWidget(b.anchor);
|
||||
const QPointF tl = coordinates.tileToWidget(b.anchor);
|
||||
const QRectF bboxRect(tl.x(), tl.y(),
|
||||
b.footprint.width() * static_cast<qreal>(getTilePx()),
|
||||
b.footprint.height() * static_cast<qreal>(getTilePx()));
|
||||
b.footprint.width() * static_cast<qreal>(coordinates.getTilePx()),
|
||||
b.footprint.height() * static_cast<qreal>(coordinates.getTilePx()));
|
||||
|
||||
painter.setPen(QPen(bv.outline, 1));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
@@ -1323,7 +1278,8 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
|
||||
// Icon glyph over the fill (REQ-UI-WORLD-ICON); falls back to the text
|
||||
// glyph for building types without a world icon (e.g. tunnels).
|
||||
if (!drawBuildingIcon(painter, b.type, bboxRect, bv.fill) && !bv.glyph.isEmpty())
|
||||
if (!drawBuildingIcon(painter, coordinates, b.type, bboxRect, bv.fill)
|
||||
&& !bv.glyph.isEmpty())
|
||||
{
|
||||
painter.setPen(bv.outline);
|
||||
painter.drawText(bboxRect, Qt::AlignCenter, bv.glyph);
|
||||
@@ -1331,7 +1287,8 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
|
||||
for (const Port& port : b.outputPorts)
|
||||
{
|
||||
drawPortGlyph(painter, outputBodyTile(port.tile, port.direction),
|
||||
drawPortGlyph(painter, coordinates,
|
||||
outputBodyTile(port.tile, port.direction),
|
||||
port.direction, bv.outline, /*centered*/ false);
|
||||
}
|
||||
|
||||
@@ -1343,7 +1300,7 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
if (const std::optional<ProductionStatus> status =
|
||||
getProductionStatus(m_sim->getConfig(), b))
|
||||
{
|
||||
const float px = getTilePx();
|
||||
const float px = coordinates.getTilePx();
|
||||
const float r = px * 0.18f;
|
||||
const float inset = r + px * 0.12f;
|
||||
// Default orientation (East) puts the light at the top-right corner;
|
||||
@@ -1375,13 +1332,13 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
|
||||
for (const QPoint& cell : s.bodyCells)
|
||||
{
|
||||
painter.fillRect(tileRect(cell), bv.fill);
|
||||
painter.fillRect(coordinates.tileRect(cell), bv.fill);
|
||||
}
|
||||
|
||||
const QPointF tl = tileToWidget(s.anchor);
|
||||
const QPointF tl = coordinates.tileToWidget(s.anchor);
|
||||
const QRectF bboxRect(tl.x(), tl.y(),
|
||||
s.footprint.width() * static_cast<qreal>(getTilePx()),
|
||||
s.footprint.height() * static_cast<qreal>(getTilePx()));
|
||||
s.footprint.width() * static_cast<qreal>(coordinates.getTilePx()),
|
||||
s.footprint.height() * static_cast<qreal>(coordinates.getTilePx()));
|
||||
painter.setPen(QPen(bv.outline, 1, Qt::DashLine));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawRect(bboxRect);
|
||||
@@ -1406,7 +1363,7 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
// Identity symbol with the progress percentage below it
|
||||
// (REQ-UI-CONSTRUCTION-PROGRESS): the world icon centered on the
|
||||
// footprint where the type has one, otherwise the text glyph.
|
||||
if (drawBuildingIcon(painter, s.type, bboxRect, bv.fill))
|
||||
if (drawBuildingIcon(painter, coordinates, s.type, bboxRect, bv.fill))
|
||||
{
|
||||
painter.drawText(bboxRect, Qt::AlignHCenter | Qt::AlignBottom, pctText);
|
||||
}
|
||||
@@ -1432,8 +1389,8 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
{
|
||||
const QPoint absBody = s.anchor
|
||||
+ outputBodyTile(port.tile, port.direction);
|
||||
drawPortGlyph(painter, absBody, port.direction, bv.outline,
|
||||
/*centered*/ false);
|
||||
drawPortGlyph(painter, coordinates, absBody, port.direction,
|
||||
bv.outline, /*centered*/ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1446,17 +1403,18 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
for (const Building& b : getAllBuildings(m_sim->getFactoryState()))
|
||||
{
|
||||
if (b.type != BuildingType::Hq) { continue; }
|
||||
const QPointF tl = tileToWidget(b.anchor);
|
||||
const QPointF tl = coordinates.tileToWidget(b.anchor);
|
||||
const QRectF bboxRect(tl.x(), tl.y(),
|
||||
b.footprint.width() * static_cast<qreal>(getTilePx()),
|
||||
b.footprint.height() * static_cast<qreal>(getTilePx()));
|
||||
b.footprint.width() * static_cast<qreal>(coordinates.getTilePx()),
|
||||
b.footprint.height() * static_cast<qreal>(coordinates.getTilePx()));
|
||||
m_sim->getAdmin().forEach<HqProxyComponent, FactionComponent, HealthComponent>(
|
||||
[&](entt::entity /*e*/, const HqProxyComponent& /*hq*/,
|
||||
const FactionComponent& f, const HealthComponent& h)
|
||||
{
|
||||
if (h.maxHp > 0.0f)
|
||||
{
|
||||
drawHpBar(painter, bboxRect.left(), bboxRect.bottom() + 1.0,
|
||||
drawHpBar(painter, coordinates,
|
||||
bboxRect.left(), bboxRect.bottom() + 1.0,
|
||||
bboxRect.width(), h.hp / h.maxHp, f.isEnemy);
|
||||
}
|
||||
});
|
||||
@@ -1466,10 +1424,11 @@ void GameWorldView::drawBuildings(QPainter& painter)
|
||||
// site fill, so a selected building surrounded by neighbours keeps its outline:
|
||||
// the highlight sits 1px outside the footprint (into adjacent tiles), and drawing
|
||||
// it inline would let later-drawn neighbours overpaint it with their body fill.
|
||||
drawSelectionHighlights(painter);
|
||||
drawSelectionHighlights(painter, coordinates);
|
||||
}
|
||||
|
||||
std::optional<QRectF> GameWorldView::footprintWidgetRect(BuildingId id) const
|
||||
std::optional<QRectF> GameWorldView::footprintWidgetRect(
|
||||
const WorldCoordinates& coordinates, BuildingId id) const
|
||||
{
|
||||
std::optional<QPoint> anchor;
|
||||
std::optional<QSize> footprint;
|
||||
@@ -1486,20 +1445,21 @@ std::optional<QRectF> GameWorldView::footprintWidgetRect(BuildingId id) const
|
||||
}
|
||||
if (!anchor.has_value() || !footprint.has_value()) { return std::nullopt; }
|
||||
|
||||
const QPointF tl = tileToWidget(*anchor);
|
||||
const QPointF tl = coordinates.tileToWidget(*anchor);
|
||||
return QRectF(tl.x(), tl.y(),
|
||||
footprint->width() * static_cast<qreal>(getTilePx()),
|
||||
footprint->height() * static_cast<qreal>(getTilePx()));
|
||||
footprint->width() * static_cast<qreal>(coordinates.getTilePx()),
|
||||
footprint->height() * static_cast<qreal>(coordinates.getTilePx()));
|
||||
}
|
||||
|
||||
void GameWorldView::drawSelectionHighlights(QPainter& painter)
|
||||
void GameWorldView::drawSelectionHighlights(QPainter& painter,
|
||||
const WorldCoordinates& coordinates)
|
||||
{
|
||||
painter.setPen(QPen(m_visuals->overlays.selectedOutline, 2));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
|
||||
for (BuildingId selId : m_selectedBuildingIds)
|
||||
{
|
||||
const std::optional<QRectF> rect = footprintWidgetRect(selId);
|
||||
const std::optional<QRectF> rect = footprintWidgetRect(coordinates, selId);
|
||||
if (!rect.has_value()) { continue; }
|
||||
// Outline sits 1px outside the footprint (into adjacent tiles).
|
||||
painter.drawRect(rect->adjusted(-1, -1, 1, 1));
|
||||
@@ -1509,17 +1469,20 @@ void GameWorldView::drawSelectionHighlights(QPainter& painter)
|
||||
// rendered circle (radius getTilePx()*0.2, matching drawDebris) (REQ-UI-DEBRIS-CLICK-SELECT).
|
||||
if (!m_selectedDebris.empty())
|
||||
{
|
||||
const qreal outlineRadius = static_cast<qreal>(getTilePx() * 0.2f) + 3.0;
|
||||
const qreal outlineRadius =
|
||||
static_cast<qreal>(coordinates.getTilePx() * 0.2f) + 3.0;
|
||||
for (const DebrisInfo& debris : getAllDebrisInfo(m_sim->getAdmin()))
|
||||
{
|
||||
if (std::find(m_selectedDebris.begin(), m_selectedDebris.end(), debris.entity)
|
||||
== m_selectedDebris.end()) { continue; }
|
||||
painter.drawEllipse(worldToWidget(debris.position), outlineRadius, outlineRadius);
|
||||
painter.drawEllipse(coordinates.worldToWidget(debris.position),
|
||||
outlineRadius, outlineRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorldView::drawCopyConfigFeedback(QPainter& painter)
|
||||
void GameWorldView::drawCopyConfigFeedback(QPainter& painter,
|
||||
const WorldCoordinates& coordinates)
|
||||
{
|
||||
const QColor color = m_visuals->overlays.copyConfig;
|
||||
|
||||
@@ -1534,13 +1497,13 @@ void GameWorldView::drawCopyConfigFeedback(QPainter& painter)
|
||||
for (const Building& b : getAllBuildings(m_sim->getFactoryState()))
|
||||
{
|
||||
if (b.type != type) { continue; }
|
||||
const std::optional<QRectF> rect = footprintWidgetRect(b.id);
|
||||
const std::optional<QRectF> rect = footprintWidgetRect(coordinates, b.id);
|
||||
if (rect.has_value()) { painter.drawRect(*rect); }
|
||||
}
|
||||
for (const ConstructionSite& s : getAllSites(m_sim->getFactoryState()))
|
||||
{
|
||||
if (s.type != type) { continue; }
|
||||
const std::optional<QRectF> rect = footprintWidgetRect(s.id);
|
||||
const std::optional<QRectF> rect = footprintWidgetRect(coordinates, s.id);
|
||||
if (rect.has_value()) { painter.drawRect(*rect); }
|
||||
}
|
||||
}
|
||||
@@ -1551,14 +1514,14 @@ void GameWorldView::drawCopyConfigFeedback(QPainter& painter)
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
for (const CopyConfigFlash& flash : m_copyConfigFlashes)
|
||||
{
|
||||
const std::optional<QRectF> rect = footprintWidgetRect(flash.id);
|
||||
const std::optional<QRectF> rect = footprintWidgetRect(coordinates, flash.id);
|
||||
if (rect.has_value()) { painter.drawRect(rect->adjusted(-1, -1, 1, 1)); }
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorldView::drawPortItems(QPainter& painter)
|
||||
void GameWorldView::drawPortItems(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
const float halfPx = getTilePx() * 0.5f * 0.5f;
|
||||
const float halfPx = coordinates.getTilePx() * 0.5f * 0.5f;
|
||||
|
||||
// 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
|
||||
@@ -1569,7 +1532,7 @@ void GameWorldView::drawPortItems(QPainter& painter)
|
||||
// (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>(getTilePx());
|
||||
const double margin = kPortMarginTiles * static_cast<double>(coordinates.getTilePx());
|
||||
|
||||
QRegion clip(rect());
|
||||
for (const Building& b : getAllBuildings(m_sim->getFactoryState()))
|
||||
@@ -1588,7 +1551,8 @@ void GameWorldView::drawPortItems(QPainter& painter)
|
||||
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()));
|
||||
clip = clip.subtracted(
|
||||
QRegion(coordinates.tileRect(cell).adjusted(l, t, -r, -d).toRect()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1597,7 +1561,7 @@ void GameWorldView::drawPortItems(QPainter& painter)
|
||||
const std::function<void(const ItemType&, QPointF)> drawItem =
|
||||
[&](const ItemType& type, QPointF worldPos)
|
||||
{
|
||||
const QPointF center = worldToWidget(
|
||||
const QPointF center = coordinates.worldToWidget(
|
||||
QVector2D(static_cast<float>(worldPos.x()),
|
||||
static_cast<float>(worldPos.y())));
|
||||
drawWorldItem(painter, type.id, center, halfPx);
|
||||
@@ -1637,26 +1601,26 @@ void GameWorldView::drawWorldItem(QPainter& painter, const std::string& itemId,
|
||||
painter.drawRect(itemRect);
|
||||
}
|
||||
|
||||
void GameWorldView::drawBeltItems(QPainter& painter)
|
||||
void GameWorldView::drawBeltItems(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
const float halfPx = getTilePx() * 0.5f * 0.5f;
|
||||
const QRect vr = getViewportRect();
|
||||
const float halfPx = coordinates.getTilePx() * 0.5f * 0.5f;
|
||||
const QRect vr = coordinates.getViewportRect();
|
||||
|
||||
m_sim->getBelts().forEachVisualItem(vr, [&](const VisualItem& vi)
|
||||
{
|
||||
const QPointF center = worldToWidget(
|
||||
const QPointF center = coordinates.worldToWidget(
|
||||
QVector2D(static_cast<float>(vi.worldPos.x()),
|
||||
static_cast<float>(vi.worldPos.y())));
|
||||
drawWorldItem(painter, vi.type.id, center, halfPx);
|
||||
});
|
||||
}
|
||||
|
||||
void GameWorldView::drawDebris(QPainter& painter)
|
||||
void GameWorldView::drawDebris(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
const float r = getTilePx() * 0.2f;
|
||||
const float r = coordinates.getTilePx() * 0.2f;
|
||||
for (const DebrisInfo& debris : getAllDebrisInfo(m_sim->getAdmin()))
|
||||
{
|
||||
const QPointF center = worldToWidget(debris.position);
|
||||
const QPointF center = coordinates.worldToWidget(debris.position);
|
||||
painter.setBrush(QColor(128, 110, 90));
|
||||
painter.setPen(QPen(QColor(50, 40, 30), 1));
|
||||
painter.drawEllipse(center,
|
||||
@@ -1664,7 +1628,7 @@ void GameWorldView::drawDebris(QPainter& painter)
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorldView::drawStations(QPainter& painter)
|
||||
void GameWorldView::drawStations(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
m_sim->getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
|
||||
[&](entt::entity e, const StationBodyComponent& sb, const FactionComponent& f,
|
||||
@@ -1681,13 +1645,14 @@ void GameWorldView::drawStations(QPainter& painter)
|
||||
painter.setPen(Qt::NoPen);
|
||||
for (const QPoint& cell : sb.bodyCells)
|
||||
{
|
||||
painter.fillRect(tileRect(cell), bv.fill);
|
||||
painter.fillRect(coordinates.tileRect(cell), bv.fill);
|
||||
}
|
||||
|
||||
const QPointF tl = tileToWidget(QPoint(sb.anchor.x(), sb.anchor.y()));
|
||||
const QPointF tl =
|
||||
coordinates.tileToWidget(QPoint(sb.anchor.x(), sb.anchor.y()));
|
||||
const QRectF bboxRect(tl.x(), tl.y(),
|
||||
sb.footprint.width() * static_cast<qreal>(getTilePx()),
|
||||
sb.footprint.height() * static_cast<qreal>(getTilePx()));
|
||||
sb.footprint.width() * static_cast<qreal>(coordinates.getTilePx()),
|
||||
sb.footprint.height() * static_cast<qreal>(coordinates.getTilePx()));
|
||||
|
||||
painter.setPen(QPen(bv.outline, 1));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
@@ -1695,7 +1660,7 @@ void GameWorldView::drawStations(QPainter& painter)
|
||||
|
||||
// Station icon over the fill (REQ-UI-WORLD-ICON); the same symbol is
|
||||
// colored blue/red by the player/enemy fill it is drawn over.
|
||||
drawBuildingIcon(painter, visType, bboxRect, bv.fill);
|
||||
drawBuildingIcon(painter, coordinates, visType, bboxRect, bv.fill);
|
||||
|
||||
if (isEntitySelected(e))
|
||||
{
|
||||
@@ -1707,13 +1672,14 @@ void GameWorldView::drawStations(QPainter& painter)
|
||||
// HP bar below footprint.
|
||||
if (h.maxHp > 0.0f)
|
||||
{
|
||||
drawHpBar(painter, bboxRect.left(), bboxRect.bottom() + 1.0,
|
||||
drawHpBar(painter, coordinates,
|
||||
bboxRect.left(), bboxRect.bottom() + 1.0,
|
||||
bboxRect.width(), h.hp / h.maxHp, f.isEnemy);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void GameWorldView::drawShips(QPainter& painter)
|
||||
void GameWorldView::drawShips(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
m_sim->getAdmin().forEach<ShipIdentityComponent, PositionComponent, FacingComponent,
|
||||
FactionComponent, HealthComponent>(
|
||||
@@ -1725,12 +1691,12 @@ void GameWorldView::drawShips(QPainter& painter)
|
||||
m_visuals->ships.find(si.schematicId);
|
||||
if (it == m_visuals->ships.end()) { return; }
|
||||
|
||||
const QPointF center = worldToWidget(pos.value);
|
||||
const QPointF center = coordinates.worldToWidget(pos.value);
|
||||
const QVector2D dir(std::cos(facing.radians), std::sin(facing.radians));
|
||||
const QVector2D perp(-dir.y(), dir.x());
|
||||
|
||||
const float fwd = getTilePx() * 0.45f;
|
||||
const float side = getTilePx() * 0.25f;
|
||||
const float fwd = coordinates.getTilePx() * 0.45f;
|
||||
const float side = coordinates.getTilePx() * 0.25f;
|
||||
|
||||
QPolygonF tri;
|
||||
tri << QPointF(center.x() + static_cast<qreal>(dir.x() * fwd),
|
||||
@@ -1757,22 +1723,25 @@ void GameWorldView::drawShips(QPainter& painter)
|
||||
const qreal barW = static_cast<qreal>(fwd) * 2.0;
|
||||
const qreal barX = center.x() - static_cast<qreal>(fwd);
|
||||
const qreal barY = center.y() + static_cast<qreal>(fwd) + 1.0;
|
||||
drawHpBar(painter, barX, barY, barW, h.hp / h.maxHp, fac.isEnemy);
|
||||
drawHpBar(painter, coordinates, barX, barY, barW,
|
||||
h.hp / h.maxHp, fac.isEnemy);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void GameWorldView::drawHpBar(QPainter& painter, qreal left, qreal top, qreal width,
|
||||
void GameWorldView::drawHpBar(QPainter& painter, const WorldCoordinates& coordinates,
|
||||
qreal left, qreal top, qreal width,
|
||||
float fraction, bool isEnemy)
|
||||
{
|
||||
const qreal barH = static_cast<qreal>(getTilePx()) * 0.12;
|
||||
const qreal barH = static_cast<qreal>(coordinates.getTilePx()) * 0.12;
|
||||
const float clamped = std::max(0.0f, fraction);
|
||||
painter.fillRect(QRectF(left, top, width, barH), QColor(60, 60, 60));
|
||||
painter.fillRect(QRectF(left, top, width * static_cast<qreal>(clamped), barH),
|
||||
isEnemy ? QColor(200, 60, 60) : QColor(60, 200, 60));
|
||||
}
|
||||
|
||||
void GameWorldView::drawDebugSensorRanges(QPainter& painter)
|
||||
void GameWorldView::drawDebugSensorRanges(QPainter& painter,
|
||||
const WorldCoordinates& coordinates)
|
||||
{
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
m_sim->getAdmin().forEach<ShipIdentityComponent, PositionComponent, FacingComponent,
|
||||
@@ -1785,9 +1754,9 @@ void GameWorldView::drawDebugSensorRanges(QPainter& painter)
|
||||
m_visuals->ships.find(si.schematicId);
|
||||
if (it == m_visuals->ships.end()) { return; }
|
||||
|
||||
const QPointF center = worldToWidget(pos.value);
|
||||
const QPointF center = coordinates.worldToWidget(pos.value);
|
||||
const qreal radiusPx = static_cast<qreal>(sensor.value_tiles)
|
||||
* static_cast<qreal>(getTilePx());
|
||||
* static_cast<qreal>(coordinates.getTilePx());
|
||||
QColor circleColor = it->second.outline;
|
||||
circleColor.setAlpha(77);
|
||||
painter.setPen(QPen(circleColor, 1));
|
||||
@@ -1795,7 +1764,8 @@ void GameWorldView::drawDebugSensorRanges(QPainter& painter)
|
||||
});
|
||||
}
|
||||
|
||||
void GameWorldView::drawDebugTargetLines(QPainter& painter)
|
||||
void GameWorldView::drawDebugTargetLines(QPainter& painter,
|
||||
const WorldCoordinates& coordinates)
|
||||
{
|
||||
// Draw a thin translucent line from a ship to a target, colored by the ship's
|
||||
// own schematic fill. Shared by the attack, repair and salvage target lines.
|
||||
@@ -1810,7 +1780,8 @@ void GameWorldView::drawDebugTargetLines(QPainter& painter)
|
||||
QColor lineColor = it->second.fill;
|
||||
lineColor.setAlpha(128);
|
||||
painter.setPen(QPen(lineColor, 1));
|
||||
painter.drawLine(worldToWidget(from), worldToWidget(to));
|
||||
painter.drawLine(coordinates.worldToWidget(from),
|
||||
coordinates.worldToWidget(to));
|
||||
};
|
||||
|
||||
m_sim->getAdmin().forEach<ShipIdentityComponent, PositionComponent, AttackBehavior>(
|
||||
@@ -1896,7 +1867,7 @@ void GameWorldView::drawDebugOverlay(QPainter& painter)
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorldView::drawBeams(QPainter& painter)
|
||||
void GameWorldView::drawBeams(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
const QPainter::RenderHints savedHints = painter.renderHints();
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
@@ -1915,8 +1886,8 @@ void GameWorldView::drawBeams(QPainter& painter)
|
||||
case BeamKind::Salvage: color = m_visuals->beams.salvageColor; break;
|
||||
}
|
||||
|
||||
const QPointF s = worldToWidget(*shooterPos);
|
||||
const QPointF t = worldToWidget(*targetPos + beam.targetOffset);
|
||||
const QPointF s = coordinates.worldToWidget(*shooterPos);
|
||||
const QPointF t = coordinates.worldToWidget(*targetPos + beam.targetOffset);
|
||||
|
||||
// Unit direction/perpendicular of the beam in widget space. A degenerate
|
||||
// zero-length beam (shooter and target coincide) has no direction to
|
||||
@@ -1965,7 +1936,8 @@ void GameWorldView::drawBeams(QPainter& painter)
|
||||
painter.setRenderHints(savedHints);
|
||||
}
|
||||
|
||||
void GameWorldView::drawSelectedTunnelConnections(QPainter& painter)
|
||||
void GameWorldView::drawSelectedTunnelConnections(QPainter& painter,
|
||||
const WorldCoordinates& coordinates)
|
||||
{
|
||||
if (m_selectedBuildingIds.empty()) { return; }
|
||||
|
||||
@@ -2015,14 +1987,14 @@ void GameWorldView::drawSelectedTunnelConnections(QPainter& painter)
|
||||
const QColor green = m_visuals->overlays.tunnelPreview;
|
||||
for (const QPoint& tile : highlightTiles)
|
||||
{
|
||||
painter.fillRect(tileRect(tile), green);
|
||||
painter.fillRect(coordinates.tileRect(tile), green);
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorldView::drawOverlays(QPainter& painter)
|
||||
void GameWorldView::drawOverlays(QPainter& painter, const WorldCoordinates& coordinates)
|
||||
{
|
||||
// Green connection highlight for any selected tunnel end (REQ-BLD-TUNNEL-SELECT-HIGHLIGHT).
|
||||
drawSelectedTunnelConnections(painter);
|
||||
drawSelectedTunnelConnections(painter, coordinates);
|
||||
|
||||
// Builder-mode ghost
|
||||
if (m_builderType.has_value())
|
||||
@@ -2041,8 +2013,8 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
continue;
|
||||
}
|
||||
const BeltPathTile& entry = m_beltDragPath[index];
|
||||
drawBuildingGhost(painter, BuildingType::Belt, entry.tile,
|
||||
entry.rotation,
|
||||
drawBuildingGhost(painter, coordinates, BuildingType::Belt,
|
||||
entry.tile, entry.rotation,
|
||||
/*valid*/ item.action != BeltTileAction::Invalid,
|
||||
/*showPortTargetGlyphs*/ true);
|
||||
}
|
||||
@@ -2056,7 +2028,7 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
if (inTunnelMode() && m_ghostValid && m_tunnelPartnerTile.has_value())
|
||||
{
|
||||
const QColor green = m_visuals->overlays.tunnelPreview;
|
||||
painter.fillRect(tileRect(*m_tunnelPartnerTile), green);
|
||||
painter.fillRect(coordinates.tileRect(*m_tunnelPartnerTile), green);
|
||||
|
||||
// Partner and ghost tile are colinear along the tunnel run; tint the
|
||||
// tiles strictly between them.
|
||||
@@ -2065,12 +2037,12 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
(delta.y() > 0) - (delta.y() < 0));
|
||||
for (QPoint t = m_ghostTile + step; t != *m_tunnelPartnerTile; t += step)
|
||||
{
|
||||
painter.fillRect(tileRect(t), green);
|
||||
painter.fillRect(coordinates.tileRect(t), green);
|
||||
}
|
||||
}
|
||||
|
||||
drawBuildingGhost(painter, effectiveBuilderType(), m_ghostTile,
|
||||
m_ghostRotation, m_ghostValid,
|
||||
drawBuildingGhost(painter, coordinates, effectiveBuilderType(),
|
||||
m_ghostTile, m_ghostRotation, m_ghostValid,
|
||||
/*showPortTargetGlyphs*/ true);
|
||||
}
|
||||
}
|
||||
@@ -2085,8 +2057,8 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
if (!m_sim->isBuildingUnlocked(bb.type)) { continue; }
|
||||
const QPoint anchor = m_blueprintGhostTile + bb.offset;
|
||||
const bool valid = isValidPlacement(bb.type, anchor, bb.rotation);
|
||||
drawBuildingGhost(painter, bb.type, anchor, bb.rotation, valid,
|
||||
/*showPortTargetGlyphs*/ false);
|
||||
drawBuildingGhost(painter, coordinates, bb.type, anchor, bb.rotation,
|
||||
valid, /*showPortTargetGlyphs*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2097,7 +2069,8 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
if (!b.queuedForDeconstruction) { continue; }
|
||||
for (const QPoint& cell : b.bodyCells)
|
||||
{
|
||||
painter.fillRect(tileRect(cell), m_visuals->overlays.deconstructTint);
|
||||
painter.fillRect(coordinates.tileRect(cell),
|
||||
m_visuals->overlays.deconstructTint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2117,7 +2090,8 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
{
|
||||
for (const QPoint& cell : *cells)
|
||||
{
|
||||
painter.fillRect(tileRect(cell), m_visuals->overlays.deconstructTint);
|
||||
painter.fillRect(coordinates.tileRect(cell),
|
||||
m_visuals->overlays.deconstructTint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2129,7 +2103,8 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
{
|
||||
for (const QPoint& cell : b->bodyCells)
|
||||
{
|
||||
painter.fillRect(tileRect(cell), m_visuals->overlays.deconstructTint);
|
||||
painter.fillRect(coordinates.tileRect(cell),
|
||||
m_visuals->overlays.deconstructTint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2141,14 +2116,17 @@ void GameWorldView::drawOverlays(QPainter& painter)
|
||||
std::min(m_boxStartTile.y(), m_boxCurrentTile.y()));
|
||||
const QPoint br(std::max(m_boxStartTile.x(), m_boxCurrentTile.x()) + 1,
|
||||
std::max(m_boxStartTile.y(), m_boxCurrentTile.y()) + 1);
|
||||
const QRectF selRect(tileToWidget(tl), tileToWidget(br));
|
||||
const QRectF selRect(coordinates.tileToWidget(tl),
|
||||
coordinates.tileToWidget(br));
|
||||
painter.setPen(QPen(m_visuals->overlays.selectionRect, 1));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawRect(selRect);
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
|
||||
void GameWorldView::drawBuildingGhost(QPainter& painter,
|
||||
const WorldCoordinates& coordinates,
|
||||
BuildingType type,
|
||||
QPoint anchorTile, Rotation rotation,
|
||||
bool valid, bool showPortTargetGlyphs)
|
||||
{
|
||||
@@ -2179,17 +2157,17 @@ void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
|
||||
QPoint maxCell = parsed.bodyCells.front();
|
||||
for (const QPoint& cell : parsed.bodyCells)
|
||||
{
|
||||
painter.fillRect(tileRect(anchorTile + cell), fillColor);
|
||||
painter.fillRect(coordinates.tileRect(anchorTile + cell), fillColor);
|
||||
minCell.setX(std::min(minCell.x(), cell.x()));
|
||||
minCell.setY(std::min(minCell.y(), cell.y()));
|
||||
maxCell.setX(std::max(maxCell.x(), cell.x()));
|
||||
maxCell.setY(std::max(maxCell.y(), cell.y()));
|
||||
}
|
||||
|
||||
const QPointF tl = tileToWidget(anchorTile + minCell);
|
||||
const QPointF tl = coordinates.tileToWidget(anchorTile + minCell);
|
||||
const QRectF bboxRect(tl.x(), tl.y(),
|
||||
(maxCell.x() - minCell.x() + 1) * static_cast<qreal>(getTilePx()),
|
||||
(maxCell.y() - minCell.y() + 1) * static_cast<qreal>(getTilePx()));
|
||||
(maxCell.x() - minCell.x() + 1) * static_cast<qreal>(coordinates.getTilePx()),
|
||||
(maxCell.y() - minCell.y() + 1) * static_cast<qreal>(coordinates.getTilePx()));
|
||||
|
||||
painter.setPen(QPen(lineColor, 1));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
@@ -2197,7 +2175,8 @@ void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
|
||||
|
||||
// Icon glyph over the ghost fill (REQ-UI-WORLD-ICON); an invalid ghost's fill
|
||||
// is the red invalid color, which auto-contrasts to a white icon.
|
||||
if (!drawBuildingIcon(painter, type, bboxRect, fillColor) && !bv.glyph.isEmpty())
|
||||
if (!drawBuildingIcon(painter, coordinates, type, bboxRect, fillColor)
|
||||
&& !bv.glyph.isEmpty())
|
||||
{
|
||||
painter.setPen(lineColor);
|
||||
painter.drawText(bboxRect, Qt::AlignCenter, bv.glyph);
|
||||
@@ -2205,7 +2184,8 @@ void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
|
||||
|
||||
for (const Port& port : parsed.outputPorts)
|
||||
{
|
||||
drawPortGlyph(painter, anchorTile + outputBodyTile(port.tile, port.direction),
|
||||
drawPortGlyph(painter, coordinates,
|
||||
anchorTile + outputBodyTile(port.tile, port.direction),
|
||||
port.direction, lineColor, /*centered*/ false);
|
||||
}
|
||||
|
||||
@@ -2221,8 +2201,8 @@ void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
|
||||
{
|
||||
for (const Port& port : parsed.outputPorts)
|
||||
{
|
||||
drawPortGlyph(painter, anchorTile + port.tile, port.direction,
|
||||
lineColor, /*centered*/ true);
|
||||
drawPortGlyph(painter, coordinates, anchorTile + port.tile,
|
||||
port.direction, lineColor, /*centered*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2483,6 +2463,8 @@ void GameWorldView::keyReleaseEvent(QKeyEvent* event)
|
||||
|
||||
void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
const WorldCoordinates coordinates = getCoordinates();
|
||||
|
||||
if (event->button() != Qt::LeftButton)
|
||||
{
|
||||
if (event->button() == Qt::RightButton)
|
||||
@@ -2507,7 +2489,7 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
// Shift + right-click copies a building's settings, but only in the
|
||||
// default selection mode (REQ-BLD-COPY-CONFIG).
|
||||
const QPoint tile = widgetToTile(event->pos());
|
||||
const QPoint tile = coordinates.widgetToTile(event->pos());
|
||||
std::optional<BuildingId> id = buildingAtTile(tile);
|
||||
if (!id.has_value()) { id = siteAtTile(tile); }
|
||||
if (id.has_value()) { copyConfigFrom(*id); }
|
||||
@@ -2516,7 +2498,7 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||
return;
|
||||
}
|
||||
|
||||
const QPoint tile = widgetToTile(event->pos());
|
||||
const QPoint tile = coordinates.widgetToTile(event->pos());
|
||||
|
||||
if (m_builderType.has_value())
|
||||
{
|
||||
@@ -2527,7 +2509,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());
|
||||
m_cursorWorldPos = coordinates.widgetToWorld(event->pos());
|
||||
recomputeBeltDragPath(tile);
|
||||
}
|
||||
else
|
||||
@@ -2564,7 +2546,7 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||
}
|
||||
|
||||
const bool ctrl = (event->modifiers() & Qt::ControlModifier) != 0;
|
||||
const QVector2D worldPos = widgetToWorld(event->pos());
|
||||
const QVector2D worldPos = coordinates.widgetToWorld(event->pos());
|
||||
|
||||
// Point hit-test precedence: buildings win over actors, which win over debris
|
||||
// (REQ-UI-SELECTION-CATEGORIES).
|
||||
@@ -2690,8 +2672,9 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||
|
||||
void GameWorldView::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
const QPoint tile = widgetToTile(event->pos());
|
||||
m_cursorWorldPos = widgetToWorld(event->pos());
|
||||
const WorldCoordinates coordinates = getCoordinates();
|
||||
const QPoint tile = coordinates.widgetToTile(event->pos());
|
||||
m_cursorWorldPos = coordinates.widgetToWorld(event->pos());
|
||||
|
||||
if (m_builderType.has_value())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user