put the controls panel in the corner and let it step around the build bar
It was confined to the band above the build button bar's strip, borrowing the selection panel's rule. That rule exists because the selection panel is full-height on the right, where the bar's strip is genuinely in the way. This panel is short and in the corner, and the bar is centered and sized to its buttons, so the corner is normally free -- reserving the whole strip pushed the panel up for a collision that was not happening. It now sits in the bottom-left corner and shares the view's bottom edge with the bar, rising only when the panel's rectangle would actually intersect the bar's, in which case it clears the bar's top by the usual margin and caps its height at what is left. So it moves for a wide bar and a wide panel, and drops back into the corner as soon as they no longer meet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHcUerKAZKWNvSKJxYKbnG
This commit is contained in:
@@ -428,7 +428,7 @@ Any ship, module, building, or assembler recipe id that appears in no unlock gro
|
||||
|
||||
### Layout
|
||||
|
||||
The screen is a single column: a header bar across the top and the game world view filling the whole area below it. There is no side panel. All three permanent UI widgets float over the game world — the build button bar (REQ-UI-BUILD-BAR) at its bottom center, the selection panel (REQ-UI-SELECTION-PANEL) at its right edge, centered vertically within the height left above the build button bar and shown only while something is selected, and the controls panel (REQ-UI-CONTROLS-PANEL) at its left edge, bottom-aligned within that same height. Blueprints have no permanent screen real estate; they are reached through modal dialogs (REQ-UI-BLUEPRINT-DIALOG):
|
||||
The screen is a single column: a header bar across the top and the game world view filling the whole area below it. There is no side panel. All three permanent UI widgets float over the game world — the build button bar (REQ-UI-BUILD-BAR) at its bottom center, the selection panel (REQ-UI-SELECTION-PANEL) at its right edge, centered vertically within the height left above the build button bar and shown only while something is selected, and the controls panel (REQ-UI-CONTROLS-PANEL) in its bottom-left corner, beside the build button bar and rising above it only when the two would overlap. Blueprints have no permanent screen real estate; they are reached through modal dialogs (REQ-UI-BLUEPRINT-DIALOG):
|
||||
|
||||
```
|
||||
+-----------------------------------------------------------+
|
||||
@@ -438,11 +438,11 @@ The screen is a single column: a header bar across the top and the game world vi
|
||||
| | Selection | |
|
||||
| Game World | Panel | |
|
||||
| +-----------+ |
|
||||
| |
|
||||
| +----------+ |
|
||||
| | Controls | |
|
||||
| +----------+ +------------------+ |
|
||||
| | Build Button Bar | |
|
||||
+------------------+------------------+---------------------+
|
||||
| | Controls | +------------------+ |
|
||||
| | Panel | | Build Button Bar | |
|
||||
+-+----------+-----+------------------+---------------------+
|
||||
(full window width)
|
||||
```
|
||||
|
||||
@@ -614,7 +614,8 @@ The panel shows exactly one **content** at a time, picked from the catalog in RE
|
||||
|
||||
The controls panel tells the player which controls are available right now. It is context-sensitive: the game is always in exactly one **control context**, derived from the active build mode and the current selection, and the panel shows that context's rows and no others. Its position, size, and overlay behavior are defined in REQ-UI-CONTROLS-PANEL; its structure in REQ-UI-CONTROLS-CARD; and which rows each context shows in REQ-UI-CONTROLS-CONTENT. The panel never defines a binding: every row restates one already defined in REQ-UI-HOTKEYS or in the mouse gestures cited beside it.
|
||||
|
||||
- REQ-UI-CONTROLS-PANEL: The **controls panel** is a widget that **floats over the game world view** (REQ-UI-WORLD-SIZE), anchored to the view's **left edge** with a small margin and **bottom-aligned within the available band** — the same band the selection panel is placed against (REQ-UI-SELECTION-PANEL): the height of the game world view, less the panel's top and bottom margins, less the height of the horizontal strip occupied by the build button bar at the bottom of the view (the bar's height plus its bottom margin, REQ-UI-BUILD-BAR), the bar's strip being subtracted over the full view width regardless of how wide the bar currently is. Bottom-aligning within that band puts the panel just above the bar's strip, so the two never overlap whatever the bar's current width, and the bar never moves on the panel's account (REQ-UI-BUILD-BAR). The panel is **sized to its content in both width and height**, growing and shrinking upward from the band's bottom edge as the context changes. Should its content ever be taller than the band, the panel's height is capped at the band height and the content scrolls vertically within it. The panel and the selection panel are on opposite edges of the view and never overlap.
|
||||
- REQ-UI-CONTROLS-PANEL: The **controls panel** is a widget that **floats over the game world view** (REQ-UI-WORLD-SIZE), anchored to the view's **bottom-left corner** with a small margin on both edges. It is **sized to its content in both width and height**, growing and shrinking upward from that corner as the context changes. Should its content ever be taller than the view, the panel's height is capped at the view height less its margins and the content scrolls vertically within it. The panel and the selection panel are on opposite sides of the view and never overlap.
|
||||
- **Stepping around the build button bar.** Unlike the selection panel (REQ-UI-SELECTION-PANEL), the panel does **not** confine itself to the band above the build button bar's strip: the bar is horizontally centered and sized to its buttons (REQ-UI-BUILD-BAR), so it normally leaves this corner free, and the panel shares the view's bottom edge with it. The panel **rises only to avoid an actual overlap**: whenever the panel at the bottom-left corner would intersect the bar's current rectangle, it is moved up so that its bottom edge clears the bar's top by the same margin it keeps from the view's edges, and its height is capped at the space that leaves. Whether it rises therefore depends on how wide the bar and the panel currently are, and it returns to the corner as soon as they no longer meet. The bar never moves on the panel's account (REQ-UI-BUILD-BAR).
|
||||
- **Visibility.** The panel is shown whenever the game is being played. Unlike the selection panel it has no empty state (REQ-UI-EMPTY-SELECTION): every context has rows, so there is never nothing to show.
|
||||
- **Collapsing.** Clicking anywhere on the panel's header (REQ-UI-CONTROLS-CARD) toggles the panel between **expanded** and **collapsed**. Collapsed, it shows its header alone, keeping the context name visible and the header clickable so the panel can be expanded again; expanded, it shows the header followed by every row of the current context. The panel starts **expanded**. Changing context does not change the collapsed state: a panel collapsed in one context stays collapsed in the next, and its header updates in place. The collapsed state is presentation-only — it is not a player command, never enters the replay stream, and has no effect on the simulation. It persists for as long as the application runs, including across a restart from the escape menu (REQ-UI-GAME-MENU), and is not saved to disk.
|
||||
- **Overlay behavior.** As for the build button bar and the selection panel (REQ-UI-BUILD-BAR, REQ-UI-SELECTION-PANEL): the panel occludes the strip of the game world it covers; the world view itself keeps its full extent and the view's scrolling, ghost rendering, and tile geometry are unaffected. It is drawn above the pause and deconstruct vignettes (REQ-UI-PAUSE-BORDER, REQ-UI-DECONSTRUCT-BORDER), which keep their full left-hand band underneath it, and below the modal dim (REQ-UI-MODAL-DIM), which covers the entire game window including the panel.
|
||||
|
||||
@@ -139,9 +139,10 @@ ControlsPanel::ControlsPanel(const GameWorldView* view, QWidget* parent)
|
||||
refresh();
|
||||
}
|
||||
|
||||
void ControlsPanel::anchorTo(const QRect& bandRect)
|
||||
void ControlsPanel::anchorTo(const QRect& worldRect, const QRect& buildBarRect)
|
||||
{
|
||||
m_bandRect = bandRect;
|
||||
m_worldRect = worldRect;
|
||||
m_buildBarRect = buildBarRect;
|
||||
refit();
|
||||
}
|
||||
|
||||
@@ -258,7 +259,7 @@ QString ControlsPanel::getHeadingText(const ControlContext& context) const
|
||||
|
||||
void ControlsPanel::refit()
|
||||
{
|
||||
if (m_bandRect.isNull()) { return; }
|
||||
if (m_worldRect.isNull()) { return; }
|
||||
|
||||
// Rows are torn down and rebuilt wholesale, and a widget added to a layout is only
|
||||
// shown once that layout runs -- without this the new rows count for nothing and
|
||||
@@ -277,13 +278,26 @@ void ControlsPanel::refit()
|
||||
layout()->invalidate();
|
||||
const QSize needed = layout()->totalSizeHint();
|
||||
|
||||
const QRect band = m_bandRect.adjusted(kMarginPx, kMarginPx, -kMarginPx, -kMarginPx);
|
||||
const QRect band = m_worldRect.adjusted(kMarginPx, kMarginPx, -kMarginPx, -kMarginPx);
|
||||
if (band.width() <= 0 || band.height() <= 0) { return; }
|
||||
|
||||
// The bottom-left corner of the view, growing upward as rows are added
|
||||
// (REQ-UI-CONTROLS-PANEL).
|
||||
const int widthPx = qMin(needed.width(), band.width());
|
||||
const int heightPx = qMin(needed.height(), band.height());
|
||||
int heightPx = qMin(needed.height(), band.height());
|
||||
int topPx = band.bottom() - heightPx + 1;
|
||||
|
||||
// Left edge of the band, sitting on its bottom edge, so the panel grows upward as
|
||||
// rows are added (REQ-UI-CONTROLS-PANEL).
|
||||
setGeometry(band.left(), band.bottom() - heightPx + 1, widthPx, heightPx);
|
||||
// The build button bar is centered and sized to its buttons, so it usually leaves
|
||||
// this corner free and the panel can share the bottom edge with it. Only when the
|
||||
// two would actually overlap does the panel rise, clearing the bar's top by the
|
||||
// same margin it keeps from the view's edges (REQ-UI-BUILD-BAR).
|
||||
const QRect wanted(band.left(), topPx, widthPx, heightPx);
|
||||
if (!m_buildBarRect.isNull() && wanted.intersects(m_buildBarRect))
|
||||
{
|
||||
const int availablePx = m_buildBarRect.top() - kMarginPx - band.top();
|
||||
heightPx = qMin(heightPx, qMax(0, availablePx));
|
||||
topPx = m_buildBarRect.top() - kMarginPx - heightPx;
|
||||
}
|
||||
|
||||
setGeometry(band.left(), topPx, widthPx, heightPx);
|
||||
}
|
||||
|
||||
@@ -38,11 +38,13 @@ public:
|
||||
// selection.
|
||||
ControlsPanel(const GameWorldView* view, QWidget* parent = nullptr);
|
||||
|
||||
// Confines the panel to the given band of the game world view: it left-aligns
|
||||
// within it and sits on its bottom edge. The band is the world view less the strip
|
||||
// the build button bar occupies, so the two never overlap and the bar never has to
|
||||
// move (REQ-UI-CONTROLS-PANEL, REQ-UI-BUILD-BAR).
|
||||
void anchorTo(const QRect& bandRect);
|
||||
// Places the panel in the bottom-left corner of the game world view. It shares the
|
||||
// bottom edge with the build button bar rather than clearing its strip, the bar
|
||||
// being centered and sized to its buttons and so usually leaving the left free; it
|
||||
// rises above the bar only when the two would otherwise overlap. `buildBarRect` is
|
||||
// the bar's current geometry in the same coordinates, or a null rect when there is
|
||||
// none to avoid (REQ-UI-CONTROLS-PANEL, REQ-UI-BUILD-BAR).
|
||||
void anchorTo(const QRect& worldRect, const QRect& buildBarRect);
|
||||
|
||||
protected:
|
||||
// Clicking the heading collapses and expands the panel (REQ-UI-CONTROLS-PANEL).
|
||||
@@ -77,7 +79,8 @@ private:
|
||||
// command (REQ-UI-CONTROLS-PANEL).
|
||||
bool m_collapsed = false;
|
||||
|
||||
// The band the panel confines itself to, in the coordinates of its parent; null
|
||||
// until the owner has anchored it for the first time.
|
||||
QRect m_bandRect;
|
||||
// The world view the panel sits in, and the build button bar it steps around, both
|
||||
// in the coordinates of its parent. Null until the owner has anchored it.
|
||||
QRect m_worldRect;
|
||||
QRect m_buildBarRect;
|
||||
};
|
||||
|
||||
@@ -179,10 +179,11 @@ void MainWindow::layoutPanels()
|
||||
// move for it (REQ-UI-SELECTION-PANEL, REQ-UI-BUILD-BAR).
|
||||
m_selectionPanel->anchorTo(
|
||||
worldRect.adjusted(0, 0, 0, -m_buildButtonBar->getStripHeightPx()));
|
||||
// Same band, opposite edge: left and bottom-aligned, so it clears the bar's strip
|
||||
// too and never meets the selection panel (REQ-UI-CONTROLS-PANEL).
|
||||
m_controlsPanel->anchorTo(
|
||||
worldRect.adjusted(0, 0, 0, -m_buildButtonBar->getStripHeightPx()));
|
||||
// The opposite corner: bottom-left of the view, sharing the bottom edge with the
|
||||
// bar rather than clearing its whole strip, and rising only if the two would meet.
|
||||
// Anchored after the bar so the geometry it steps around is the current one
|
||||
// (REQ-UI-CONTROLS-PANEL).
|
||||
m_controlsPanel->anchorTo(worldRect, m_buildButtonBar->geometry());
|
||||
m_dimOverlay->setGeometry(0, 0, totalW, totalH);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user