Auto-open layout dialog when a new shipyard schematic is selected
Implement REQ-MOD-UI-AUTO-DIALOG: picking a new schematic for a shipyard via the manual selection dialog now opens the layout configuration dialog immediately. Only triggers on an actual schematic change; copy-settings and blueprint placement are unaffected. Extract the ShipLayoutDialog-opening logic into a reusable MainWindow::openShipLayoutDialog helper. Because SetRecipeCommand is queued and clears the layout, the auto-open passes the chosen schematic and an empty layout explicitly rather than reading stale building state. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DZR44tA8sn4dPqDzAVXyps
This commit is contained in:
@@ -220,33 +220,13 @@ void MainWindow::handleEvent(std::shared_ptr<const EscapeMenuRequestedEvent> /*e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::handleEvent(std::shared_ptr<const LayoutDialogRequestedEvent> event)
|
void MainWindow::openShipLayoutDialog(BuildingId shipyardId,
|
||||||
|
const std::string& schematicId,
|
||||||
|
const ShipLayoutConfig& currentLayout)
|
||||||
{
|
{
|
||||||
const double prevSpeed = m_gameWorldView->gameSpeed();
|
const double prevSpeed = m_gameWorldView->gameSpeed();
|
||||||
m_gameWorldView->setGameSpeed(0.0);
|
m_gameWorldView->setGameSpeed(0.0);
|
||||||
|
|
||||||
// A construction site has no Building yet; fall back to its site record so
|
|
||||||
// the shipyard layout can be configured before it is built (REQ-BLD-SITE-CONFIG).
|
|
||||||
const Building* b = m_sim->buildings().findBuilding(event->shipyardId);
|
|
||||||
const ConstructionSite* s =
|
|
||||||
b ? nullptr : m_sim->buildings().findSite(event->shipyardId);
|
|
||||||
if (!b && !s)
|
|
||||||
{
|
|
||||||
m_gameWorldView->setGameSpeed(prevSpeed);
|
|
||||||
m_gameWorldView->resetFrameTimer();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& schematicId = b ? b->recipeId : s->recipeId;
|
|
||||||
const std::optional<ShipLayoutConfig>& layoutOpt =
|
|
||||||
b ? b->shipLayout : s->shipLayout;
|
|
||||||
|
|
||||||
ShipLayoutConfig currentLayout;
|
|
||||||
if (layoutOpt.has_value())
|
|
||||||
{
|
|
||||||
currentLayout = *layoutOpt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<std::string> unlockedModuleIds;
|
std::set<std::string> unlockedModuleIds;
|
||||||
for (const ModuleDef& def : m_sim->config().modules.modules)
|
for (const ModuleDef& def : m_sim->config().modules.modules)
|
||||||
{
|
{
|
||||||
@@ -265,7 +245,7 @@ void MainWindow::handleEvent(std::shared_ptr<const LayoutDialogRequestedEvent> e
|
|||||||
{
|
{
|
||||||
std::shared_ptr<SetShipLayoutCommand> command =
|
std::shared_ptr<SetShipLayoutCommand> command =
|
||||||
std::make_shared<SetShipLayoutCommand>();
|
std::make_shared<SetShipLayoutCommand>();
|
||||||
command->id = event->shipyardId;
|
command->id = shipyardId;
|
||||||
command->layout = *dialog.result();
|
command->layout = *dialog.result();
|
||||||
EventManager::getInstance()->sendEventImmediately(
|
EventManager::getInstance()->sendEventImmediately(
|
||||||
std::make_shared<CommandRequestedEvent>(command));
|
std::make_shared<CommandRequestedEvent>(command));
|
||||||
@@ -275,6 +255,31 @@ void MainWindow::handleEvent(std::shared_ptr<const LayoutDialogRequestedEvent> e
|
|||||||
m_gameWorldView->resetFrameTimer();
|
m_gameWorldView->resetFrameTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::handleEvent(std::shared_ptr<const LayoutDialogRequestedEvent> event)
|
||||||
|
{
|
||||||
|
// A construction site has no Building yet; fall back to its site record so
|
||||||
|
// the shipyard layout can be configured before it is built (REQ-BLD-SITE-CONFIG).
|
||||||
|
const Building* b = m_sim->buildings().findBuilding(event->shipyardId);
|
||||||
|
const ConstructionSite* s =
|
||||||
|
b ? nullptr : m_sim->buildings().findSite(event->shipyardId);
|
||||||
|
if (!b && !s)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& schematicId = b ? b->recipeId : s->recipeId;
|
||||||
|
const std::optional<ShipLayoutConfig>& layoutOpt =
|
||||||
|
b ? b->shipLayout : s->shipLayout;
|
||||||
|
|
||||||
|
ShipLayoutConfig currentLayout;
|
||||||
|
if (layoutOpt.has_value())
|
||||||
|
{
|
||||||
|
currentLayout = *layoutOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
openShipLayoutDialog(event->shipyardId, schematicId, currentLayout);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent> event)
|
void MainWindow::handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent> event)
|
||||||
{
|
{
|
||||||
const double prevSpeed = m_gameWorldView->gameSpeed();
|
const double prevSpeed = m_gameWorldView->gameSpeed();
|
||||||
@@ -293,12 +298,18 @@ void MainWindow::handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
const BuildingType type = b ? b->type : s->type;
|
const BuildingType type = b ? b->type : s->type;
|
||||||
|
// Captured as a copy: a queued command may drain during the modal dialog's
|
||||||
|
// event loop and reallocate the building vectors, so b/s must not be
|
||||||
|
// dereferenced after dialog.exec() returns.
|
||||||
|
const std::string oldSchematic = b ? b->recipeId : s->recipeId;
|
||||||
const std::vector<RecipeSelectionOption> options =
|
const std::vector<RecipeSelectionOption> options =
|
||||||
buildRecipeSelectionOptions(type, *m_sim, m_sim->config());
|
buildRecipeSelectionOptions(type, *m_sim, m_sim->config());
|
||||||
const QString title = (type == BuildingType::Shipyard)
|
const QString title = (type == BuildingType::Shipyard)
|
||||||
? tr("Select Schematic")
|
? tr("Select Schematic")
|
||||||
: tr("Select Recipe");
|
: tr("Select Recipe");
|
||||||
|
|
||||||
|
bool autoOpenLayout = false;
|
||||||
|
std::string chosenSchematic;
|
||||||
RecipeSelectionDialog dialog(options, title, this);
|
RecipeSelectionDialog dialog(options, title, this);
|
||||||
if (dialog.exec() == QDialog::Accepted && dialog.getChosenId().has_value())
|
if (dialog.exec() == QDialog::Accepted && dialog.getChosenId().has_value())
|
||||||
{
|
{
|
||||||
@@ -307,10 +318,27 @@ void MainWindow::handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent
|
|||||||
command->recipeId = *dialog.getChosenId();
|
command->recipeId = *dialog.getChosenId();
|
||||||
EventManager::getInstance()->sendEventImmediately(
|
EventManager::getInstance()->sendEventImmediately(
|
||||||
std::make_shared<CommandRequestedEvent>(command));
|
std::make_shared<CommandRequestedEvent>(command));
|
||||||
|
|
||||||
|
// REQ-MOD-UI-AUTO-DIALOG: picking a new schematic for a shipyard opens the
|
||||||
|
// layout configuration dialog immediately. Only on an actual change.
|
||||||
|
if (type == BuildingType::Shipyard && *dialog.getChosenId() != oldSchematic)
|
||||||
|
{
|
||||||
|
autoOpenLayout = true;
|
||||||
|
chosenSchematic = *dialog.getChosenId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_gameWorldView->setGameSpeed(prevSpeed);
|
m_gameWorldView->setGameSpeed(prevSpeed);
|
||||||
m_gameWorldView->resetFrameTimer();
|
m_gameWorldView->resetFrameTimer();
|
||||||
|
|
||||||
|
// The SetRecipeCommand above is queued (drains on a later frame) and clears
|
||||||
|
// the shipyard's layout, so open the dialog with the chosen schematic and an
|
||||||
|
// empty layout rather than reading the not-yet-updated building state. Speed
|
||||||
|
// is already restored so the helper snapshots the real speed to restore.
|
||||||
|
if (autoOpenLayout)
|
||||||
|
{
|
||||||
|
openShipLayoutDialog(event->buildingId, chosenSchematic, ShipLayoutConfig{});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::handleEvent(std::shared_ptr<const GameOverEvent> /*event*/)
|
void MainWindow::handleEvent(std::shared_ptr<const GameOverEvent> /*event*/)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "WinEvent.h"
|
#include "WinEvent.h"
|
||||||
#include "RecipeSelectionRequestedEvent.h"
|
#include "RecipeSelectionRequestedEvent.h"
|
||||||
#include "SchematicChoicesAvailableEvent.h"
|
#include "SchematicChoicesAvailableEvent.h"
|
||||||
|
#include "ShipLayout.h"
|
||||||
#include "ShipLayoutBlueprint.h"
|
#include "ShipLayoutBlueprint.h"
|
||||||
#include "Tick.h"
|
#include "Tick.h"
|
||||||
#include "VisualsConfig.h"
|
#include "VisualsConfig.h"
|
||||||
@@ -57,6 +58,12 @@ private:
|
|||||||
void handleEvent(std::shared_ptr<const EscapeMenuRequestedEvent> event) override;
|
void handleEvent(std::shared_ptr<const EscapeMenuRequestedEvent> event) override;
|
||||||
void handleEvent(std::shared_ptr<const LayoutDialogRequestedEvent> event) override;
|
void handleEvent(std::shared_ptr<const LayoutDialogRequestedEvent> event) override;
|
||||||
void handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent> event) override;
|
void handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent> event) override;
|
||||||
|
|
||||||
|
// Opens the shipyard layout configuration dialog for the given schematic and
|
||||||
|
// current layout, applying the result via SetShipLayoutCommand (REQ-MOD-UI-DIALOG).
|
||||||
|
void openShipLayoutDialog(BuildingId shipyardId,
|
||||||
|
const std::string& schematicId,
|
||||||
|
const ShipLayoutConfig& currentLayout);
|
||||||
void layoutPanels();
|
void layoutPanels();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user