#include "ShipyardContent.h" #include #include #include "Building.h" #include "BuildingTarget.h" #include "EventManager.h" #include "GameConfig.h" #include "LayoutDialogRequestedEvent.h" #include "ProductionRules.h" #include "RecipeSelectionControl.h" #include "SelectionNames.h" #include "ShipLayoutPreview.h" ShipyardContent::ShipyardContent(const SelectionContext& context, const SelectionRequest& request, QWidget* parent) : BufferedBuildingContent(context, request.buildings.front(), parent) { m_schematicControl = new RecipeSelectionControl(context, getBuildingId(), BuildingType::Shipyard, this); m_layoutPreview = new ShipLayoutPreview(this); m_configureButton = new QPushButton(tr("Configure Layout"), this); getConfigurationLayout()->addWidget(m_schematicControl); getConfigurationLayout()->addWidget(m_layoutPreview); getConfigurationLayout()->addWidget(m_configureButton); const BuildingId id = getBuildingId(); connect(m_configureButton, &QPushButton::clicked, this, [id]() { EventManager::getInstance()->sendEventImmediately( std::make_shared(id)); }); } void ShipyardContent::refreshConfiguration() { const BuildingTarget target = resolveBuildingTarget(getContext(), getBuildingId()); if (!target.isValid()) { return; } setBuildingIdentity(target.type, getBuildingTypeName(target.type)); m_schematicControl->setRecipeId(target.recipeId); // The preview and Configure button are always shown for a shipyard and are only // enabled once a schematic is selected (REQ-MOD-UI-PREVIEW). The schematic arrives // by queued command, so this refresh is what picks it up rather than the click that // chose it. const ShipDef* shipDef = target.recipeId.empty() ? nullptr : getContext().config->ships.findShipDef(target.recipeId); const bool hasSchematic = shipDef && !shipDef->layout.empty(); if (hasSchematic) { m_layoutPreview->setShipAndLayout( shipDef->layout, target.shipLayout.has_value() ? *target.shipLayout : ShipLayoutConfig(), &getContext().config->modules); } else { m_layoutPreview->showPlaceholder(); } m_layoutPreview->setEnabled(hasSchematic); m_configureButton->setEnabled(hasSchematic); } BufferedBuildingContent::CycleInfo ShipyardContent::getCycleInfo( const Building& building) const { CycleInfo info; const ShipDef* shipDef = building.recipeId.empty() ? nullptr : getContext().config->ships.findShipDef(building.recipeId); if (!shipDef) { return info; } // The schematic's materials plus every placed module's, which is also what sized the // input buffers (REQ-BLD-SHIPYARD). The simulation owns that sum, so the panel asks // it rather than adding the modules up a second time. info.perCycleInputs = computeShipyardRequiredMaterials(*getContext().config, building); info.durationSeconds = shipDef->schematic.productionTimeSeconds; if (building.shipLayout.has_value()) { for (const PlacedModule& placed : building.shipLayout->placedModules) { const ModuleDef* moduleDef = getContext().config->modules.findModuleDef(placed.moduleId); if (moduleDef) { info.durationSeconds += moduleDef->productionTimeSeconds; } } } info.runsProduction = true; return info; }