share BuildingSystem's free functions instead of copying them

Four of the five file-local helpers in BuildingSystem.cpp had duplicates
elsewhere: isAutoRecipeBuildingType and isBeltSubsystemType were re-spelled as
isAutoRecipeBuilding and isBeltLike in SelectedBuildingPanel.cpp, and
outputBodyTile was copied verbatim as portBodyTile in GameWorldView.cpp. Same
predicates, different names, so a change to one would silently not reach the
others.

The two BuildingType predicates move to BuildingType.h, which already hosts the
free functions over that enum and is already included by both lib and ui. The
port geometry moves to a new PortGeometry.h; inputBodyTile has no duplicate but
is outputBodyTile's counterpart and belongs beside it — the sim moves items
across the port edge and the renderer draws the virtual belt there, so the two
must agree on which tile a port owns.

inputLaneEntryFree stays file-local: single use, and tied to BeltItemSlot rather
than to building types or port geometry.

Verified the six moved bodies are character-identical to their originals.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHcUerKAZKWNvSKJxYKbnG
This commit is contained in:
2026-08-04 16:09:01 +02:00
parent d713257fb5
commit fda88fe75c
7 changed files with 80 additions and 85 deletions

View File

@@ -50,6 +50,7 @@
#include "HealthComponent.h"
#include "HqProxyComponent.h"
#include "ItemIconCache.h"
#include "PortGeometry.h"
#include "PositionComponent.h"
#include "RepairBehavior.h"
#include "SalvageScrapBehavior.h"
@@ -166,18 +167,6 @@ Rotation rotateCounterClockwise(Rotation r)
return Rotation::East;
}
QPoint portBodyTile(QPoint portTile, Rotation direction)
{
switch (direction)
{
case Rotation::East: return portTile + QPoint(-1, 0);
case Rotation::West: return portTile + QPoint( 1, 0);
case Rotation::North: return portTile + QPoint( 0, 1);
case Rotation::South: return portTile + QPoint( 0, -1);
}
return portTile;
}
// Fill color for a building's status light per its production state
// (REQ-UI-STATUS-LIGHT).
QColor statusLightFill(ProductionStatus status, const StatusLightVisuals& sl)
@@ -1341,7 +1330,7 @@ void GameWorldView::drawBuildings(QPainter& painter)
for (const Port& port : b.outputPorts)
{
drawPortGlyph(painter, portBodyTile(port.tile, port.direction),
drawPortGlyph(painter, outputBodyTile(port.tile, port.direction),
port.direction, bv.outline, /*centered*/ false);
}
@@ -1441,7 +1430,7 @@ void GameWorldView::drawBuildings(QPainter& painter)
for (const Port& port : siteMask.outputPorts)
{
const QPoint absBody = s.anchor
+ portBodyTile(port.tile, port.direction);
+ outputBodyTile(port.tile, port.direction);
drawPortGlyph(painter, absBody, port.direction, bv.outline,
/*centered*/ false);
}
@@ -2215,7 +2204,7 @@ void GameWorldView::drawBuildingGhost(QPainter& painter, BuildingType type,
for (const Port& port : parsed.outputPorts)
{
drawPortGlyph(painter, anchorTile + portBodyTile(port.tile, port.direction),
drawPortGlyph(painter, anchorTile + outputBodyTile(port.tile, port.direction),
port.direction, lineColor, /*centered*/ false);
}

View File

@@ -84,20 +84,6 @@ bool hasRecipeSelection(BuildingType type)
|| type == BuildingType::Shipyard;
}
// Auto-recipe buildings have no selected recipe; their production is driven by
// whatever inputs they receive.
bool isAutoRecipeBuilding(BuildingType type)
{
return type == BuildingType::Smelter
|| type == BuildingType::ReprocessingPlant;
}
bool isBeltLike(BuildingType type)
{
return type == BuildingType::Belt || type == BuildingType::Splitter
|| type == BuildingType::TunnelEntry || type == BuildingType::TunnelExit;
}
QString rotationLabel(Rotation r)
{
switch (r)
@@ -313,7 +299,7 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
// Belt "Clear" removes items from a live belt tile; a construction site has
// none and is not registered with BeltSystem yet, so hide it for sites.
if (isBeltLike(type) && !m_singleIsSite)
if (isBeltSubsystemType(type) && !m_singleIsSite)
{
m_clearBeltBtn->show();
}
@@ -394,7 +380,7 @@ void SelectedBuildingPanel::refreshBuffers(const Building* b)
// Auto-recipe buildings (Smelter, Reprocessing Plant) have no selected
// recipe; while a cycle runs, resolve the recipe actually in production so
// the cycle time and progress can be shown (REQ-UI-PRODUCTION-PROGRESS).
if (!recipe && isAutoRecipeBuilding(b->type) && b->production.has_value())
if (!recipe && isAutoRecipeBuildingType(b->type) && b->production.has_value())
{
recipe = m_config->recipes.findRecipeDef(b->production->recipeId, b->type);
}
@@ -488,7 +474,7 @@ void SelectedBuildingPanel::refreshBuffers(const Building* b)
}
if (isProductionBuilding(b->type)
&& (recipe || shipDef || isAutoRecipeBuilding(b->type)))
&& (recipe || shipDef || isAutoRecipeBuildingType(b->type)))
{
if (recipe || shipDef)
{
@@ -683,7 +669,7 @@ void SelectedBuildingPanel::buildMulti(const std::vector<BuildingId>& ids)
{
text += buildingTypeName(entry.first) + " x "
+ QString::number(entry.second) + "\n";
if (isBeltLike(entry.first))
if (isBeltSubsystemType(entry.first))
{
hasBelt = true;
}
@@ -832,7 +818,7 @@ void SelectedBuildingPanel::onClearBelt()
for (BuildingId id : m_selectedBuildingIds)
{
const Building* b = m_sim->getBuildings().findBuilding(id);
if (b && isBeltLike(b->type))
if (b && isBeltSubsystemType(b->type))
{
for (const QPoint& cell : b->bodyCells)
{