draw item icons on their colored square in the UI

Item icons were drawn bare in the panels and dialogs while only the game
world composed them onto the item's visuals.toml square, so the same item
read differently on a belt than in a panel.

Move the composition into ItemIconCache, which now holds the visuals and
offers it in two forms: paintItem() for the world's fractional geometry
and getSquarePixmap() for widgets. WorldRenderer::drawWorldItem collapses
onto the former, and the recipe-selection dialog, the selection panel's
item chips and the recipe summary onto the latter. The inset fraction
that shapes the composition now has one definition instead of two.

An item with no icon file now shows its square alone rather than falling
back to text, so callers gate on the composed pixmap being null -- the
case of an item with neither square nor icon -- instead of on hasIcon().
The inline building_block icon beside a number keeps using the bare
getPixmap() and takes no square.

The chip and summary squares are drawn a few pixels larger than the icons
were, so the artwork keeps its size once the square insets it. Reloading
the visuals on a restart drops the composed pixmaps, which carry the
colors they were painted with (REQ-CFG-RELOAD).

REQ-UI-ITEM-ICON, REQ-UI-RECIPE-ICON, REQ-UI-SINGLE-SELECTION,
REQ-UI-RECIPE-SUMMARY, REQ-UI-HQ-PANEL

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
This commit is contained in:
2026-08-11 09:33:19 +02:00
parent c15f09855c
commit 9dd61b6e64
7 changed files with 189 additions and 73 deletions

View File

@@ -55,7 +55,7 @@ MainWindow::MainWindow(Simulation* sim, const std::string& configDir,
// REQ-UI-BUILD-ICON).
const QString configDirPath = QString::fromStdString(m_configDir);
m_itemIcons = std::make_unique<ItemIconCache>(
QDir::cleanPath(configDirPath + "/../icons/items"));
QDir::cleanPath(configDirPath + "/../icons/items"), &m_visuals);
m_buildingIcons = std::make_unique<BuildingIconCache>(
QDir::cleanPath(configDirPath + "/../icons/buildings"));
@@ -283,6 +283,9 @@ std::optional<GameConfig> MainWindow::reloadConfig()
VisualsConfig newVisuals = VisualsLoader::load(m_configDir + "/visuals.toml");
m_visuals = std::move(newVisuals);
m_dimOverlay->setDimColor(m_visuals.overlays.modalDim);
// The composed item squares carry the colors they were painted with, so they
// are dropped for the new ones to take effect (REQ-UI-ITEM-ICON).
m_itemIcons->clearPixmapCache();
return newConfig;
}
catch (const std::exception& e)