107 lines
4.6 KiB
C++
107 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
#include <QString>
|
|
|
|
#include "Blueprint.h"
|
|
#include "BlueprintModeExitedEvent.h"
|
|
#include "BuildingId.h"
|
|
#include "EventHandler.h"
|
|
#include "GameConfig.h"
|
|
#include "GameResetEvent.h"
|
|
#include "SelectionChangedEvent.h"
|
|
#include "TemporaryBlueprintCaptureRequestedEvent.h"
|
|
#include "TemporaryBlueprintPlaceRequestedEvent.h"
|
|
|
|
class Simulation;
|
|
class QWidget;
|
|
|
|
// The player's saved blueprints: the list itself, its persistence (REQ-UI-BLUEPRINT-SAVE,
|
|
// REQ-UI-BLUEPRINT-LOAD), capture from the current selection (REQ-UI-BLUEPRINT-CREATE,
|
|
// REQ-UI-BLUEPRINT-TEMP), and entry into blueprint placement mode.
|
|
//
|
|
// Deliberately not a widget: blueprints have no permanent place on screen any more
|
|
// (REQ-UI-BLUEPRINT-DIALOG), and the modal dialogs that present them must be driven from
|
|
// MainWindow, the only widget that can pause the game (ModalPauseScope) and raise the dim
|
|
// overlay. This class is the model those dialogs read and mutate.
|
|
class BlueprintLibrary
|
|
: public CombinedEventHandler<SelectionChangedEvent,
|
|
BlueprintModeExitedEvent,
|
|
TemporaryBlueprintCaptureRequestedEvent,
|
|
TemporaryBlueprintPlaceRequestedEvent,
|
|
GameResetEvent>
|
|
{
|
|
public:
|
|
// dialogParent parents the load-failure message box (REQ-UI-BLUEPRINT-LOAD) and is
|
|
// not owned.
|
|
BlueprintLibrary(Simulation* sim, const GameConfig* config, QWidget* dialogParent);
|
|
~BlueprintLibrary();
|
|
|
|
// True when the current selection holds at least one player-placeable building or
|
|
// construction site -- the condition under which Ctrl+C has any effect
|
|
// (REQ-UI-BLUEPRINT-CREATE).
|
|
bool getCanCaptureSelection() const;
|
|
|
|
// True once C has captured something -- the condition under which V does anything
|
|
// (REQ-UI-BLUEPRINT-TEMP), and so the condition under which the controls panel
|
|
// offers it (REQ-UI-CONTROLS-ACCURACY).
|
|
bool getHasTemporaryBlueprint() const;
|
|
|
|
// Captures the current selection under the given name and appends it to the list.
|
|
// Silently does nothing when nothing player-placeable is selected.
|
|
void saveSelectionAs(const QString& name);
|
|
|
|
const std::vector<Blueprint>& getBlueprints() const;
|
|
|
|
// The blueprint's contents line, ready for its card: one "<name> x <count>" entry
|
|
// per building type, comma-separated, ordered by summarizeBlueprintContents
|
|
// (REQ-UI-BLUEPRINT-CARD).
|
|
QString getContentsSummary(int index) const;
|
|
|
|
// Sum of the constituent buildings' placement costs (REQ-UI-BLUEPRINT-CARD).
|
|
int getCost(int index) const;
|
|
|
|
// Whether the player can currently afford the blueprint's total cost, which is what
|
|
// enables or greys out its card (REQ-UI-BLUEPRINT-CARD).
|
|
bool getCanAfford(int index) const;
|
|
|
|
// Removes the blueprint, exiting blueprint placement mode if it was the active one
|
|
// (REQ-UI-BLUEPRINT-DELETE).
|
|
void remove(int index);
|
|
|
|
// Enters blueprint placement mode for the blueprint (REQ-UI-BLUEPRINT-MODE).
|
|
void beginPlacement(int index);
|
|
|
|
private:
|
|
void handleEvent(std::shared_ptr<const SelectionChangedEvent> event) override;
|
|
void handleEvent(std::shared_ptr<const BlueprintModeExitedEvent> event) override;
|
|
void handleEvent(
|
|
std::shared_ptr<const TemporaryBlueprintCaptureRequestedEvent> event) override;
|
|
void handleEvent(
|
|
std::shared_ptr<const TemporaryBlueprintPlaceRequestedEvent> event) override;
|
|
void handleEvent(std::shared_ptr<const GameResetEvent> event) override;
|
|
|
|
Blueprint createBlueprintFromSelection() const;
|
|
void loadFromDisk();
|
|
void saveToDisk() const;
|
|
|
|
// The simulation is the single source of truth for the block stock and the
|
|
// selection; the change events are only refresh signals.
|
|
Simulation* m_sim;
|
|
const GameConfig* m_config;
|
|
QWidget* m_dialogParent;
|
|
std::vector<BuildingId> m_selectedBuildingIds;
|
|
std::vector<Blueprint> m_blueprints;
|
|
// Index of the blueprint currently in placement mode, so deleting it can exit that
|
|
// mode (REQ-UI-BLUEPRINT-DELETE). nullopt = no saved blueprint is being placed.
|
|
std::optional<int> m_activeIndex;
|
|
// The one unnamed blueprint captured with C and re-placed with V
|
|
// (REQ-UI-BLUEPRINT-TEMP). Deliberately kept out of m_blueprints: it is never named,
|
|
// never listed in the selection dialog, and never written to blueprints.toml. It
|
|
// outlives its placement mode, so V can re-enter it. nullopt = none captured since
|
|
// startup or the last restart.
|
|
std::optional<Blueprint> m_temporaryBlueprint;
|
|
};
|