deselect build tool when it becomes unaffordable and fix stale enabled button

This commit is contained in:
2026-07-19 21:20:59 +02:00
parent a4267a4760
commit c21af63e84
5 changed files with 60 additions and 28 deletions

View File

@@ -12,12 +12,13 @@
#include "DisplayName.h"
#include "EventManager.h"
#include "ExitBuilderModeRequestedEvent.h"
#include "Simulation.h"
BuildButtonGrid::BuildButtonGrid(const GameConfig* config, QWidget* parent)
BuildButtonGrid::BuildButtonGrid(Simulation* sim, const GameConfig* config, QWidget* parent)
: QWidget(parent)
, m_sim(sim)
, m_config(config)
, m_activeIndex(-1)
{
QGridLayout* layout = new QGridLayout(this);
layout->setSpacing(4);
@@ -79,24 +80,42 @@ BuildButtonGrid::~BuildButtonGrid()
unregisterForEvents();
}
void BuildButtonGrid::updateAffordability(int buildingBlocks)
void BuildButtonGrid::updateAffordability()
{
const int buildingBlocks = m_sim->getBuildingBlocksStock();
// If the currently selected tool can no longer be afforded, exit builder mode
// before recomputing button states so it does not stay selected. Clearing the
// active index first lets the loop below disable the now-unaffordable button.
if (m_activeIndex)
{
const BuildingType activeType = m_types[*m_activeIndex];
const std::map<BuildingType, int>::const_iterator it = m_costs.find(activeType);
const int cost = (it != m_costs.end()) ? it->second : 0;
if (buildingBlocks < cost)
{
clearActiveButton();
EventManager::getInstance()->sendEventImmediately(
std::make_shared<ExitBuilderModeRequestedEvent>());
}
}
for (std::size_t i = 0; i < m_buttons.size(); ++i)
{
const BuildingType type = m_types[i];
const std::map<BuildingType, int>::const_iterator it = m_costs.find(type);
const int cost = (it != m_costs.end()) ? it->second : 0;
m_buttons[i]->setEnabled(buildingBlocks >= cost || m_activeIndex == static_cast<int>(i));
m_buttons[i]->setEnabled(buildingBlocks >= cost || m_activeIndex == i);
}
}
void BuildButtonGrid::clearActiveButton()
{
if (m_activeIndex >= 0 && m_activeIndex < static_cast<int>(m_buttons.size()))
if (m_activeIndex)
{
m_buttons[static_cast<std::size_t>(m_activeIndex)]->setChecked(false);
m_buttons[*m_activeIndex]->setChecked(false);
}
m_activeIndex = -1;
m_activeIndex.reset();
}
void BuildButtonGrid::onBuildButton(int index)
@@ -105,8 +124,9 @@ void BuildButtonGrid::onBuildButton(int index)
{
return;
}
const std::size_t idx = static_cast<std::size_t>(index);
if (m_activeIndex == index)
if (m_activeIndex == idx)
{
clearActiveButton();
EventManager::getInstance()->sendEventImmediately(
@@ -114,15 +134,15 @@ void BuildButtonGrid::onBuildButton(int index)
return;
}
if (m_activeIndex >= 0 && m_activeIndex < static_cast<int>(m_buttons.size()))
if (m_activeIndex)
{
m_buttons[static_cast<std::size_t>(m_activeIndex)]->setChecked(false);
m_buttons[*m_activeIndex]->setChecked(false);
}
m_activeIndex = index;
m_buttons[static_cast<std::size_t>(index)]->setChecked(true);
m_activeIndex = idx;
m_buttons[idx]->setChecked(true);
EventManager::getInstance()->sendEventImmediately(
std::make_shared<BuildingTypeSelectedEvent>(m_types[static_cast<std::size_t>(index)]));
std::make_shared<BuildingTypeSelectedEvent>(m_types[idx]));
}
void BuildButtonGrid::handleEvent(std::shared_ptr<const BuilderModeExitedEvent> /*event*/)
@@ -130,6 +150,11 @@ void BuildButtonGrid::handleEvent(std::shared_ptr<const BuilderModeExitedEvent>
clearActiveButton();
}
void BuildButtonGrid::handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> /*event*/)
{
updateAffordability();
}
void BuildButtonGrid::handleEvent(std::shared_ptr<const DemolishModeChangedEvent> event)
{
m_demolishButton->setChecked(event->active);

View File

@@ -1,46 +1,56 @@
#pragma once
#include <map>
#include <optional>
#include <vector>
#include <QWidget>
#include "BuilderModeExitedEvent.h"
#include "BuildHotkeyPressedEvent.h"
#include "BuildingBlocksChangedEvent.h"
#include "BuildingType.h"
#include "DemolishModeChangedEvent.h"
#include "EventHandler.h"
#include "GameConfig.h"
class QPushButton;
class Simulation;
class BuildButtonGrid : public QWidget,
public CombinedEventHandler<BuilderModeExitedEvent,
DemolishModeChangedEvent,
BuildHotkeyPressedEvent>
BuildHotkeyPressedEvent,
BuildingBlocksChangedEvent>
{
Q_OBJECT
public:
BuildButtonGrid(const GameConfig* config, QWidget* parent = nullptr);
BuildButtonGrid(Simulation* sim, const GameConfig* config, QWidget* parent = nullptr);
~BuildButtonGrid() override;
void updateAffordability(int buildingBlocks);
void clearActiveButton();
private:
// Re-evaluates which build buttons are enabled from the current building block
// stock (read from the simulation). If the currently selected tool can no longer
// be afforded, it exits builder mode so the button does not stay selected.
void updateAffordability();
void handleEvent(std::shared_ptr<const BuilderModeExitedEvent> event) override;
void handleEvent(std::shared_ptr<const DemolishModeChangedEvent> event) override;
void handleEvent(std::shared_ptr<const BuildHotkeyPressedEvent> event) override;
void handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> event) override;
private slots:
void onBuildButton(int index);
private:
Simulation* m_sim;
const GameConfig* m_config;
std::vector<BuildingType> m_types;
std::vector<QPushButton*> m_buttons;
std::map<BuildingType, int> m_costs;
int m_activeIndex;
std::optional<std::size_t> m_activeIndex;
QPushButton* m_demolishButton;
};

