Implements the REQ-UI-BUILD-BAR rewrite: the build buttons leave the side panel column for a widget floating at the bottom center of the game world view, as one non-wrapping row. BuildButtonGrid is renamed BuildButtonBar and its QGridLayout becomes a QHBoxLayout; the side panel column is left with two equal-height panels. Buttons become icon-only. Each face is composed into a single pixmap per QIcon mode - hotkey badge in the top-left corner, chip icon centered, cost and block icon below - because a QPushButton holds only one icon. That replaces the custom-painted BuildButton and lets Qt grey an unaffordable button by swapping the pixmap. The building name moves into the tooltip, which now always leads with it, and a missing chip SVG falls back to the name in the chip's place. The badge labels come from InputMapper, searched out of the same table the key handler uses so a badge cannot claim a key that does nothing. The Deconstruct button has no cost, so it shows its name there instead, and sits last behind a gap. Parenting the bar to MainWindow makes creation order the stacking order: it lands above the world view and its vignettes and below the modal dim, and Qt routes mouse events to it rather than the world, which is the whole input clause of REQ-UI-BUILD-BAR at no cost. Requirements are amended for the two things the mockup added: the hotkey badge and the Deconstruct caption. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
94 lines
3.5 KiB
C++
94 lines
3.5 KiB
C++
#pragma once
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <QWidget>
|
|
|
|
#include "BuildingId.h"
|
|
#include "EscapeMenuRequestedEvent.h"
|
|
#include "EventHandler.h"
|
|
#include "GameConfig.h"
|
|
#include "GameOverEvent.h"
|
|
#include "LayoutDialogRequestedEvent.h"
|
|
#include "ModalDimOverlay.h"
|
|
#include "WinEvent.h"
|
|
#include "RecipeSelectionRequestedEvent.h"
|
|
#include "SchematicChoicesAvailableEvent.h"
|
|
#include "ShipLayout.h"
|
|
#include "ShipLayoutBlueprint.h"
|
|
#include "Tick.h"
|
|
#include "VisualsConfig.h"
|
|
|
|
struct ParsedReplay;
|
|
class Simulation;
|
|
class GameWorldView;
|
|
class HeaderBar;
|
|
class SelectedBuildingPanel;
|
|
class BuildButtonBar;
|
|
class BlueprintPanel;
|
|
class ItemIconCache;
|
|
class QCloseEvent;
|
|
class QResizeEvent;
|
|
|
|
class MainWindow : public QWidget,
|
|
public CombinedEventHandler<SchematicChoicesAvailableEvent,
|
|
GameOverEvent,
|
|
WinEvent,
|
|
EscapeMenuRequestedEvent,
|
|
LayoutDialogRequestedEvent,
|
|
RecipeSelectionRequestedEvent>
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
MainWindow(Simulation* sim, const std::string& configDir,
|
|
std::shared_ptr<ParsedReplay> replay = nullptr, QWidget* parent = nullptr);
|
|
~MainWindow() override;
|
|
|
|
protected:
|
|
void resizeEvent(QResizeEvent* event) override;
|
|
void closeEvent(QCloseEvent* event) override;
|
|
|
|
private:
|
|
void handleEvent(std::shared_ptr<const SchematicChoicesAvailableEvent> event) override;
|
|
void handleEvent(std::shared_ptr<const GameOverEvent> event) override;
|
|
void handleEvent(std::shared_ptr<const WinEvent> 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 RecipeSelectionRequestedEvent> event) override;
|
|
|
|
// Reloads the game config and visuals.toml from disk (REQ-CFG-RELOAD), shared
|
|
// by every restart path. On success the reloaded visuals are applied to this
|
|
// window and the fresh GameConfig is returned; on failure a modal error dialog
|
|
// is shown and std::nullopt is returned, leaving the window state untouched.
|
|
std::optional<GameConfig> reloadConfig();
|
|
|
|
// 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();
|
|
|
|
private:
|
|
std::string m_configDir;
|
|
VisualsConfig m_visuals;
|
|
Simulation* m_sim;
|
|
// One per-item icon cache for the whole window (REQ-UI-ITEM-ICON): the header,
|
|
// build bar, world view, and recipe dialog all rasterize the same SVGs.
|
|
std::unique_ptr<ItemIconCache> m_itemIcons;
|
|
GameWorldView* m_gameWorldView;
|
|
HeaderBar* m_headerBar;
|
|
SelectedBuildingPanel* m_selectedBuildingPanel;
|
|
BuildButtonBar* m_buildButtonBar;
|
|
BlueprintPanel* m_blueprintPanel;
|
|
QWidget* m_sidePanel;
|
|
ModalDimOverlay* m_dimOverlay = nullptr;
|
|
|
|
std::vector<ShipLayoutBlueprint> m_layoutBlueprints;
|
|
std::shared_ptr<ParsedReplay> m_replay; // non-null => view-only playback
|
|
};
|