the login scene frames its art, char select remembers, DXT stays DXT

- the glue scene widens only as far as its art goes: none of the seven login dioramas is drawn wider than about 3:2 — measured per texel by `benilla-extract glueextent`, which rasterises every batch into the camera's own tan-space, painting where the reference's alpha-key test passes — so the frame zooms down to the reference's own 16:9 opening (never tighter) and pillarboxes past the aspect the art cannot fill, instead of showing the clear colour past the backdrop's slanted edges; 4:3 stays byte-identical
- the character screen opens on whoever you last logged in as: the reference's `lastCharacterIndex` CVar, written at Enter World and only there — clicks and arrow keys never touch it, which is what makes the value mean "last logged in" rather than "last clicked" — restored on every character-list rebuild and clamped into range
- spam-hovering tooltips stops costing 2 ms: two write sites gave up naming their node and re-derived the whole layout graph (1,812 µs against the ledger's 44, on 919 of 1,262 resolves) — the wrap pin now touches the one region it wrote, and re-pointing a tooltip at the button under the cursor retargets the node's edges in place instead of throwing the cached graph away
- two corrections off the project's first GPU-bound report (a Steam Deck at 94% GPU busy on 8.4 W of a 15 W budget, the memory-stall signature): `farclip` ships the reference's registered 350 instead of the clamp's 777 — the value also sizes terrain residency, so 777 streamed, held and drew 4.8× the area — and BLP textures upload WoW's own DXT blocks verbatim the way the reference does, instead of decoding to RGBA8 at 8× the bytes of DXT1; the terrain slider still reaches 777, and the lanes that read texels on the CPU (terrain arrays, the character-skin compositor) stay decoded and say why

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Sam
2026-08-27 15:11:59 +07:00
co-authored by Claude Fable 5
parent 88f036206e
commit 7146bc91f0
36 changed files with 3333 additions and 244 deletions
@@ -442,13 +442,26 @@ fn set_point(lua: &Lua, this: &Table, point: &str, rest: [Value; 4]) -> mlua::Re
// Value-only unless the target moved (decision 1388) — the per-frame `SetPoint` idiom
// (a dragged window, a moving spark) re-points the SAME anchor at the SAME target with new
// offsets, so it names its node and the cached graph survives the frame.
//
// A retarget names its node too now (decision 1625): the edge set is not derivable from a
// per-node hash, but it IS derivable from the anchors, and both lists are right here. The
// target lists are collected only on the structural path — the value-only one is the hot
// idiom and must stay allocation-free.
let structural = anchor_retarget_is_structural(&input.anchors, &new);
let old_targets: Option<Vec<u32>> =
structural.then(|| input.anchors.iter().map(|a| a.relative_to).collect());
input.anchors.retain(|a| a.point != point);
input.anchors.push(new);
if structural {
model.touch_layout();
} else {
model.touch_layout_frame(h);
match old_targets {
None => model.touch_layout_frame(h),
Some(old) => {
let new_targets: Vec<u32> = model.layout_inputs[&h]
.anchors
.iter()
.map(|a| a.relative_to)
.collect();
model.touch_layout_retarget_frame(h, &old, &new_targets);
}
}
}
Ok(())
@@ -460,7 +473,14 @@ fn set_point(lua: &Lua, this: &Table, point: &str, rest: [Value; 4]) -> mlua::Re
/// node reads that node's rect". An anchor whose OFFSETS moved is a value change — the node
/// re-solves and nothing else does, which is exactly what a precise touch claims. An anchor whose
/// TARGET moved is not: an edge has to disappear and another to appear, and no per-node hash can
/// say so, so the cached graph must be thrown away instead (decision 1388).
/// say so.
///
/// 1388 answered that by throwing the cached graph away. **Since decision 1625 it does not have
/// to be**: the write site holds both target lists, so the node's edges are re-pointed in place
/// (`Model::touch_layout_retarget_frame`) and the roster and every other node's hash survive.
/// What this predicate decides is therefore no longer "value change or catastrophe" but which of
/// two precise touches to use — and it still earns its place, because the value-only answer is
/// the hot per-frame idiom and must stay allocation-free.
///
/// Mirrors the `retain(point) + push` the setters do. It is value-only in exactly one shape — one
/// existing anchor carries this point and keeps the same target. Zero (an edge appears) and two or