Allow creating blueprints from construction sites

This commit is contained in:
2026-07-13 20:50:13 +02:00
parent 698dd4d13d
commit 8c4fb78fc9
5 changed files with 225 additions and 69 deletions

View File

@@ -146,60 +146,10 @@ void BlueprintPanel::onBlueprintButtonClicked(int index)
Blueprint BlueprintPanel::createBlueprintFromSelection() const
{
struct Entry
{
const Building* building;
};
std::vector<Entry> entries;
entries.reserve(m_selectedBuildingIds.size());
for (const BuildingId id : m_selectedBuildingIds)
{
const Building* b = m_sim->buildings().findBuilding(id);
if (!b) { continue; }
const BuildingDef* def = m_config->buildings.findBuildingDef(b->type);
if (def && def->playerPlaceable) { entries.push_back({ b }); }
}
if (entries.empty()) { return Blueprint{}; }
int minX = INT_MAX, maxX = INT_MIN;
int minY = INT_MAX, maxY = INT_MIN;
for (const Entry& e : entries)
{
for (const QPoint& cell : e.building->bodyCells)
{
minX = std::min(minX, cell.x());
maxX = std::max(maxX, cell.x());
minY = std::min(minY, cell.y());
maxY = std::max(maxY, cell.y());
}
}
const QPoint center((minX + maxX) / 2, (minY + maxY) / 2);
Blueprint bp;
bp.buildings.reserve(entries.size());
for (const Entry& e : entries)
{
BlueprintBuilding bb;
bb.type = e.building->type;
bb.rotation = e.building->rotation;
bb.offset = e.building->anchor - center;
// Recipe / schematic / layout / splitter-filter capture is shared with the
// copy-settings gesture (REQ-BLD-COPY-CONFIG) via readBuildingConfig.
const std::optional<BuildingConfig> config =
readBuildingConfig(*m_sim, e.building->id);
if (config.has_value())
{
bb.recipeId = config->recipeId.value_or(std::string());
bb.shipLayout = config->shipLayout;
bb.splitterFilterA = config->splitterFilterA;
bb.splitterFilterB = config->splitterFilterB;
}
bp.buildings.push_back(bb);
}
return bp;
// Capture is shared, testable logic in lib/sim: it resolves each selected id as an
// operational building or a construction site alike (REQ-UI-BLUEPRINT-CREATE,
// REQ-UI-BLUEPRINT-STORAGE).
return captureBlueprintFromSelection(*m_sim, m_selectedBuildingIds);
}
int BlueprintPanel::computeBlueprintCost(const Blueprint& bp) const
@@ -295,19 +245,8 @@ void BlueprintPanel::loadFromDisk()
void BlueprintPanel::refreshButtonStates()
{
const bool anyPlaceable = [&]() {
for (const BuildingId id : m_selectedBuildingIds)
{
const Building* b = m_sim->buildings().findBuilding(id);
if (!b) { continue; }
for (const BuildingDef& def : m_config->buildings.buildings)
{
if (def.type == b->type) { return def.playerPlaceable; }
}
}
return false;
}();
m_createBtn->setEnabled(anyPlaceable);
// A construction site counts the same as an operational building (REQ-UI-BLUEPRINT-CREATE).
m_createBtn->setEnabled(selectionHasPlaceableBuilding(*m_sim, m_selectedBuildingIds));
for (int i = 0; i < static_cast<int>(m_blueprintButtons.size()); ++i)
{