add FieldSelectionPanel for the ships/stations/debris selection

SelectedBuildingPanel has grown to 1200 lines by carrying two unrelated
selection categories. Introduce the field half as its own widget first,
so the cut-over is a separate, reviewable step.

The panel owns only its own selection state and widgets: it renders the
single-object stats panel (ship, station, debris) or the multi-object
count summary, subscribes to the tick/commands-applied refresh signals
and the debug-draw toggle, and hides itself while it has no selection.
Which category owns the side panel is not its decision - the parent
feeds it through setSelectedEntities/setSelectedDebris/clearSelection.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHcUerKAZKWNvSKJxYKbnG
This commit is contained in:
2026-08-04 15:42:25 +02:00
parent 622447c45b
commit 0029236135
3 changed files with 496 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
#pragma once
#include <vector>
#include <QString>
#include <QWidget>
#include "entt/entity/entity.hpp"
#include "DebugDrawToggledEvent.h"
#include "EventHandler.h"
#include "PlayerCommandsAppliedEvent.h"
#include "TickAdvancedEvent.h"
struct GameConfig;
class Simulation;
class ShipStatsPanel;
class QLabel;
class QVBoxLayout;
// Renders the "field" selection category — ships, defence stations and debris — as either
// a single-object stats panel (ship, station, or debris) or a compact multi-object count
// summary (REQ-UI-SELECTION-CATEGORIES, REQ-UI-FIELD-MULTI-SELECTION, REQ-UI-DEBRIS-PANEL).
//
// The panel owns its own selection state and its own widgets, and nothing else. Which of
// the two selection categories owns the side panel is arbitrated by the parent
// SelectedBuildingPanel: it feeds this panel through setSelectedEntities() /
// setSelectedDebris() / clearSelection() and asks it via hasSelection(). This panel hides
// itself whenever its selection is empty, so an inactive field category takes no space.
class FieldSelectionPanel : public QWidget,
public CombinedEventHandler<TickAdvancedEvent,
PlayerCommandsAppliedEvent,
DebugDrawToggledEvent>
{
Q_OBJECT
public:
FieldSelectionPanel(Simulation* sim, const GameConfig* config,
QWidget* parent = nullptr);
~FieldSelectionPanel() override;
// Replaces the selected actors (ships and defence stations); debris is left alone,
// the two coexist within the field category (REQ-UI-SELECTION-CATEGORIES).
void setSelectedEntities(const std::vector<entt::entity>& entities);
// Replaces the selected debris; the selected actors are left alone.
void setSelectedDebris(const std::vector<entt::entity>& debris);
// Drops the whole field selection — used when the building category takes over.
void clearSelection();
// True while the field category has anything selected, i.e. while this panel owns
// the side panel's content.
bool hasSelection() const;
private:
void handleEvent(std::shared_ptr<const TickAdvancedEvent> event) override;
void handleEvent(std::shared_ptr<const PlayerCommandsAppliedEvent> event) override;
void handleEvent(std::shared_ptr<const DebugDrawToggledEvent> event) override;
// Picks the layout for the current selection and shows/hides this panel accordingly.
void rebuild();
// Keeps the live values of the layout chosen by rebuild() current.
void refreshDisplay();
void buildEntityShip(entt::entity entity);
void buildEntityStation(entt::entity entity);
void buildEntitySummary();
void buildDebrisSingle();
void refreshEntityStats();
void hideAllWidgets();
// Summed remaining scrap across the selected debris (REQ-UI-DEBRIS-PANEL).
int selectedDebrisScrapTotal() const;
// "Scrap x N" line for the multi-object summary (REQ-UI-FIELD-MULTI-SELECTION).
QString scrapTotalText() const;
Simulation* m_sim;
const GameConfig* m_config;
bool m_debugDraw = false;
// The selected ships/defence stations. Shares the "field" selection category with
// debris (m_selectedDebris): both can be non-empty at once (REQ-UI-SELECTION-CATEGORIES).
std::vector<entt::entity> m_selectedEntities;
std::vector<entt::entity> m_selectedDebris;
QVBoxLayout* m_layout;
QLabel* m_entityTitleLabel;
ShipStatsPanel* m_entityStatsPanel;
QLabel* m_stationStatsLabel;
QLabel* m_entitySummaryLabel;
// Shows the debris "Scrap" stat row (single selection) — the scrap total for the
// multi-object summary lives in m_entitySummaryLabel instead.
QLabel* m_scrapLabel;
};