View File

@@ -14,7 +14,6 @@
#include "BlueprintPanel.h"
#include "BuildButtonGrid.h"
#include "BuildingBlocksChangedEvent.h"
#include "BuildingSystem.h"
#include "Command.h"
#include "CommandRequestedEvent.h"
@@ -53,7 +52,7 @@ MainWindow::MainWindow(Simulation* sim, const std::string& configDir,
sideLayout->setSpacing(1);
m_selectedBuildingPanel = new SelectedBuildingPanel(sim, &sim->getConfig(), m_sidePanel);
m_buildButtonGrid = new BuildButtonGrid(&sim->getConfig(), m_sidePanel);
m_buildButtonGrid = new BuildButtonGrid(sim, &sim->getConfig(), m_sidePanel);
m_blueprintPanel = new BlueprintPanel(sim, &sim->getConfig(), m_sidePanel);
sideLayout->addWidget(m_selectedBuildingPanel, 1);
@@ -151,11 +150,6 @@ void MainWindow::layoutPanels()
m_dimOverlay->setGeometry(0, 0, totalW, totalH);
}
void MainWindow::handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> event)
{
m_buildButtonGrid->updateAffordability(event->blocks);
}
void MainWindow::handleEvent(std::shared_ptr<const SchematicChoicesAvailableEvent> event)
{
const double prevSpeed = m_gameWorldView->getGameSpeed();

View File

@@ -6,7 +6,6 @@
#include <QWidget>
#include "BuildingBlocksChangedEvent.h"
#include "BuildingId.h"
#include "EscapeMenuRequestedEvent.h"
#include "EventHandler.h"
@@ -32,8 +31,7 @@ class QCloseEvent;
class QResizeEvent;
class MainWindow : public QWidget,
public CombinedEventHandler<BuildingBlocksChangedEvent,
SchematicChoicesAvailableEvent,
public CombinedEventHandler<SchematicChoicesAvailableEvent,
GameOverEvent,
WinEvent,
EscapeMenuRequestedEvent,
@@ -52,7 +50,6 @@ protected:
void closeEvent(QCloseEvent* event) override;
private:
void handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> event) override;
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;