From ae394ec89fdfebb38bfd392356d352229e6485a6 Mon Sep 17 00:00:00 2001 From: calic Date: Sun, 21 Jun 2026 11:43:34 +0200 Subject: [PATCH] feat(inventory-list-display): icon_atlas override + fit-to-bounds rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- init.lua | 39 ++++++++++++++++++++++++++++++++------- manifest.lib | 2 +- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/init.lua b/init.lua index 95075d5..fab759a 100644 --- a/init.lua +++ b/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) diff --git a/manifest.lib b/manifest.lib index 40d9e06..b22f3a9 100644 --- a/manifest.lib +++ b/manifest.lib @@ -1 +1 @@ -{"id":"lib-core.inventory-list-display","version":"0.1.1","api_min":"0.1","deps":[{"id":"lib-core.panel","version":"0.4.0"},{"id":"lib-core.inventory-list","version":"0.1.0"},{"id":"lib-core.composition","version":"0.3.0"}]} \ No newline at end of file +{"id":"lib-core.inventory-list-display","version":"0.2.0","api_min":"0.1","deps":[{"id":"lib-core.panel","version":"0.4.0"},{"id":"lib-core.inventory-list","version":"0.1.0"},{"id":"lib-core.composition","version":"0.3.0"}]}