share a single ItemIconCache across the UI
This commit is contained in:
@@ -184,13 +184,12 @@ namespace
|
||||
|
||||
BuildButtonGrid::BuildButtonGrid(Simulation* sim, const GameConfig* config,
|
||||
const std::string& iconDir,
|
||||
const std::string& itemsIconDir, QWidget* parent)
|
||||
ItemIconCache* itemIcons, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_sim(sim)
|
||||
, m_config(config)
|
||||
, m_iconDir(iconDir)
|
||||
, m_itemIcons(std::make_unique<ItemIconCache>(
|
||||
QString::fromStdString(itemsIconDir)))
|
||||
, m_itemIcons(itemIcons)
|
||||
{
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
layout->setSpacing(4);
|
||||
|
||||
@@ -32,11 +32,12 @@ class BuildButtonGrid : public QWidget,
|
||||
|
||||
public:
|
||||
// iconDir is the directory holding the per-building "<id>.svg" chip icons
|
||||
// (REQ-UI-BUILD-GRID); itemsIconDir holds the per-item icons and supplies the
|
||||
// building_block icon shown in each button's cost (REQ-UI-BUILD-COST). Both are
|
||||
// read from disk at runtime, like the config files.
|
||||
// (REQ-UI-BUILD-GRID), read from disk at runtime like the config files.
|
||||
// itemIcons is the window-wide per-item icon cache and supplies the
|
||||
// building_block icon shown in each button's cost (REQ-UI-BUILD-COST). Not
|
||||
// owned; must outlive this widget.
|
||||
BuildButtonGrid(Simulation* sim, const GameConfig* config,
|
||||
const std::string& iconDir, const std::string& itemsIconDir,
|
||||
const std::string& iconDir, ItemIconCache* itemIcons,
|
||||
QWidget* parent = nullptr);
|
||||
~BuildButtonGrid() override;
|
||||
|
||||
@@ -65,7 +66,7 @@ private:
|
||||
Simulation* m_sim;
|
||||
const GameConfig* m_config;
|
||||
std::string m_iconDir;
|
||||
std::unique_ptr<ItemIconCache> m_itemIcons;
|
||||
ItemIconCache* m_itemIcons; // Not owned; lives in MainWindow.
|
||||
std::vector<BuildingType> m_types;
|
||||
std::vector<QPushButton*> m_buttons;
|
||||
std::map<BuildingType, int> m_costs;
|
||||
|
||||
@@ -197,11 +197,13 @@ QColor statusLightFill(ProductionStatus status, const StatusLightVisuals& sl)
|
||||
|
||||
GameWorldView::GameWorldView(Simulation* sim, const GameConfig* config,
|
||||
const VisualsConfig* visuals, const std::string& configDir,
|
||||
const ParsedReplay* replay, QWidget* parent)
|
||||
ItemIconCache* itemIcons, const ParsedReplay* replay,
|
||||
QWidget* parent)
|
||||
: QOpenGLWidget(parent)
|
||||
, m_sim(sim)
|
||||
, m_config(config)
|
||||
, m_visuals(visuals)
|
||||
, m_itemIcons(itemIcons)
|
||||
, m_commandManager(*sim)
|
||||
, m_gameSpeedMultiplier(1.0)
|
||||
, m_prevNonZeroSpeed(1.0)
|
||||
@@ -223,11 +225,6 @@ GameWorldView::GameWorldView(Simulation* sim, const GameConfig* config,
|
||||
|
||||
loadBuildingIcons(configDir);
|
||||
|
||||
// Item icons live beside the config dir, mirroring the building icons
|
||||
// (REQ-UI-ITEM-ICON, REQ-UI-WORLD-ICON).
|
||||
m_itemIcons = std::make_unique<ItemIconCache>(QDir::cleanPath(
|
||||
QString::fromStdString(configDir) + "/../icons/items"));
|
||||
|
||||
m_renderTimer = new QTimer(this);
|
||||
m_renderTimer->setInterval(16);
|
||||
connect(m_renderTimer, &QTimer::timeout, this, &GameWorldView::onFrame);
|
||||
|
||||
@@ -83,9 +83,12 @@ class GameWorldView : public QOpenGLWidget,
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// itemIcons is the window-wide per-item icon cache (REQ-UI-ITEM-ICON); not
|
||||
// owned, must outlive this widget.
|
||||
GameWorldView(Simulation* sim, const GameConfig* config,
|
||||
const VisualsConfig* visuals, const std::string& configDir,
|
||||
const ParsedReplay* replay, QWidget* parent = nullptr);
|
||||
ItemIconCache* itemIcons, const ParsedReplay* replay,
|
||||
QWidget* parent = nullptr);
|
||||
~GameWorldView() override;
|
||||
|
||||
double getGameSpeed() const;
|
||||
@@ -309,9 +312,10 @@ private:
|
||||
};
|
||||
std::map<BuildingType, BuildingIconRenderers> m_buildingIcons;
|
||||
|
||||
// Per-item icon cache (REQ-UI-ITEM-ICON), loaded from <configDir>/../icons/items.
|
||||
// Shared draw path for belt and port items; pixmaps are cached per target size.
|
||||
std::unique_ptr<ItemIconCache> m_itemIcons;
|
||||
// Per-item icon cache (REQ-UI-ITEM-ICON), shared window-wide and owned by
|
||||
// MainWindow. Shared draw path for belt and port items; pixmaps are cached
|
||||
// per target size.
|
||||
ItemIconCache* m_itemIcons;
|
||||
|
||||
// Funnels all player input into the single Simulation::apply chokepoint.
|
||||
CommandManager m_commandManager;
|
||||
|
||||
@@ -32,10 +32,9 @@ const double HeaderBar::kSpeeds[] = { 0.0, 0.5, 1.0, 2.0, 10.0 };
|
||||
const int HeaderBar::kSpeedCount = 5;
|
||||
|
||||
HeaderBar::HeaderBar(const Simulation* sim, const GameConfig* config,
|
||||
const std::string& itemsIconDir, QWidget* parent)
|
||||
ItemIconCache* itemIcons, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_itemIcons(std::make_unique<ItemIconCache>(
|
||||
QString::fromStdString(itemsIconDir)))
|
||||
, m_itemIcons(itemIcons)
|
||||
, m_sim(sim)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
|
||||
@@ -33,11 +33,11 @@ class HeaderBar : public QWidget,
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// itemsIconDir holds the per-item icon SVGs (REQ-UI-ITEM-ICON); used to show the
|
||||
// building_block icon in the stock display and expand button (REQ-UI-BLOCKS-ICON,
|
||||
// REQ-UI-EXPAND-BUTTON).
|
||||
// itemIcons is the window-wide per-item icon cache (REQ-UI-ITEM-ICON); used to
|
||||
// show the building_block icon in the stock display and expand button
|
||||
// (REQ-UI-BLOCKS-ICON, REQ-UI-EXPAND-BUTTON). Not owned; must outlive this widget.
|
||||
HeaderBar(const Simulation* sim, const GameConfig* config,
|
||||
const std::string& itemsIconDir, QWidget* parent = nullptr);
|
||||
ItemIconCache* itemIcons, QWidget* parent = nullptr);
|
||||
~HeaderBar() override;
|
||||
|
||||
private slots:
|
||||
@@ -73,7 +73,7 @@ private:
|
||||
QPushButton* m_expandButton;
|
||||
std::vector<QPushButton*> m_speedButtons;
|
||||
|
||||
std::unique_ptr<ItemIconCache> m_itemIcons;
|
||||
ItemIconCache* m_itemIcons; // Not owned; lives in MainWindow.
|
||||
|
||||
// The simulation is the single source of truth for the block stock and the
|
||||
// expansion cost; the change events are only refresh signals.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "SelectedBuildingPanel.h"
|
||||
#include "ShipLayoutBlueprintSerializer.h"
|
||||
#include "ShipLayoutDialog.h"
|
||||
#include "ItemIconCache.h"
|
||||
#include "Simulation.h"
|
||||
#include "Tick.h"
|
||||
#include "VisualsLoader.h"
|
||||
@@ -47,10 +48,13 @@ MainWindow::MainWindow(Simulation* sim, const std::string& configDir,
|
||||
const std::string itemsIconDir = QDir::cleanPath(
|
||||
QString::fromStdString(m_configDir) + "/../icons/items").toStdString();
|
||||
|
||||
m_headerBar = new HeaderBar(sim, &sim->getConfig(), itemsIconDir, this);
|
||||
m_itemIcons = std::make_unique<ItemIconCache>(
|
||||
QString::fromStdString(itemsIconDir));
|
||||
|
||||
m_headerBar = new HeaderBar(sim, &sim->getConfig(), m_itemIcons.get(), this);
|
||||
|
||||
m_gameWorldView = new GameWorldView(sim, &sim->getConfig(), &m_visuals, m_configDir,
|
||||
m_replay.get(), this);
|
||||
m_itemIcons.get(), m_replay.get(), this);
|
||||
|
||||
m_sidePanel = new QWidget(this);
|
||||
QVBoxLayout* sideLayout = new QVBoxLayout(m_sidePanel);
|
||||
@@ -63,7 +67,7 @@ MainWindow::MainWindow(Simulation* sim, const std::string& configDir,
|
||||
QString::fromStdString(m_configDir) + "/../icons/buildings").toStdString();
|
||||
|
||||
m_selectedBuildingPanel = new SelectedBuildingPanel(sim, &sim->getConfig(), m_sidePanel);
|
||||
m_buildButtonGrid = new BuildButtonGrid(sim, &sim->getConfig(), iconDir, itemsIconDir, m_sidePanel);
|
||||
m_buildButtonGrid = new BuildButtonGrid(sim, &sim->getConfig(), iconDir, m_itemIcons.get(), m_sidePanel);
|
||||
m_blueprintPanel = new BlueprintPanel(sim, &sim->getConfig(), m_sidePanel);
|
||||
|
||||
sideLayout->addWidget(m_selectedBuildingPanel, 1);
|
||||
@@ -328,11 +332,7 @@ void MainWindow::handleEvent(std::shared_ptr<const RecipeSelectionRequestedEvent
|
||||
|
||||
bool autoOpenLayout = false;
|
||||
std::string chosenSchematic;
|
||||
// Item icons live beside the config dir, mirroring the buildings icon path
|
||||
// (REQ-UI-ITEM-ICON, REQ-UI-BUILD-ICON).
|
||||
const QString itemIconDir = QDir::cleanPath(
|
||||
QString::fromStdString(m_configDir) + "/../icons/items");
|
||||
RecipeSelectionDialog dialog(options, title, itemIconDir, this);
|
||||
RecipeSelectionDialog dialog(options, title, m_itemIcons.get(), this);
|
||||
if (dialog.exec() == QDialog::Accepted && dialog.getChosenId().has_value())
|
||||
{
|
||||
std::shared_ptr<SetRecipeCommand> command = std::make_shared<SetRecipeCommand>();
|
||||
|
||||
@@ -27,6 +27,7 @@ class HeaderBar;
|
||||
class SelectedBuildingPanel;
|
||||
class BuildButtonGrid;
|
||||
class BlueprintPanel;
|
||||
class ItemIconCache;
|
||||
class QCloseEvent;
|
||||
class QResizeEvent;
|
||||
|
||||
@@ -68,6 +69,9 @@ private:
|
||||
std::string m_configDir;
|
||||
VisualsConfig m_visuals;
|
||||
Simulation* m_sim;
|
||||
// One per-item icon cache for the whole window (REQ-UI-ITEM-ICON): the header,
|
||||
// build grid, world view, and recipe dialog all rasterize the same SVGs.
|
||||
std::unique_ptr<ItemIconCache> m_itemIcons;
|
||||
GameWorldView* m_gameWorldView;
|
||||
HeaderBar* m_headerBar;
|
||||
SelectedBuildingPanel* m_selectedBuildingPanel;
|
||||
|
||||
@@ -111,14 +111,12 @@ namespace
|
||||
|
||||
RecipeSelectionDialog::RecipeSelectionDialog(
|
||||
const std::vector<RecipeSelectionOption>& options,
|
||||
const QString& title, const QString& itemIconDir, QWidget* parent)
|
||||
const QString& title, ItemIconCache* itemIcons, QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(title);
|
||||
setModal(true);
|
||||
|
||||
ItemIconCache iconCache(itemIconDir);
|
||||
|
||||
QVBoxLayout* mainLayout = new QVBoxLayout(this);
|
||||
QGridLayout* grid = new QGridLayout();
|
||||
mainLayout->addLayout(grid);
|
||||
@@ -131,9 +129,9 @@ RecipeSelectionDialog::RecipeSelectionDialog(
|
||||
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() && iconCache.hasIcon(option.iconItemId))
|
||||
if (!option.iconItemId.empty() && itemIcons->hasIcon(option.iconItemId))
|
||||
{
|
||||
button->setIcon(QIcon(iconCache.getPixmap(
|
||||
button->setIcon(QIcon(itemIcons->getPixmap(
|
||||
option.iconItemId, kOptionIconSize.width())));
|
||||
button->setIconSize(kOptionIconSize);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
struct GameConfig;
|
||||
class Simulation;
|
||||
class QPushButton;
|
||||
class ItemIconCache;
|
||||
|
||||
// One selectable entry in the recipe/schematic selection dialog
|
||||
// (REQ-UI-SELECT-BUTTON). The "(None)" entry uses an empty id.
|
||||
@@ -43,11 +44,11 @@ class RecipeSelectionDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// itemIconDir is the directory holding per-item icon SVGs (REQ-UI-ITEM-ICON);
|
||||
// used to render recipe options icon-only (REQ-UI-RECIPE-ICON). Options whose
|
||||
// item has no icon file fall back to their caption text.
|
||||
// itemIcons is the window-wide per-item icon cache (REQ-UI-ITEM-ICON); used to
|
||||
// render recipe options icon-only (REQ-UI-RECIPE-ICON). Options whose item has
|
||||
// no icon file fall back to their caption text. Not owned.
|
||||
RecipeSelectionDialog(const std::vector<RecipeSelectionOption>& options,
|
||||
const QString& title, const QString& itemIconDir,
|
||||
const QString& title, ItemIconCache* itemIcons,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
std::optional<std::string> getChosenId() const;
|
||||
|
||||
Reference in New Issue
Block a user