the hover tax is pinned and cut, and a spell-less macro is a button

- a tooltip change costs ~1.3 ms — five whole-interface recomputes, each working as designed: the quad re-convert at 474 µs, the Lua tick at 287, the layout resolve at 200, bevy's `Assets<Mesh>` tax at ~270 and the mesh rebuild at 146 — pinned with new hover probes (a jitter dial, a `WOW_PROBE_HOVER_DUTY` duty cycle so run drift cancels, an `AssetChanged` tax meter), and the layout preamble's two whole-roster scans become lists maintained at the writer (52–83 µs → 1–11)
- the splice compared this frame's entries against last frame's by index, so one inserted highlight shifted the 160 entries behind it and read as "everything changed"; it now aligns on `z` — an identity, not a position — and a `Text` entry that writes only quads became spliceable, so a tooltip change re-converts 22 entries instead of 520 (`convert` +439 µs → +107), with `WOW_UI_SPLICE_VERIFY` running the full conversion behind every spliced frame: 0 mismatches over 1,078
- a spell-less macro is a usable action button, not the 0.4 grey — the reference's usable compute has a dedicated leg answering usable for the bound-spell zero, cross-checked at the bytes in the reference's disassembly — and the button's Name line is written unconditionally from `GetActionText` as the reference does, so the macro's name sits under its icon and a `/cast` of a spell the character does not know now greys, which is also 1.12's behaviour (B340)
- a capture bounds its run in wall-clock seconds, because a frame cap is no cap at the ~1 fps a starved `nextDrawable` leaves — 1800 frames is thirty minutes there — and the teardown backstop runs on every run as a liveness guarantee, carrying the exit code the run asked for; the Multisampling row reads Off / 2x / 4x, since "1x" contradicts the no-multisampling byte both of the reference's enumerators normalise to and the bit-depth prefix was identical on every row

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Sam
2026-08-27 15:13:58 +07:00
co-authored by Claude Fable 5
parent a0447c171d
commit 45f001bbc5
26 changed files with 1599 additions and 257 deletions
+16 -9
View File
@@ -671,16 +671,16 @@ fn cell(model: &Model, rh: crate::widget::RegionHandle) -> Cell {
/// frames whose lines haven't been measured yet (the XML default size holds until the measure
/// round-trip lands, one frame later — the same convergence the Lua loop had).
pub(super) fn layout_tooltips(model: &mut Model) {
// The arena's tooltip registry, not the resolve's whole frame roster: this pre-pass runs at
// the top of EVERY resolve, and finding two or three tooltips by scanning ~4000 ids was most
// of what it cost (decision 1634). `frame_to_id` still gates each one — a tooltip outside the
// resolve's roster would mint an id here and take the ledger's conservative branch with it.
let tips: Vec<FrameHandle> = model
.frame_to_id
.keys()
.arena
.tooltip_kinds()
.iter()
.copied()
.filter(|&h| {
matches!(
model.arena.frame(h).map(|f| &f.kind_state),
Some(KindState::Tooltip(_))
)
})
.filter(|h| model.frame_to_id.contains_key(h))
.collect();
for h in tips {
let (num, lefts, rights, min_w, pad_w) = match model.arena.frame(h).map(|f| &f.kind_state) {
@@ -767,7 +767,14 @@ pub(super) fn tick_fades(lua: &Lua) {
let mut finished: Vec<FrameHandle> = Vec::new();
{
let model = lua.app_data_ref::<Model>().expect("model app_data");
for &h in model.frame_to_id.keys() {
// The arena's tooltip registry (1634) — this runs every tick, and the roster it used to
// walk is ~4000 entries at a corpus UI. The `frame_to_id` gate is kept: `hide_tooltip`
// below writes layout, and a frame outside the resolve's roster takes the ledger's
// conservative branch.
for &h in model.arena.tooltip_kinds() {
if !model.frame_to_id.contains_key(&h) {
continue;
}
let Some(frame) = model.arena.frame(h) else {
continue;
};