Files
dota_factory/src/ui/BlueprintPanel.h
Malte Langkabel 388d354e51 Use std::optional instead of sentinel values for absent data
Replace sentinel values that signalled "no value" with std::optional
across simulation, UI, and balancing code:

- BuildingId references: DeliverScrapBehavior::deliveryBay,
  Simulation::m_hqBuildingId, the return types of BuildingSystem::place
  and Simulation::tryPlaceBuilding (previously kInvalidBuildingId on
  failure), GameWorldView building/site-at-tile lookups and demolish
  hover, SelectedBuildingPanel::m_singleBuildingId.
- Command id fields: the five id-carrying commands now hold
  optional<BuildingId>; CommandSerializer and Simulation::apply updated.
  The serialized replay format is unchanged.
- Index sentinels: BlueprintPanel::m_activeIndex,
  BalancingWindow::m_inspectedArenaIndex, ArenaSimulation winnerTeam,
  and the moduleIndex grid cells in ShipLayoutDialog/ShipLayoutPreview.
  ShipLayoutDialog::m_activeModuleIndex was a tri-state, so it is
  modelled as bool m_removeMode + optional<int>.

Building/ConstructionSite id defaults keep kInvalidBuildingId (identity,
not an absent reference); entt::null and config -1 domain values are
left as-is.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7N59FsLA5e2kuVdqe4Uhc
2026-07-20 07:36:34 +02:00

67 lines
2.2 KiB
C++

#pragma once
#include <optional>
#include <vector>
#include <QWidget>
#include "Blueprint.h"
#include "BlueprintModeExitedEvent.h"
#include "BuildingBlocksChangedEvent.h"
#include "BuildingId.h"
#include "EventHandler.h"
#include "GameConfig.h"
#include "SelectionChangedEvent.h"
#include "TemporaryBlueprintRequestedEvent.h"
#include "Tick.h"
class Simulation;
class QPushButton;
class QScrollArea;
class QVBoxLayout;
class BlueprintPanel : public QWidget,
public CombinedEventHandler<BuildingBlocksChangedEvent,
SelectionChangedEvent,
BlueprintModeExitedEvent,
TemporaryBlueprintRequestedEvent>
{
Q_OBJECT
public:
BlueprintPanel(Simulation* sim, const GameConfig* config, QWidget* parent = nullptr);
~BlueprintPanel() override;
private:
void handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> event) override;
void handleEvent(std::shared_ptr<const SelectionChangedEvent> event) override;
void handleEvent(std::shared_ptr<const BlueprintModeExitedEvent> event) override;
void handleEvent(std::shared_ptr<const TemporaryBlueprintRequestedEvent> event) override;
private slots:
void onCreateClicked();
void onDeleteBlueprintClicked(int index);
void onBlueprintButtonClicked(int index);
private:
void onSelectionChanged(const std::vector<BuildingId>& ids);
void clearActiveBlueprintButton();
Blueprint createBlueprintFromSelection() const;
int computeBlueprintCost(const Blueprint& bp) const;
void rebuildButtons();
void refreshButtonStates();
void loadFromDisk();
void saveToDisk() const;
Simulation* m_sim;
const GameConfig* m_config;
std::vector<BuildingId> m_selectedBuildingIds;
int m_currentBlocks;
std::optional<int> m_activeIndex; // nullopt = no blueprint selected
std::vector<Blueprint> m_blueprints;
std::vector<QPushButton*> m_blueprintButtons;
QPushButton* m_createBtn;
QWidget* m_buttonsContainer;
QVBoxLayout* m_buttonsLayout;
};