Fix shipyard layout preview/button not showing until re-selection
Selecting a ship schematic in the shipyard left the layout preview and Configure Layout button hidden until the building was deselected and re-selected. The recipe change is applied via a queued command that only drains on a later frame, so the immediate rebuild() in onSelectRecipeClicked() still saw the old (empty) recipe and hid both widgets. The per-tick refreshBuffers() path then updated the preview's data but never set its visibility -- that was only ever done in buildSingle() -- so the widgets stayed hidden until a re-selection re-ran buildSingle(). Extract the shipyard preview/button show-hide-and-populate logic into updateShipyardLayoutWidgets() and call it from both buildSingle() and refreshBuffers(), so the per-tick refresh becomes authoritative for visibility and the widgets appear on the first tick after the command drains. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DyCu8vwChKMbLJQ3xosYEN
This commit is contained in:
@@ -294,38 +294,12 @@ void SelectedBuildingPanel::buildSingle(BuildingId id)
|
|||||||
}
|
}
|
||||||
m_recipeSelectButton->show();
|
m_recipeSelectButton->show();
|
||||||
|
|
||||||
if (type == BuildingType::Shipyard && !recipeId.empty())
|
updateShipyardLayoutWidgets(type, recipeId, shipLayout);
|
||||||
{
|
|
||||||
const ShipDef* sDef = findShipDef(recipeId);
|
|
||||||
if (sDef && !sDef->layout.empty())
|
|
||||||
{
|
|
||||||
ShipLayoutConfig layout;
|
|
||||||
if (shipLayout.has_value())
|
|
||||||
{
|
|
||||||
layout = *shipLayout;
|
|
||||||
}
|
|
||||||
m_layoutPreview->setShipAndLayout(
|
|
||||||
sDef->layout, layout, &m_config->modules.modules);
|
|
||||||
m_layoutPreview->show();
|
|
||||||
m_configureLayoutBtn->show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_layoutPreview->hide();
|
|
||||||
m_configureLayoutBtn->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_layoutPreview->hide();
|
|
||||||
m_configureLayoutBtn->hide();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_recipeSelectButton->hide();
|
m_recipeSelectButton->hide();
|
||||||
m_layoutPreview->hide();
|
updateShipyardLayoutWidgets(type, recipeId, shipLayout);
|
||||||
m_configureLayoutBtn->hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Belt "Clear" removes items from a live belt tile; a construction site has
|
// Belt "Clear" removes items from a live belt tile; a construction site has
|
||||||
@@ -530,15 +504,38 @@ void SelectedBuildingPanel::refreshBuffers(const Building* b)
|
|||||||
|
|
||||||
m_buffersLabel->setText(bufText);
|
m_buffersLabel->setText(bufText);
|
||||||
|
|
||||||
if (b->type == BuildingType::Shipyard && shipDef && !shipDef->layout.empty())
|
// The recipe/schematic is applied via a queued command that only drains on a
|
||||||
|
// later frame, so the per-tick refresh must own the shipyard preview and the
|
||||||
|
// Configure Layout button's visibility; otherwise they stay hidden until the
|
||||||
|
// building is re-selected (which re-runs buildSingle).
|
||||||
|
updateShipyardLayoutWidgets(b->type, b->recipeId, b->shipLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectedBuildingPanel::updateShipyardLayoutWidgets(
|
||||||
|
BuildingType type,
|
||||||
|
const std::string& recipeId,
|
||||||
|
const std::optional<ShipLayoutConfig>& shipLayout)
|
||||||
|
{
|
||||||
|
const ShipDef* shipDef = (type == BuildingType::Shipyard)
|
||||||
|
? findShipDef(recipeId)
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
if (shipDef && !shipDef->layout.empty())
|
||||||
{
|
{
|
||||||
ShipLayoutConfig layout;
|
ShipLayoutConfig layout;
|
||||||
if (b->shipLayout.has_value())
|
if (shipLayout.has_value())
|
||||||
{
|
{
|
||||||
layout = *b->shipLayout;
|
layout = *shipLayout;
|
||||||
}
|
}
|
||||||
m_layoutPreview->setShipAndLayout(
|
m_layoutPreview->setShipAndLayout(
|
||||||
shipDef->layout, layout, &m_config->modules.modules);
|
shipDef->layout, layout, &m_config->modules.modules);
|
||||||
|
m_layoutPreview->show();
|
||||||
|
m_configureLayoutBtn->show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_layoutPreview->hide();
|
||||||
|
m_configureLayoutBtn->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,9 +644,11 @@ void SelectedBuildingPanel::onSelectRecipeClicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The emit is synchronous: MainWindow pauses the game, runs the modal
|
// The emit is synchronous: MainWindow pauses the game, runs the modal
|
||||||
// selection dialog, applies the chosen recipe/schematic, and restores the
|
// selection dialog, and restores the speed before this returns. The chosen
|
||||||
// speed before this returns. rebuild() then refreshes the button caption,
|
// recipe/schematic is only *enqueued* as a command, though, and drains on a
|
||||||
// tooltip, preview, and buffers for the new selection.
|
// later frame -- so this rebuild() still sees the old recipe. The per-tick
|
||||||
|
// refreshBuffers() path picks up the new schematic (and shows the layout
|
||||||
|
// preview + Configure Layout button) once the command has been applied.
|
||||||
EventManager::getInstance()->sendEventImmediately(
|
EventManager::getInstance()->sendEventImmediately(
|
||||||
std::make_shared<RecipeSelectionRequestedEvent>(m_singleBuildingId));
|
std::make_shared<RecipeSelectionRequestedEvent>(m_singleBuildingId));
|
||||||
rebuild();
|
rebuild();
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ private:
|
|||||||
void buildSingle(BuildingId id);
|
void buildSingle(BuildingId id);
|
||||||
void buildMulti(const std::vector<BuildingId>& ids);
|
void buildMulti(const std::vector<BuildingId>& ids);
|
||||||
void refreshBuffers(const Building* b);
|
void refreshBuffers(const Building* b);
|
||||||
|
void updateShipyardLayoutWidgets(BuildingType type,
|
||||||
|
const std::string& recipeId,
|
||||||
|
const std::optional<ShipLayoutConfig>& shipLayout);
|
||||||
void buildSplitterFilters(const std::optional<BeltSystem::SplitterInfo>& info);
|
void buildSplitterFilters(const std::optional<BeltSystem::SplitterInfo>& info);
|
||||||
const RecipeDef* findRecipe(const Building* b) const;
|
const RecipeDef* findRecipe(const Building* b) const;
|
||||||
const ShipDef* findShipDef(const std::string& id) const;
|
const ShipDef* findShipDef(const std::string& id) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user