event-driven UI feeds, and the character window's cost lets go

- the eight heaviest UI feeds — spellbook, party, character, bags, talents, units, pet, player — rebuild only when an input moved instead of every frame: 216 → 12 µs a frame parked
- the character window's cost settles once it closes: enchant countdowns feed by the second instead of firing an inventory event into all 20 slots every frame, the paper-doll booth parks with its camera, and a window hidden under the cursor fires OnLeave so its tooltip goes with it — the reference's hover-hide law
- the walk stops paying for finished work: the loading-screen tally's per-placement walk latches off once the world is ready, the settled placement spawner is one integer compare, and billboards stop dirtying every card's transform
- never-rendering hierarchy nodes — rig anchors, joints, doodad hosts — keep the hide chain but leave the per-camera visibility sweep: 25,198 → 18,026 swept entities at Goldshire

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Sam
2026-08-20 19:01:11 +07:00
co-authored by Claude Fable 5
parent 447e92aed5
commit 5360a44f89
49 changed files with 1611 additions and 142 deletions
@@ -213,10 +213,18 @@ pub(super) fn drive_script(
) {
let (capture, ui_cost_wanted) = run;
let Some(mut script) = script else {
// No VM ⇒ no UI is sampling any booth pane. The panes map must not outlive its writer:
// every OTHER return in this system provably keeps pane presence unchanged (the settled
// gate compares the whole extracted list; the splice refuses `portrait_unit` entries),
// but a VM dying mid-world with the character window up would strand its pane here and
// the paper-doll camera would render behind a dead UI until the next full conversion.
booths.panes.0.clear();
return;
};
let prev = prev.get(&script);
let Ok(window) = window.single() else {
// Same law as the no-VM arm: no window, no sampling — a pane map with no writer lies.
booths.panes.0.clear();
return;
};
let (w, h) = (window.width(), window.height());