Fix recipe button unclickable on construction site during play

This commit is contained in:
2026-07-08 20:46:26 +02:00
parent e4ea4ca4b4
commit 808e0c6a7b
2 changed files with 58 additions and 31 deletions

View File

@@ -338,32 +338,7 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
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);
refreshSiteProgress(s);
}
else
{
@@ -371,6 +346,36 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
}
}
void SelectedBuildingPanel::refreshSiteProgress(const ConstructionSite* s)
{
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);
}
void SelectedBuildingPanel::refreshBuffers(const Building* b)
{
const RecipeDef* recipe = findRecipe(b);
@@ -562,7 +567,7 @@ const ShipDef* SelectedBuildingPanel::findShipDef(const std::string& id) const
void SelectedBuildingPanel::handleEvent(std::shared_ptr<const TickAdvancedEvent> /*event*/)
{
refreshSelectionDisplay();
refreshSelectionDisplay(RefreshReason::PeriodicTick);
}
void SelectedBuildingPanel::handleEvent(
@@ -572,10 +577,10 @@ void SelectedBuildingPanel::handleEvent(
// queued drain, not synchronously. When the game is paused no tick advances,
// so TickAdvancedEvent never fires; refresh here too, otherwise the panel
// would not reflect the change until the next tick or a re-selection.
refreshSelectionDisplay();
refreshSelectionDisplay(RefreshReason::CommandApplied);
}
void SelectedBuildingPanel::refreshSelectionDisplay()
void SelectedBuildingPanel::refreshSelectionDisplay(RefreshReason reason)
{
if (m_selectedEntity.has_value())
{
@@ -600,7 +605,18 @@ void SelectedBuildingPanel::refreshSelectionDisplay()
const ConstructionSite* s = m_sim->buildings().findSite(m_singleBuildingId);
if (s)
{
rebuild();
// A periodic tick only advances construction progress, so update just the
// progress label. Rebuilding every tick would hide/re-show all widgets and
// cancel any in-progress click on the recipe button. An applied command
// may have changed the site's recipe/layout, so rebuild in that case.
if (reason == RefreshReason::CommandApplied)
{
rebuild();
}
else
{
refreshSiteProgress(s);
}
return;
}
buildEmpty();