94 lines
4.7 KiB
C++
94 lines
4.7 KiB
C++
#pragma once
|
|
|
|
#include <map>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include <QByteArray>
|
|
#include <QFont>
|
|
#include <QPixmap>
|
|
#include <QString>
|
|
|
|
class QPainter;
|
|
class QRectF;
|
|
struct VisualsConfig;
|
|
|
|
// Rasterizes and caches per-item icon SVGs, and composes them onto the item's colored
|
|
// square (REQ-UI-ITEM-ICON). Item icons are self-contained, full-color SVGs loaded from
|
|
// a directory, one file per item type named after the item's id (e.g. "iron_ore.svg").
|
|
//
|
|
// The square is the item's `fill` and `outline` from visuals.toml with the icon inset
|
|
// within it, and it backs the icon both in the game world and wherever the UI displays
|
|
// an item as an item: the selection panel's item chips (REQ-UI-SINGLE-SELECTION,
|
|
// REQ-UI-HQ-PANEL), and every recipe drawn as a line -- the recipe summary, the
|
|
// selection dialog's option buttons, the item production tooltip
|
|
// (REQ-UI-RECIPE-SUMMARY, REQ-UI-SELECT-OPTIONS, REQ-UI-ITEM-TOOLTIP). Defined here
|
|
// once rather than per widget, in
|
|
// two forms: paintItem() for the world's fractional geometry, getSquarePixmap() for
|
|
// widgets that want a ready-made pixmap.
|
|
//
|
|
// The bare icon of getPixmap() has one remaining use: an inline icon standing in for the
|
|
// item's name beside a number -- building blocks beside a cost or a stock
|
|
// (REQ-UI-BLOCKS-ICON), scrap beside the amount left in debris (REQ-UI-DEBRIS-PANEL) --
|
|
// which is a decoration on a line of text rather than an item display and takes no
|
|
// square. getInlineItemIcon() in IconCaption.h is how callers ask for that form.
|
|
//
|
|
// A missing icon file is not an error: hasIcon() returns false for it and the item shows
|
|
// its colored square alone.
|
|
class ItemIconCache
|
|
{
|
|
public:
|
|
// iconDir is the directory holding the "<item_id>.svg" icon files (typically
|
|
// "<configDir>/../icons/items"). visuals supplies the per-item square colors and
|
|
// must outlive the cache; its contents may be replaced on a restart (REQ-CFG-RELOAD),
|
|
// which is what clearPixmapCache() is for.
|
|
ItemIconCache(const QString& iconDir, const VisualsConfig* visuals);
|
|
|
|
// True if an icon SVG file exists for the given item id. Loads the file's bytes
|
|
// on first query and remembers the result (including absence) so repeated calls
|
|
// are cheap.
|
|
bool hasIcon(const std::string& itemId);
|
|
|
|
// Paints the item's colored square into rect and its icon inset within it
|
|
// (REQ-UI-ITEM-ICON). Takes the rect as a QRectF so the world can keep painting at
|
|
// sub-pixel geometry. An item with no visuals entry gets no square, one with no icon
|
|
// file no icon; with neither, this paints nothing.
|
|
void paintItem(QPainter& painter, const QRectF& rect, const std::string& itemId);
|
|
|
|
// The same composition rasterized to a sizePx*sizePx pixmap for widget use, cached
|
|
// per (item id, size) so it is rendered once and reused. Returns a null pixmap only
|
|
// when the item has neither a visuals entry nor an icon file, which is the one case
|
|
// in which a caller has nothing to show and falls back to text.
|
|
QPixmap getSquarePixmap(const std::string& itemId, int sizePx);
|
|
|
|
// Returns the item's icon alone, without its square, rasterized to a transparent
|
|
// sizePx*sizePx pixmap and cached per (item id, size) so it is rendered once and
|
|
// reused across frames (REQ-UI-ITEM-ICON). Returns a null pixmap if the item has no
|
|
// icon file (callers should gate on hasIcon()).
|
|
QPixmap getPixmap(const std::string& itemId, int sizePx);
|
|
|
|
// The same bare icon sized to the height of `font`'s text, for the inline form above:
|
|
// an icon standing in for the item's name on a line of text. Null when the item has
|
|
// no icon file, which is not an error -- the caller names the item in words instead.
|
|
QPixmap getInlineIcon(const std::string& itemId, const QFont& font);
|
|
|
|
// Drops every rasterized pixmap. Called when the visuals are reloaded on a restart
|
|
// (REQ-CFG-RELOAD), because the composed squares carry the colors they were painted
|
|
// with; they are re-rasterized on next use.
|
|
void clearPixmapCache();
|
|
|
|
private:
|
|
// Returns the raw SVG bytes for an item id, loading and caching them on first
|
|
// access. An absent file caches an empty QByteArray so it is not retried.
|
|
const QByteArray& getSvg(const std::string& itemId);
|
|
// Shared rasterize-and-cache step. cacheKey distinguishes the bare and squared
|
|
// variants of one item within the single pixmap cache.
|
|
QPixmap getPixmap(const std::string& cacheKey, const std::string& itemId,
|
|
int sizePx, bool withSquare);
|
|
|
|
QString m_iconDir;
|
|
const VisualsConfig* m_visuals; // Not owned; lives in MainWindow.
|
|
std::map<std::string, QByteArray> m_svgById;
|
|
std::map<std::pair<std::string, int>, QPixmap> m_pixmapCache;
|
|
};
|