extract WorldRenderer
This commit is contained in:
@@ -153,3 +153,13 @@ std::optional<QPoint> findTunnelPartner(const TunnelLookup& lookup, QPoint tile,
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
TunnelLookup makeTunnelLookup(const TunnelTileMap& tunnels)
|
||||
{
|
||||
return [&tunnels](QPoint tile) -> std::optional<TunnelTileInfo>
|
||||
{
|
||||
const TunnelTileMap::const_iterator it = tunnels.find(tile);
|
||||
if (it == tunnels.end()) { return std::nullopt; }
|
||||
return it->second;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
#include <QPoint>
|
||||
@@ -9,6 +10,17 @@
|
||||
#include "BuildingType.h"
|
||||
#include "Rotation.h"
|
||||
|
||||
// QPoint has no operator<, so an explicit ordering is needed to key a map or set
|
||||
// by tile.
|
||||
struct QPointCompare
|
||||
{
|
||||
bool operator()(const QPoint& a, const QPoint& b) const
|
||||
{
|
||||
if (a.x() != b.x()) { return a.x() < b.x(); }
|
||||
return a.y() < b.y();
|
||||
}
|
||||
};
|
||||
|
||||
// A tunnel building occupying a single tile: whether it is an entry or an exit and
|
||||
// the direction it faces. Used by the tunnel pairing scan (REQ-BLD-TUNNEL-PAIR) and
|
||||
// the unified tunnel build mode (REQ-BLD-TUNNEL-MODE).
|
||||
@@ -22,6 +34,13 @@ struct TunnelTileInfo
|
||||
// direction, or std::nullopt when the tile holds no tunnel building.
|
||||
using TunnelLookup = std::function<std::optional<TunnelTileInfo>(QPoint)>;
|
||||
|
||||
// Tunnel entries/exits indexed by their single-cell tile (REQ-BLD-TUNNEL-MODE).
|
||||
using TunnelTileMap = std::map<QPoint, TunnelTileInfo, QPointCompare>;
|
||||
|
||||
// Wraps a tunnel tile index in the lookup functor the helpers below take. The
|
||||
// returned functor references `tunnels`, which must outlive it.
|
||||
TunnelLookup makeTunnelLookup(const TunnelTileMap& tunnels);
|
||||
|
||||
// Steps from `start` in `stepDir` over the tiles at distance 1..maxDistance and
|
||||
// returns the first tile whose tunnel faces `targetFacing`. Tunnel buildings facing
|
||||
// any other direction are skipped, mirroring the "stop at the first same-direction
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "FactoryQueries.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include "PortGeometry.h"
|
||||
@@ -179,3 +180,61 @@ getSiteSplitterInfo(const FactoryState& state, const GameConfig& config, Buildin
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
std::vector<BuildingId> buildingsInBox(const FactoryState& state,
|
||||
QPoint cornerA, QPoint cornerB)
|
||||
{
|
||||
const int x0 = std::min(cornerA.x(), cornerB.x());
|
||||
const int y0 = std::min(cornerA.y(), cornerB.y());
|
||||
const int x1 = std::max(cornerA.x(), cornerB.x());
|
||||
const int y1 = std::max(cornerA.y(), cornerB.y());
|
||||
|
||||
const auto covers = [&](const std::vector<QPoint>& bodyCells)
|
||||
{
|
||||
for (const QPoint& cell : bodyCells)
|
||||
{
|
||||
if (cell.x() >= x0 && cell.x() <= x1
|
||||
&& cell.y() >= y0 && cell.y() <= y1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
std::vector<BuildingId> ids;
|
||||
for (const Building& building : getAllBuildings(state))
|
||||
{
|
||||
if (covers(building.bodyCells)) { ids.push_back(building.id); }
|
||||
}
|
||||
for (const ConstructionSite& site : getAllSites(state))
|
||||
{
|
||||
if (covers(site.bodyCells)) { ids.push_back(site.id); }
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
TunnelTileMap collectTunnelTiles(const FactoryState& state)
|
||||
{
|
||||
// Index every tunnel entry/exit — built or still a construction site — by its
|
||||
// single-cell tile, so a just-placed tunnel (not yet constructed) is matchable
|
||||
// (REQ-BLD-TUNNEL-MODE, REQ-BLD-TUNNEL-SELECT-HIGHLIGHT).
|
||||
TunnelTileMap tunnels;
|
||||
for (const Building& building : getAllBuildings(state))
|
||||
{
|
||||
if (building.type == BuildingType::TunnelEntry
|
||||
|| building.type == BuildingType::TunnelExit)
|
||||
{
|
||||
tunnels[building.anchor] = TunnelTileInfo{building.type, building.rotation};
|
||||
}
|
||||
}
|
||||
for (const ConstructionSite& site : getAllSites(state))
|
||||
{
|
||||
if (site.type == BuildingType::TunnelEntry
|
||||
|| site.type == BuildingType::TunnelExit)
|
||||
{
|
||||
tunnels[site.anchor] = TunnelTileInfo{site.type, site.rotation};
|
||||
}
|
||||
}
|
||||
return tunnels;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "FactoryState.h"
|
||||
#include "GameConfig.h"
|
||||
#include "Port.h"
|
||||
#include "TunnelCompletion.h"
|
||||
|
||||
// Queries and operations over the factory's world data that need nothing but that
|
||||
// data — no config, no belts, no RNG. Free functions rather than BuildingSystem
|
||||
@@ -69,3 +70,13 @@ std::vector<Port> getInputPorts(const FactoryState& state, const GameConfig& con
|
||||
std::optional<BeltSystem::SplitterInfo> getSiteSplitterInfo(const FactoryState& state,
|
||||
const GameConfig& config,
|
||||
BuildingId id);
|
||||
|
||||
// Ids of all buildings and construction sites whose footprint intersects the tile
|
||||
// box spanned by the two (unordered) corner tiles (REQ-UI-MULTI-SELECT,
|
||||
// REQ-BLD-DECONSTRUCT-BOX).
|
||||
std::vector<BuildingId> buildingsInBox(const FactoryState& state,
|
||||
QPoint cornerA, QPoint cornerB);
|
||||
|
||||
// Every tunnel entry and exit, built or still a construction site, indexed by its
|
||||
// single-cell tile. Shared by the placement preview and the selection highlight.
|
||||
TunnelTileMap collectTunnelTiles(const FactoryState& state);
|
||||
|
||||
Reference in New Issue
Block a user