Files
dota_factory/src/ui/MainWindow.cpp

170 lines
5.3 KiB
C++

#include "MainWindow.h"
#include <QApplication>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QPushButton>
#include <QResizeEvent>
#include <QVBoxLayout>
#include "BuildButtonGrid.h"
#include "GameWorldView.h"
#include "HeaderBar.h"
#include "SelectedBuildingPanel.h"
#include "Simulation.h"
#include "Tick.h"
MainWindow::MainWindow(Simulation* sim, const GameConfig* config,
const VisualsConfig* visuals, QWidget* parent)
: QWidget(parent)
, m_sim(sim)
{
setWindowTitle("Dota Factory");
resize(1280, 768);
m_headerBar = new HeaderBar(this);
m_gameWorldView = new GameWorldView(sim, config, visuals, this);
m_bottomPanel = new QWidget(this);
QHBoxLayout* bottomLayout = new QHBoxLayout(m_bottomPanel);
bottomLayout->setContentsMargins(0, 0, 0, 0);
bottomLayout->setSpacing(0);
m_selectedBuildingPanel = new SelectedBuildingPanel(sim, config, m_bottomPanel);
m_buildButtonGrid = new BuildButtonGrid(config, m_bottomPanel);
bottomLayout->addWidget(m_selectedBuildingPanel, 1);
bottomLayout->addWidget(m_buildButtonGrid, 1);
// Signals: game world → other panels
connect(m_gameWorldView, SIGNAL(selectionChanged(std::vector<EntityId>)),
m_selectedBuildingPanel, SLOT(onSelectionChanged(std::vector<EntityId>)));
connect(m_gameWorldView, SIGNAL(stateUpdated(Tick, int, double)),
m_headerBar, SLOT(onStateUpdated(Tick, int, double)));
connect(m_gameWorldView, SIGNAL(stateUpdated(Tick, int, double)),
this, SLOT(onStateUpdated(Tick, int, double))); // for affordability
connect(m_gameWorldView, SIGNAL(stateUpdated(Tick, int, double)),
m_selectedBuildingPanel, SLOT(onStateUpdated(Tick, int, double)));
connect(m_gameWorldView, SIGNAL(gameOver()),
this, SLOT(onGameOver()));
connect(m_gameWorldView, SIGNAL(escapeMenuRequested()),
this, SLOT(onEscapeMenuRequested()));
// Signals: build grid → game world
connect(m_buildButtonGrid, SIGNAL(buildingTypeSelected(BuildingType)),
m_gameWorldView, SLOT(enterBuilderMode(BuildingType)));
connect(m_buildButtonGrid, SIGNAL(builderModeExited()),
m_gameWorldView, SLOT(exitBuilderMode()));
connect(m_gameWorldView, SIGNAL(builderModeExited()),
m_buildButtonGrid, SLOT(clearActiveButton()));
connect(m_buildButtonGrid, SIGNAL(demolishModeToggleRequested()),
m_gameWorldView, SLOT(toggleDemolishMode()));
connect(m_gameWorldView, SIGNAL(demolishModeChanged(bool)),
m_buildButtonGrid, SLOT(setDemolishModeActive(bool)));
// Signals: header bar → game world
connect(m_headerBar, SIGNAL(speedChanged(double)),
m_gameWorldView, SLOT(setGameSpeed(double)));
m_gameWorldView->setFocus();
connect(qApp, &QApplication::focusChanged, this, [this](QWidget*, QWidget* newWidget) {
if (newWidget && newWidget != m_gameWorldView && !QApplication::activeModalWidget())
{
m_gameWorldView->setFocus();
}
});
}
void MainWindow::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
layoutPanels();
}
void MainWindow::layoutPanels()
{
const int totalW = width();
const int totalH = height();
const int headerH = m_headerBar->sizeHint().height();
if (headerH <= 0) { return; }
const int remaining = totalH - headerH;
const int gameH = remaining * 70 / 100;
const int panelH = remaining - gameH;
m_headerBar->setGeometry(0, 0, totalW, headerH);
m_gameWorldView->setGeometry(0, headerH, totalW, gameH);
m_bottomPanel->setGeometry(0, headerH + gameH, totalW, panelH);
}
void MainWindow::onStateUpdated(Tick /*tick*/, int blocks, double /*speed*/)
{
m_buildButtonGrid->updateAffordability(blocks);
}
void MainWindow::onEscapeMenuRequested()
{
const double prevSpeed = m_gameWorldView->gameSpeed();
m_gameWorldView->setGameSpeed(0.0);
QMessageBox box(this);
box.setWindowTitle("Paused");
QPushButton* continueBtn = box.addButton("Continue", QMessageBox::AcceptRole);
QPushButton* restartBtn = box.addButton("Restart", QMessageBox::ResetRole);
QPushButton* quitBtn = box.addButton("Quit", QMessageBox::DestructiveRole);
box.setEscapeButton(continueBtn);
box.exec();
QAbstractButton* clicked = box.clickedButton();
if (clicked == restartBtn)
{
m_sim->reset();
m_gameWorldView->resetForNewGame();
}
else if (clicked == quitBtn)
{
close();
}
else
{
m_gameWorldView->setGameSpeed(prevSpeed);
}
}
void MainWindow::onGameOver()
{
const Tick tick = m_sim->currentTick();
const int totalSeconds = static_cast<int>(ticksToSeconds(tick));
const int minutes = totalSeconds / 60;
const int seconds = totalSeconds % 60;
QMessageBox box(this);
box.setWindowTitle("Game Over");
box.setText(QString("HQ destroyed!\nSurvival time: %1:%2")
.arg(minutes, 2, 10, QChar('0'))
.arg(seconds, 2, 10, QChar('0')));
QPushButton* restartBtn = box.addButton("Restart", QMessageBox::AcceptRole);
box.addButton("Quit", QMessageBox::RejectRole);
box.exec();
if (box.clickedButton() == restartBtn)
{
m_sim->reset();
m_gameWorldView->resetForNewGame();
}
else
{
close();
}
}