From 204184afb2500e99f3c7bbe15eb6d7c270422965 Mon Sep 17 00:00:00 2001 From: grom Date: Mon, 2 Nov 2026 18:42:45 -0700 Subject: [PATCH] ui: the map's own art line, in every session's log A play report about how the map looks arrives without the diagnostic that answers it, and the only way to ask for the line again is to wait for the player to play again. It cost a round trip on 2026-11-02, so the trace is unconditional now: one line per world-map selection change, with the frame the detail is drawn into added beside the detail frame's own rect, since a canvas zoom and an oversized tile change the picture the same way and only the two together say which one did it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn --- crates/benilla-app/src/ui_world_map.rs | 45 +++++++++++++++----------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/crates/benilla-app/src/ui_world_map.rs b/crates/benilla-app/src/ui_world_map.rs index 8220f139..c700069d 100644 --- a/crates/benilla-app/src/ui_world_map.rs +++ b/crates/benilla-app/src/ui_world_map.rs @@ -64,16 +64,9 @@ struct DirectAreaEntry { view: WorldMapZoneView, } -/// `WOW_MAP_TRACE=1`, read once: the map-art trace below is off unless a player is being asked -/// to reproduce something, since it runs a Lua chunk per map change. -fn map_trace_on() -> bool { - static ON: std::sync::OnceLock = std::sync::OnceLock::new(); - *ON.get_or_init(|| std::env::var_os("WOW_MAP_TRACE").is_some()) -} - -/// The chunk [`map_trace_on`] runs. Pure reads; `GetTexture` answers the path the stock repaint -/// set, and a texture created with no size of its own answers the file's own extent through the -/// host's size probe, which is why a scratch region is used to measure the file rather than the +/// The chunk the art trace runs, once per map change. Pure reads; `GetTexture` answers the path +/// the stock repaint set, and a texture created with no size of its own answers its own extent +/// through the host's size probe, which is why a scratch region measures the file rather than the /// tile (the tile declares 256x256 in `WorldMapFrame.xml` and would answer that whatever the file /// holds). const MAP_ART_TRACE: &str = r#" @@ -83,6 +76,18 @@ local function num(v) return v and string.format("%.0f", v) or "?" end local out = { string.format("detail %sx%s @(%s,%s) scale %.2f shown=%s", num(d:GetWidth()), num(d:GetHeight()), num(d:GetLeft()), num(d:GetTop()), d:GetEffectiveScale() or 1, tostring(d:IsShown())) } +-- What it is drawn into: a canvas zoom and a tile size both change the picture, and only the +-- two together say which one did. +local p = d:GetParent() +if p then + out[#out + 1] = string.format("in %s %sx%s @(%s,%s) scale %.2f", p:GetName() or "", + num(p:GetWidth()), num(p:GetHeight()), num(p:GetLeft()), num(p:GetTop()), + p:GetEffectiveScale() or 1) +end +if WorldMapFrame then + out[#out + 1] = string.format("frame %sx%s scale %.2f", num(WorldMapFrame:GetWidth()), + num(WorldMapFrame:GetHeight()), WorldMapFrame:GetEffectiveScale() or 1) +end -- One scratch texture, re-pointed per tile: with no size of its own it answers the file's extent. if not BenillaMapTraceProbe then BenillaMapTraceProbe = UIParent:CreateTexture(nil, "BACKGROUND") @@ -691,7 +696,7 @@ struct FeedMemos { /// line prints on change rather than every frame — the selection is in the key because a /// selection that stops following the player is the thing the line exists to show. zone_logged: Option<(u32, u32, u32, u32, u32, u32, u32)>, - /// The map selection the `WOW_MAP_TRACE` art line last reported, so it prints once per map + /// The map selection the art line last reported, so it prints once per map /// rather than once per frame. art_logged: Option<(u32, u32, Option)>, /// The resolved pair last seen, so the watchdog in [`feed_world_map`] can tell the player @@ -1028,14 +1033,16 @@ fn feed_world_map( } } - // `WOW_MAP_TRACE=1`: what the map's base art actually is, once per map change. A player's - // report about how the map *looks* cannot be answered from this side — the offline harness - // seats no renderer and the capture harness seats no UI — and every number that decides the - // picture is readable from the VM, so this prints them rather than guessing from a - // screenshot: the detail frame's own rect and effective scale, then per tile its rect, the - // texture path it holds and the decoded size of that file. A tile whose rect is not 256x256 - // at a 256 pitch, or whose file is not the size the layout assumes, names the fault outright. - if map_trace_on() { + // What the map's base art actually is, once per map change. A player's report about how the + // map *looks* cannot be answered from this side — the offline harness seats no renderer and + // the capture harness seats no UI — and every number that decides the picture is readable + // from the VM, so this prints them rather than guessing from a screenshot: the detail frame's + // rect and effective scale, the frame it is drawn into, then per tile its rect, the texture + // path it holds and the decoded size of that file. A tile whose rect is not 256x256 at a 256 + // pitch, or whose file is not the size the layout assumes, names the fault outright. It was + // behind `WOW_MAP_TRACE` and that cost a round trip: a play report about the map arrives + // without it, and the next one cannot be asked for until the player plays again. + { let key = script.world_map_selection(); let memo = memo.get(&script); if memo.art_logged != Some(key) {