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