show recipes visually instead of describing them in text
This commit is contained in:
@@ -5,11 +5,16 @@
|
||||
#include <functional>
|
||||
|
||||
#include "DisplayName.h"
|
||||
#include "OptionButton.h"
|
||||
#include "ProductionRules.h"
|
||||
#include "RecipeLineRow.h"
|
||||
#include "SectionBox.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QInputDialog>
|
||||
#include <QKeyEvent>
|
||||
#include <QLabel>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
@@ -22,6 +27,18 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
std::vector<RecipeLineRow::Amount> toAmounts(
|
||||
const std::vector<RecipeIngredient>& ingredients)
|
||||
{
|
||||
std::vector<RecipeLineRow::Amount> amounts;
|
||||
amounts.reserve(ingredients.size());
|
||||
for (const RecipeIngredient& ingredient : ingredients)
|
||||
{
|
||||
amounts.push_back(RecipeLineRow::Amount{ ingredient.item, ingredient.amount });
|
||||
}
|
||||
return amounts;
|
||||
}
|
||||
|
||||
const int kCellSize = 32;
|
||||
|
||||
// Empty ship tiles pulse between this grey and white at 1 Hz while a module is
|
||||
@@ -401,9 +418,11 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
|
||||
std::vector<ShipLayoutBlueprint>& allBlueprints,
|
||||
std::set<std::string> unlockedModuleIds,
|
||||
bool debugDraw,
|
||||
ItemIconCache* itemIcons,
|
||||
QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_config(config)
|
||||
, m_itemIcons(itemIcons)
|
||||
, m_shipId(shipId)
|
||||
, m_unlockedModuleIds(std::move(unlockedModuleIds))
|
||||
, m_rows(0)
|
||||
@@ -463,10 +482,22 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
|
||||
// Middle: three-column area (stats | module buttons | blueprints).
|
||||
QHBoxLayout* columnsLayout = new QHBoxLayout();
|
||||
|
||||
// Left column: ship stats panel.
|
||||
// Left column: ship stats panel, and beneath it what the layout being configured
|
||||
// would cost to build (REQ-MOD-UI-DIALOG). The cost sits outside the stats panel
|
||||
// because that widget is shared with the live ship card and the balancing tool,
|
||||
// neither of which costs anything -- and the balancing tool is deliberately built
|
||||
// without the item icons this line draws with.
|
||||
QVBoxLayout* leftLayout = new QVBoxLayout();
|
||||
m_statsPanel = new ShipStatsPanel(config, this);
|
||||
m_statsPanel->setDebugDrawEnabled(m_debugDraw);
|
||||
columnsLayout->addWidget(m_statsPanel);
|
||||
leftLayout->addWidget(m_statsPanel);
|
||||
|
||||
m_buildCostSection = new SectionBox(tr("Build cost"), this);
|
||||
m_buildCostLine = new RecipeLineRow(m_itemIcons, nullptr, m_buildCostSection);
|
||||
m_buildCostSection->getContentLayout()->addWidget(m_buildCostLine);
|
||||
leftLayout->addWidget(m_buildCostSection);
|
||||
leftLayout->addStretch(1);
|
||||
columnsLayout->addLayout(leftLayout);
|
||||
|
||||
// Center column: module selection buttons.
|
||||
QVBoxLayout* centerLayout = new QVBoxLayout();
|
||||
@@ -487,11 +518,34 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config,
|
||||
m_moduleButtons.push_back(nullptr);
|
||||
continue;
|
||||
}
|
||||
const QString label = QString::fromStdString(toDisplayName(def.id))
|
||||
+ "\n" + QString::fromStdString(def.glyph);
|
||||
QPushButton* btn = new QPushButton(label, this);
|
||||
// The module's name over what it costs -- its materials and the production time
|
||||
// it adds (REQ-MOD-UI-DIALOG). The glyph is how a module is identified on the
|
||||
// layout grid, not here. Both children are transparent to the mouse so a click
|
||||
// anywhere on the face still reaches the button.
|
||||
OptionButton* btn = new OptionButton(this);
|
||||
btn->setCheckable(true);
|
||||
btn->setFixedHeight(48);
|
||||
|
||||
QVBoxLayout* face = new QVBoxLayout(btn);
|
||||
face->setContentsMargins(8, 4, 8, 4);
|
||||
face->setSpacing(1);
|
||||
|
||||
QLabel* nameLabel =
|
||||
new QLabel(QString::fromStdString(toDisplayName(def.id)), btn);
|
||||
nameLabel->setAttribute(Qt::WA_TransparentForMouseEvents, true);
|
||||
face->addWidget(nameLabel);
|
||||
|
||||
RecipeLineRow::Spec cost;
|
||||
cost.inputs = toAmounts(def.materials);
|
||||
cost.durationSeconds = def.productionTimeSeconds;
|
||||
cost.durationIsAddition = true;
|
||||
|
||||
RecipeLineRow* costLine = new RecipeLineRow(m_itemIcons, nullptr, btn);
|
||||
costLine->setAttribute(Qt::WA_TransparentForMouseEvents, true);
|
||||
face->addWidget(costLine);
|
||||
costLine->setLine(cost);
|
||||
|
||||
// The config tooltip stays: it says what the module does, which the cost line
|
||||
// does not (REQ-MOD-UI-MODULE-TOOLTIP).
|
||||
if (def.tooltip)
|
||||
{
|
||||
btn->setToolTip(QString::fromStdString(*def.tooltip));
|
||||
@@ -731,6 +785,29 @@ void ShipLayoutDialog::updateGridWidget()
|
||||
void ShipLayoutDialog::updateStats()
|
||||
{
|
||||
m_statsPanel->refresh(m_shipId, m_placedModules);
|
||||
|
||||
// What the layout as it currently stands would cost to build, so the price follows
|
||||
// every placement and removal (REQ-MOD-UI-DIALOG). The sums come from the
|
||||
// simulation's own rules rather than being added up a second time here
|
||||
// (REQ-MOD-MATERIALS, REQ-MOD-PRODUCTION-TIME).
|
||||
ShipLayoutConfig layout;
|
||||
layout.placedModules = m_placedModules;
|
||||
const std::map<std::string, int> materials =
|
||||
computeShipyardRequiredMaterials(*m_config, m_shipId, layout);
|
||||
|
||||
RecipeLineRow::Spec cost;
|
||||
cost.inputs.reserve(materials.size());
|
||||
for (const std::pair<const std::string, int>& entry : materials)
|
||||
{
|
||||
cost.inputs.push_back(RecipeLineRow::Amount{ entry.first, entry.second });
|
||||
}
|
||||
cost.durationSeconds =
|
||||
computeShipyardProductionTimeSeconds(*m_config, m_shipId, layout);
|
||||
|
||||
m_buildCostLine->setLine(cost);
|
||||
// A schematic costing no materials at all has no line to draw, and the section then
|
||||
// stays out of the way.
|
||||
m_buildCostSection->setVisible(!cost.inputs.empty());
|
||||
}
|
||||
|
||||
bool ShipLayoutDialog::canPlaceModule(const ModuleDef& def, QPoint position,
|
||||
|
||||
Reference in New Issue
Block a user