float the build buttons as a horizontal bar over the game world and show key bindings inside build buttons

This commit is contained in:
2026-08-06 08:28:40 +02:00
parent f39fe9a118
commit c1af58d80c
14 changed files with 575 additions and 477 deletions

View File

@@ -15,7 +15,7 @@
#include <QVBoxLayout>
#include "BlueprintPanel.h"
#include "BuildButtonGrid.h"
#include "BuildButtonBar.h"
#include "BuildingSystem.h"
#include "Command.h"
#include "CommandRequestedEvent.h"
@@ -58,36 +58,43 @@ MainWindow::MainWindow(Simulation* sim, const std::string& configDir,
m_gameWorldView = new GameWorldView(sim, &sim->getConfig(), &m_visuals, m_configDir,
m_itemIcons.get(), m_replay.get(), this);
m_sidePanel = new QWidget(this);
QVBoxLayout* sideLayout = new QVBoxLayout(m_sidePanel);
sideLayout->setContentsMargins(1, 1, 1, 1);
sideLayout->setSpacing(1);
// Building icons live alongside the config (a sibling of the config dir), read
// from disk at runtime the same way visuals.toml is.
const std::string iconDir = QDir::cleanPath(
QString::fromStdString(m_configDir) + "/../icons/buildings").toStdString();
// Floats over the game world rather than living in the side panel column
// (REQ-UI-BUILD-BAR). Creation order is the stacking order for siblings, so
// building it after the world view puts it above the world and its vignettes,
// and before the dim overlay keeps modals dimming it too (REQ-UI-MODAL-DIM).
// Its geometry comes from layoutPanels().
m_buildButtonBar = new BuildButtonBar(sim, &sim->getConfig(), iconDir,
m_itemIcons.get(), this);
m_sidePanel = new QWidget(this);
QVBoxLayout* sideLayout = new QVBoxLayout(m_sidePanel);
sideLayout->setContentsMargins(1, 1, 1, 1);
sideLayout->setSpacing(1);
m_selectedBuildingPanel = new SelectedBuildingPanel(sim, &sim->getConfig(), m_sidePanel);
m_buildButtonGrid = new BuildButtonGrid(sim, &sim->getConfig(), iconDir, m_itemIcons.get(), m_sidePanel);
m_blueprintPanel = new BlueprintPanel(sim, &sim->getConfig(), m_sidePanel);
// Equal stretch gives the two panels half the column height each
// (REQ-UI-PANEL-COLUMN).
sideLayout->addWidget(m_selectedBuildingPanel, 1);
sideLayout->addWidget(m_buildButtonGrid, 1);
sideLayout->addWidget(m_blueprintPanel, 1);
// Draw a thin border around each of the three side-panel sections. The class
// Draw a thin border around each of the two side-panel sections. The class
// scoped selectors keep the border on the panels themselves rather than
// cascading onto their child widgets; WA_StyledBackground lets the plain
// QWidget subclasses honor the stylesheet box (border/background).
for (QWidget* panel : { static_cast<QWidget*>(m_selectedBuildingPanel),
static_cast<QWidget*>(m_buildButtonGrid),
static_cast<QWidget*>(m_blueprintPanel) })
{
panel->setAttribute(Qt::WA_StyledBackground, true);
}
m_sidePanel->setStyleSheet(QStringLiteral(
"SelectedBuildingPanel, BuildButtonGrid, BlueprintPanel {"
"SelectedBuildingPanel, BlueprintPanel {"
" border: 1px solid palette(mid); }"));
// Created last so it stacks above the other children; covers the whole window and
@@ -164,6 +171,9 @@ void MainWindow::layoutPanels()
m_headerBar->setGeometry(0, 0, mainW, headerH);
m_gameWorldView->setGeometry(0, headerH, mainW, totalH - headerH);
m_sidePanel->setGeometry(mainW, 0, sideW, totalH);
// Sizes itself to its buttons and centers along the bottom of the world view
// (REQ-UI-BUILD-BAR).
m_buildButtonBar->anchorTo(QRect(0, headerH, mainW, totalH - headerH));
m_dimOverlay->setGeometry(0, 0, totalW, totalH);
}