move blueprints out of the sidebar into Ctrl+C / Ctrl+V dialogs
This commit is contained in:
@@ -3,10 +3,14 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
|
||||
#include "BeltSystem.h"
|
||||
#include "Building.h"
|
||||
#include "BuildingsConfig.h"
|
||||
#include "BuildingSystem.h"
|
||||
#include "DisplayName.h"
|
||||
#include "Simulation.h"
|
||||
|
||||
namespace
|
||||
@@ -49,6 +53,21 @@ std::optional<SelectedBuilding> resolvePlaceable(const Simulation& sim, Building
|
||||
resolved.bodyCells = building ? &building->bodyCells : &site->bodyCells;
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// Position of a building type in buildings.toml, which is the order the build button
|
||||
// bar lays out its buttons (REQ-UI-BUILD-BAR) and so the tie-break order for a
|
||||
// blueprint's contents line. A type with no config entry sorts after every known one.
|
||||
std::size_t configOrderIndex(BuildingType type, const BuildingsConfig& buildings)
|
||||
{
|
||||
for (std::size_t i = 0; i < buildings.buildings.size(); ++i)
|
||||
{
|
||||
if (buildings.buildings[i].type == type)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return buildings.buildings.size();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::optional<BuildingConfig> readBuildingConfig(const Simulation& sim, BuildingId id)
|
||||
@@ -166,3 +185,56 @@ bool selectionHasPlaceableBuilding(const Simulation& sim,
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<BlueprintContentEntry> summarizeBlueprintContents(
|
||||
const Blueprint& blueprint, const BuildingsConfig& buildings)
|
||||
{
|
||||
std::map<BuildingType, int> counts;
|
||||
for (const BlueprintBuilding& building : blueprint.buildings)
|
||||
{
|
||||
++counts[building.type];
|
||||
}
|
||||
|
||||
// The config index is carried through the sort so the comparator stays a strict
|
||||
// total order; the enum value is the final tie-break, which only two config-less
|
||||
// types could ever reach.
|
||||
struct RankedType
|
||||
{
|
||||
BuildingType type;
|
||||
int count;
|
||||
std::size_t order;
|
||||
};
|
||||
std::vector<RankedType> ranked;
|
||||
ranked.reserve(counts.size());
|
||||
for (const std::pair<const BuildingType, int>& entry : counts)
|
||||
{
|
||||
ranked.push_back({entry.first, entry.second,
|
||||
configOrderIndex(entry.first, buildings)});
|
||||
}
|
||||
std::sort(ranked.begin(), ranked.end(),
|
||||
[](const RankedType& left, const RankedType& right)
|
||||
{
|
||||
if (left.count != right.count) { return left.count > right.count; }
|
||||
if (left.order != right.order) { return left.order < right.order; }
|
||||
return static_cast<int>(left.type) < static_cast<int>(right.type);
|
||||
});
|
||||
|
||||
std::vector<BlueprintContentEntry> summary;
|
||||
summary.reserve(ranked.size());
|
||||
for (const RankedType& entry : ranked)
|
||||
{
|
||||
summary.push_back({toDisplayName(buildingTypeId(entry.type)), entry.count});
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
|
||||
int computeBlueprintCost(const Blueprint& blueprint, const BuildingsConfig& buildings)
|
||||
{
|
||||
int total = 0;
|
||||
for (const BlueprintBuilding& building : blueprint.buildings)
|
||||
{
|
||||
const BuildingDef* def = buildings.findBuildingDef(building.type);
|
||||
if (def) { total += def->cost; }
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "ShipLayout.h"
|
||||
|
||||
class Simulation;
|
||||
struct BuildingsConfig;
|
||||
|
||||
// The user-configurable settings of a single building or construction site: the
|
||||
// selected recipe / ship schematic, the shipyard module layout, and (for
|
||||
@@ -49,6 +50,29 @@ Blueprint captureBlueprintFromSelection(const Simulation& sim,
|
||||
const std::vector<BuildingId>& selectedIds);
|
||||
|
||||
// True if any selected id refers to a player-placeable building or construction site
|
||||
// (the enable condition for the Create Blueprint button, REQ-UI-BLUEPRINT-CREATE).
|
||||
// (the condition under which Ctrl+C opens the blueprint save dialog,
|
||||
// REQ-UI-BLUEPRINT-CREATE).
|
||||
bool selectionHasPlaceableBuilding(const Simulation& sim,
|
||||
const std::vector<BuildingId>& selectedIds);
|
||||
|
||||
// One "<building name> x <count>" entry of a blueprint card's contents line
|
||||
// (REQ-UI-BLUEPRINT-CARD).
|
||||
struct BlueprintContentEntry
|
||||
{
|
||||
std::string buildingName;
|
||||
int count;
|
||||
};
|
||||
|
||||
// Summarizes what a blueprint holds: one entry per building type it contains, ordered
|
||||
// by descending count with ties broken by the order the types appear in buildings.toml
|
||||
// (which is the order of the build button bar, REQ-UI-BUILD-BAR). Building types absent
|
||||
// from the config sort last. Derived display data for the blueprint card, kept here so
|
||||
// it is unit-testable rather than buried in the dialog (REQ-UI-BLUEPRINT-CARD).
|
||||
std::vector<BlueprintContentEntry> summarizeBlueprintContents(
|
||||
const Blueprint& blueprint, const BuildingsConfig& buildings);
|
||||
|
||||
// Plain sum of the placement cost of every building in the blueprint
|
||||
// (REQ-UI-BLUEPRINT-CARD). Distinct from the total charged on placement
|
||||
// (REQ-UI-BLUEPRINT-PLACE), which additionally excludes locked building types and
|
||||
// rotate-in-place targets; see GameWorldView's placement path.
|
||||
int computeBlueprintCost(const Blueprint& blueprint, const BuildingsConfig& buildings);
|
||||
|
||||
Reference in New Issue
Block a user