#pragma once #include #include #include #include #include #include "entt/entity/entity.hpp" #include "BeltSystem.h" #include "Building.h" #include "BuildingId.h" #include "DebugDrawToggledEvent.h" #include "EntitySelectedEvent.h" #include "EventHandler.h" #include "GameConfig.h" #include "PlayerCommandsAppliedEvent.h" #include "RecipesConfig.h" #include "ScrapSelectionChangedEvent.h" #include "SelectionChangedEvent.h" #include "ShipLayout.h" #include "ShipsConfig.h" #include "Tick.h" #include "TickAdvancedEvent.h" class Simulation; class ShipLayoutPreview; class ShipStatsPanel; class QLabel; class QListWidget; class QPushButton; class QVBoxLayout; class SelectedBuildingPanel : public QWidget, public CombinedEventHandler { Q_OBJECT public: SelectedBuildingPanel(Simulation* sim, const GameConfig* config, QWidget* parent = nullptr); ~SelectedBuildingPanel() override; private: void handleEvent(std::shared_ptr event) override; void handleEvent(std::shared_ptr event) override; void handleEvent(std::shared_ptr event) override; void handleEvent(std::shared_ptr event) override; void handleEvent(std::shared_ptr event) override; void handleEvent(std::shared_ptr event) override; private slots: void onSelectRecipeClicked(); void onClearBelt(); void onSplitterFilterChanged(); private: // Why the selection display is being refreshed. A periodic tick only needs a // lightweight content update (e.g. a construction site's progress label), // whereas an applied player command may have changed the configuration and // needs a full structural rebuild. enum class RefreshReason { PeriodicTick, CommandApplied }; void onSelectionChanged(const std::vector& ids); void refreshSelectionDisplay(RefreshReason reason); void rebuild(); void hideAllWidgets(); void clearContent(); void buildEmpty(); void buildSingle(BuildingId id); void buildMulti(const std::vector& ids); void buildScrap(); void refreshScrapTotal(); void refreshBuffers(const Building* b); void refreshSiteProgress(const ConstructionSite* s); void updateShipyardLayoutWidgets(BuildingType type, const std::string& recipeId, const std::optional& shipLayout); void buildSplitterFilters(const std::optional& info); const RecipeDef* findRecipe(const Building* b) const; const ShipDef* findShipDef(const std::string& id) const; std::vector getAllItemIds() const; Simulation* m_sim; const GameConfig* m_config; std::vector m_selectedBuildingIds; QVBoxLayout* m_layout; QLabel* m_titleLabel; QPushButton* m_recipeSelectButton; QPushButton* m_clearBeltBtn; QLabel* m_filterALabel; QListWidget* m_filterAList; QLabel* m_filterBLabel; QListWidget* m_filterBList; QLabel* m_buffersLabel; ShipLayoutPreview* m_layoutPreview; QPushButton* m_configureLayoutBtn; BuildingId m_singleBuildingId; bool m_singleIsSite = false; // selected single entity is a construction site QPoint m_splitterTile; std::string m_currentRecipeId; bool m_debugDraw = false; std::optional m_selectedEntity; ShipStatsPanel* m_entityStatsPanel; QLabel* m_entityTitleLabel; QLabel* m_stationStatsLabel; std::vector m_selectedScrap; QLabel* m_scrapLabel; void buildEntityShip(entt::entity entity); void buildEntityStation(entt::entity entity); void refreshEntityStats(); void clearEntityDisplay(); };