171 lines
4.9 KiB
C++
171 lines
4.9 KiB
C++
#include "RecipeSelectionDialog.h"
|
|
|
|
#include <cstddef>
|
|
|
|
#include <QGridLayout>
|
|
#include <QIcon>
|
|
#include <QPixmap>
|
|
#include <QPushButton>
|
|
#include <QSize>
|
|
#include <QStringList>
|
|
#include <QVBoxLayout>
|
|
|
|
#include "Building.h"
|
|
#include "BuildingType.h"
|
|
#include "DisplayName.h"
|
|
#include "GameConfig.h"
|
|
#include "ItemIconCache.h"
|
|
#include "RecipesConfig.h"
|
|
#include "RecipeTooltip.h"
|
|
#include "ShipsConfig.h"
|
|
#include "Simulation.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
QString itemLine(const std::string& itemId, int amount)
|
|
{
|
|
return QStringLiteral(" ")
|
|
+ QString::fromStdString(toDisplayName(itemId))
|
|
+ QStringLiteral(" x ") + QString::number(amount);
|
|
}
|
|
|
|
QString shipTooltip(const ShipDef& def)
|
|
{
|
|
const QString name = QString::fromStdString(toDisplayName(def.id));
|
|
|
|
QStringList lines;
|
|
lines << QObject::tr("Ship: %1").arg(name);
|
|
|
|
if (def.schematic.materials.empty())
|
|
{
|
|
lines << QObject::tr("Materials: none");
|
|
}
|
|
else
|
|
{
|
|
lines << QObject::tr("Materials:");
|
|
for (const RecipeIngredient& material : def.schematic.materials)
|
|
{
|
|
lines << itemLine(material.item, material.amount);
|
|
}
|
|
lines << QObject::tr(" + installed modules");
|
|
}
|
|
|
|
lines << QObject::tr("Completion time: %1 s")
|
|
.arg(def.schematic.productionTimeSeconds);
|
|
lines << QObject::tr("Produces: 1 %1").arg(name);
|
|
|
|
return lines.join('\n');
|
|
}
|
|
|
|
} // namespace
|
|
|
|
std::vector<RecipeSelectionOption> buildRecipeSelectionOptions(
|
|
BuildingType type, Simulation& sim, const GameConfig& config)
|
|
{
|
|
std::vector<RecipeSelectionOption> options;
|
|
options.push_back({std::string(), QObject::tr("(None)"), QString()});
|
|
|
|
if (type == BuildingType::Shipyard)
|
|
{
|
|
for (const ShipDef& def : config.ships.ships)
|
|
{
|
|
if (!sim.isSchematicUnlocked(def.id)) { continue; }
|
|
options.push_back({def.id,
|
|
QString::fromStdString(toDisplayName(def.id)),
|
|
shipTooltip(def)});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (const RecipeDef& recipe : config.recipes.recipes)
|
|
{
|
|
if (recipe.building != type) { continue; }
|
|
if ((type == BuildingType::Miner
|
|
|| type == BuildingType::Assembler)
|
|
&& !sim.isRecipeUnlocked(recipe.id))
|
|
{
|
|
continue;
|
|
}
|
|
// Icon shown on the option button (REQ-UI-RECIPE-ICON): the recipe's
|
|
// configured icon item, else its first output item.
|
|
const std::string iconItemId = recipe.icon
|
|
? *recipe.icon
|
|
: (recipe.outputs.empty() ? std::string()
|
|
: recipe.outputs.front().item);
|
|
options.push_back({recipe.id,
|
|
QString::fromStdString(toDisplayName(recipe.id)),
|
|
buildRecipeTooltip(recipe),
|
|
iconItemId});
|
|
}
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
// On-screen size of a recipe option button's item icon (REQ-UI-RECIPE-ICON).
|
|
const QSize kOptionIconSize(32, 32);
|
|
}
|
|
|
|
RecipeSelectionDialog::RecipeSelectionDialog(
|
|
const std::vector<RecipeSelectionOption>& options,
|
|
const QString& title, ItemIconCache* itemIcons, QWidget* parent)
|
|
: QDialog(parent)
|
|
{
|
|
setWindowTitle(title);
|
|
setModal(true);
|
|
|
|
QVBoxLayout* mainLayout = new QVBoxLayout(this);
|
|
QGridLayout* grid = new QGridLayout();
|
|
mainLayout->addLayout(grid);
|
|
|
|
const int columnCount = 2;
|
|
for (int i = 0; i < static_cast<int>(options.size()); ++i)
|
|
{
|
|
const RecipeSelectionOption& option = options[static_cast<std::size_t>(i)];
|
|
|
|
QPushButton* button = new QPushButton(this);
|
|
// Icon-only when the produced item has an icon (REQ-UI-RECIPE-ICON); otherwise
|
|
// fall back to the caption. The name stays reachable via the tooltip.
|
|
if (!option.iconItemId.empty() && itemIcons->hasIcon(option.iconItemId))
|
|
{
|
|
button->setIcon(QIcon(itemIcons->getPixmap(
|
|
option.iconItemId, kOptionIconSize.width())));
|
|
button->setIconSize(kOptionIconSize);
|
|
}
|
|
else
|
|
{
|
|
button->setText(option.caption);
|
|
}
|
|
if (!option.tooltip.isEmpty())
|
|
{
|
|
button->setToolTip(option.tooltip);
|
|
}
|
|
button->setMinimumHeight(40);
|
|
grid->addWidget(button, i / columnCount, i % columnCount);
|
|
|
|
m_optionIds.push_back(option.id);
|
|
const int index = i;
|
|
connect(button, &QPushButton::clicked, this, [this, index]()
|
|
{
|
|
onOptionClicked(index);
|
|
});
|
|
}
|
|
}
|
|
|
|
std::optional<std::string> RecipeSelectionDialog::getChosenId() const
|
|
{
|
|
return m_chosenId;
|
|
}
|
|
|
|
void RecipeSelectionDialog::onOptionClicked(int index)
|
|
{
|
|
if (index >= 0 && index < static_cast<int>(m_optionIds.size()))
|
|
{
|
|
m_chosenId = m_optionIds[static_cast<std::size_t>(index)];
|
|
}
|
|
accept();
|
|
}
|