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
+35 -2
View File
@@ -66,12 +66,26 @@ impl<T: Default> VmMemo<T> {
/// way into it and once on the way out, and holds in between. Reaching for a scratch default
/// each frame instead would quietly turn the memo off for the whole glue phase.
pub(crate) fn get_for(&mut self, script: Option<&UiScript>) -> &mut T {
self.get_reset_for(script).0
}
/// [`VmMemo::get`], also reporting whether the memory RESET on this read — i.e. this is the
/// first read against a new VM. A gated feed (decision 1439) keys its "must run" on exactly
/// this: with every input unchanged, a fresh VM still needs the full re-push, and the reset is
/// the only signal that says so. The flag is true at most once per session per memo, so a gate
/// that ORs it in costs nothing on the steady frames it exists to skip.
pub(crate) fn get_reset(&mut self, script: &UiScript) -> (&mut T, bool) {
self.get_reset_for(Some(script))
}
fn get_reset_for(&mut self, script: Option<&UiScript>) -> (&mut T, bool) {
let now = script.map_or(0, UiScript::session);
if self.session != now {
let reset = self.session != now;
if reset {
self.session = now;
self.inner = T::default();
}
&mut self.inner
(&mut self.inner, reset)
}
}
@@ -118,6 +132,25 @@ mod tests {
);
}
/// The gate half (1439): `get_reset` reports the reset exactly once per session flip — the
/// one frame a gated feed must run with every other input unchanged.
#[test]
fn get_reset_reports_each_session_flip_once() {
let first = UiScript::new().expect("VM");
let second = UiScript::new().expect("VM");
let mut memo: VmMemo<u32> = VmMemo::default();
let (m, reset) = memo.get_reset(&first);
assert!(reset, "the first read of a session is the reset");
*m = 7;
let (m, reset) = memo.get_reset(&first);
assert!(!reset, "steady frames read quietly");
assert_eq!(*m, 7);
let (m, reset) = memo.get_reset(&second);
assert!(reset, "a new VM resets again");
assert_eq!(*m, 0, "…and the memory is gone with the old one");
}
#[test]
fn a_seed_is_claimed_once_per_vm() {
let first = UiScript::new().expect("VM");