allow to set the recipe already for construction sites

This commit is contained in:
2026-06-22 21:32:24 +02:00
parent e5017ab3c5
commit d271d65678
10 changed files with 233 additions and 89 deletions

View File

@@ -237,62 +237,40 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
m_singleBuildingId = id;
hideAllWidgets();
const Building* b = m_sim->buildings().findBuilding(id);
if (!b)
const Building* b = m_sim->buildings().findBuilding(id);
const ConstructionSite* s = b ? nullptr : m_sim->buildings().findSite(id);
if (!b && !s)
{
const ConstructionSite* s = m_sim->buildings().findSite(id);
if (!s)
{
buildEmpty();
return;
}
QString progress;
if (s->completesAt == 0)
{
progress = tr("Queued");
}
else
{
const BuildingDef* def = nullptr;
for (const BuildingDef& d : m_config->buildings.buildings)
{
if (d.type == s->type) { def = &d; break; }
}
if (def && def->constructionTimeSeconds > 0)
{
const Tick duration = secondsToTicks(def->constructionTimeSeconds);
const Tick elapsed = m_sim->currentTick() - (s->completesAt - duration);
const int pct = static_cast<int>(
std::max(Tick(0), std::min(duration, elapsed)) * 100 / duration);
progress = tr("%1% complete").arg(pct);
}
else
{
progress = tr("Building...");
}
}
m_titleLabel->setText(tr("(Building) %1").arg(buildingTypeName(s->type)));
m_titleLabel->show();
m_buffersLabel->setText(progress);
m_buffersLabel->show();
buildEmpty();
return;
}
m_singleIsSite = (s != nullptr);
m_titleLabel->setText(buildingTypeName(b->type));
// A construction site exposes the same configuration as the operational
// building it will become (REQ-BLD-SITE-CONFIG). The only difference is
// that its buffer/production rows are replaced by a construction-progress
// line, since a site has no buffers and runs no production cycle.
const BuildingType type = b ? b->type : s->type;
const std::string& recipeId = b ? b->recipeId : s->recipeId;
const std::optional<ShipLayoutConfig>& shipLayout =
b ? b->shipLayout : s->shipLayout;
const QPoint anchor = b ? b->anchor : s->anchor;
m_titleLabel->setText(m_singleIsSite
? tr("(Building) %1").arg(buildingTypeName(type))
: buildingTypeName(type));
m_titleLabel->show();
m_buffersLabel->show();
if (isProductionBuilding(b->type))
if (isProductionBuilding(type))
{
const std::vector<RecipeSelectionOption> options =
buildRecipeSelectionOptions(*b, *m_sim, *m_config);
buildRecipeSelectionOptions(type, *m_sim, *m_config);
const RecipeSelectionOption* current = nullptr;
for (const RecipeSelectionOption& option : options)
{
if (option.id == b->recipeId)
if (option.id == recipeId)
{
current = &option;
break;
@@ -306,7 +284,7 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
}
else
{
const QString placeholder = (b->type == BuildingType::Shipyard)
const QString placeholder = (type == BuildingType::Shipyard)
? tr("Select schematic")
: tr("Select recipe");
m_recipeSelectButton->setText(placeholder);
@@ -314,15 +292,15 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
}
m_recipeSelectButton->show();
if (b->type == BuildingType::Shipyard && !b->recipeId.empty())
if (type == BuildingType::Shipyard && !recipeId.empty())
{
const ShipDef* sDef = findShipDef(b->recipeId);
const ShipDef* sDef = findShipDef(recipeId);
if (sDef && !sDef->layout.empty())
{
ShipLayoutConfig layout;
if (b->shipLayout.has_value())
if (shipLayout.has_value())
{
layout = *b->shipLayout;
layout = *shipLayout;
}
m_layoutPreview->setShipAndLayout(
sDef->layout, layout, &m_config->modules.modules);
@@ -348,7 +326,9 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
m_configureLayoutBtn->hide();
}
if (isBeltLike(b->type))
// 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)
{
m_clearBeltBtn->show();
}
@@ -357,10 +337,19 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
m_clearBeltBtn->hide();
}
if (b->type == BuildingType::Splitter)
if (type == BuildingType::Splitter)
{
m_splitterTile = b->anchor;
buildSplitterFilters(m_splitterTile);
std::optional<BeltSystem::SplitterInfo> info;
if (m_singleIsSite)
{
info = m_sim->buildings().getSiteSplitterInfo(id);
}
else
{
m_splitterTile = anchor;
info = m_sim->belts().getSplitterInfo(m_splitterTile);
}
buildSplitterFilters(info);
}
else
{
@@ -370,7 +359,39 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
m_filterBList->hide();
}
refreshBuffers(b);
if (m_singleIsSite)
{
QString progress;
if (s->completesAt == 0)
{
progress = tr("Queued");
}
else
{
const BuildingDef* def = nullptr;
for (const BuildingDef& d : m_config->buildings.buildings)
{
if (d.type == s->type) { def = &d; break; }
}
if (def && def->constructionTimeSeconds > 0)
{
const Tick duration = secondsToTicks(def->constructionTimeSeconds);
const Tick elapsed = m_sim->currentTick() - (s->completesAt - duration);
const int pct = static_cast<int>(
std::max(Tick(0), std::min(duration, elapsed)) * 100 / duration);
progress = tr("%1% complete").arg(pct);
}
else
{
progress = tr("Building...");
}
}
m_buffersLabel->setText(progress);
}
else
{
refreshBuffers(b);
}
}
void SelectedBuildingPanel::refreshBuffers(const Building* b)
@@ -632,10 +653,9 @@ void SelectedBuildingPanel::onSelectRecipeClicked()
rebuild();
}
void SelectedBuildingPanel::buildSplitterFilters(QPoint splitterTile)
void SelectedBuildingPanel::buildSplitterFilters(
const std::optional<BeltSystem::SplitterInfo>& info)
{
const std::optional<BeltSystem::SplitterInfo> info =
m_sim->belts().getSplitterInfo(splitterTile);
if (!info.has_value())
{
m_filterALabel->hide();
@@ -698,10 +718,20 @@ void SelectedBuildingPanel::onSplitterFilterChanged()
return filter;
};
m_sim->belts().setSplitterFilters(
m_splitterTile,
collectFilter(m_filterAList),
collectFilter(m_filterBList));
if (m_singleIsSite)
{
m_sim->buildings().setSiteSplitterFilters(
m_singleBuildingId,
collectFilter(m_filterAList),
collectFilter(m_filterBList));
}
else
{
m_sim->belts().setSplitterFilters(
m_splitterTile,
collectFilter(m_filterAList),
collectFilter(m_filterBList));
}
}
std::vector<std::string> SelectedBuildingPanel::allItemIds() const