feat(inventory-list-display): icon_atlas override + fit-to-bounds rendering
Two consumer-side fixes for ADR-0054 §3 (Item-Visual-Identity). 1) default_icon_resolver tries icon_atlas + icon_uv.* first; falls back to sprite_atlas + sprite_uv.* when the override is absent. Items inherit their world-render sprite as the UI icon for free (TC_Basics-style object sprites work directly as icons); dedicated low-res UI-icons can later land via icon_atlas without API churn. 2) Render path scales the icon uniformly to fit a (row_height - 4) box, centered. The world-sprite-as-icon path (300×300 native) no longer overflows the row; pre-baked small icons stay sharp because the scale is applied around the visual center of the UV rect, not the texture origin. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
39
init.lua
39
init.lua
@@ -54,9 +54,26 @@ local M = {}
|
||||
-- -----------------------------------------------------------------------
|
||||
|
||||
-- default_icon_resolver(item) -> icon_table or nil
|
||||
-- Reads sprite_atlas + sprite_uv.* from item properties.
|
||||
-- Returns nil if sprite_atlas is not set (no icon for this item).
|
||||
-- v0.2.0: per ADR-0054 §3 — additive UI-icon override on top of the
|
||||
-- world-sprite. If the item declares `icon_atlas` (string) + `icon_uv.*`
|
||||
-- (numbers), use those (e.g. for dedicated low-res UI icons baked
|
||||
-- separately). Otherwise fall back to `sprite_atlas` + `sprite_uv.*`
|
||||
-- (the world-render sprite, which today doubles as the UI icon for
|
||||
-- TC_Basics-style item-shaped sprites).
|
||||
-- Returns nil if neither chain yields a sprite (no icon for this item).
|
||||
local function default_icon_resolver(item)
|
||||
local icon_atlas = item:get_property("icon_atlas")
|
||||
if icon_atlas and icon_atlas ~= "" then
|
||||
return {
|
||||
atlas = icon_atlas,
|
||||
uv = {
|
||||
x = item:get_property("icon_uv.x"),
|
||||
y = item:get_property("icon_uv.y"),
|
||||
w = item:get_property("icon_uv.w"),
|
||||
h = item:get_property("icon_uv.h"),
|
||||
},
|
||||
}
|
||||
end
|
||||
local atlas = item:get_property("sprite_atlas")
|
||||
if not atlas or atlas == "" then return nil end
|
||||
return {
|
||||
@@ -108,13 +125,21 @@ local function render_widget(widget_def, ctx)
|
||||
widget_def.widget_id, icon.atlas)
|
||||
if ok and tex then
|
||||
local uv = icon.uv
|
||||
-- draw_sprite_transform(tex, x, y, rot, scl_x, scl_y,
|
||||
-- origin_x, origin_y, tint, u, v, uw, vh)
|
||||
-- rot=0, scl=1, origin at top-left (0,0), tint=white
|
||||
-- v0.2.0: fit-to-bounds. Compute uniform scale so the
|
||||
-- larger UV dimension matches the icon box (row_height
|
||||
-- minus a small margin), then center-anchor inside the
|
||||
-- box. Lets world-sprites (e.g. TC_Basics 300×300 native)
|
||||
-- and pre-baked icons share the same row layout without
|
||||
-- per-item magic numbers.
|
||||
local box = ctx.theme.row_height - 4
|
||||
local max_uv = (uv.w > uv.h) and uv.w or uv.h
|
||||
local s = box / max_uv
|
||||
local draw_x = ctx.bounds.x + (box - uv.w * s) / 2
|
||||
local draw_y = row_y + 2 + (box - uv.h * s) / 2
|
||||
engine.render.draw_sprite_transform(
|
||||
tex,
|
||||
ctx.bounds.x, row_y,
|
||||
0, 1, 1,
|
||||
draw_x, draw_y,
|
||||
0, s, s,
|
||||
0, 0,
|
||||
0xFFFFFFFF,
|
||||
uv.x, uv.y, uv.w, uv.h)
|
||||
|
||||
Reference in New Issue
Block a user