fix(ui): gate — no void frames around the login wormhole; vitals icons centered

The login tunnel now covers from the first world-facing frame (the
sky-void backdrop can never present pre-tunnel) and holds through an
atomic tunnel-to-world swap at reveal completion — the void is
structurally unreachable on both edges, pinned by frame-sequence tests
across WorldSceneRenderer/WorldRevealCoordinator/LocalPlayerTeleport-
Controller/RuntimeWorldTransitState. Vitals detail icons draw at their
authored centered offsets in both stacked and side-by-side layouts.
Implemented and live-probed by the fix agent; finalized by the lead
after the agent parked post-verification (gates re-run green:
App 5512/3, Runtime 1747/0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-17 12:30:51 +02:00
parent 2f8c046aba
commit fdc4fd496d
17 changed files with 649 additions and 66 deletions

View file

@ -542,13 +542,14 @@ public static class DatWidgetFactory
{
bool passToChildren = info.States.Values.Any(
static s => s.Name is "HideDetail" or "ShowDetail" && s.PassToChildren);
// Each spec carries the overlay's authored edge modes and its
// container's authored size: the overlays author L3/R3 (retail
// CENTER anchors), which is what re-centers the icon when the
// vitals window resizes the meter away from its authored
// width (UiMeter.ComputeDetailOverlayRect).
m.ConfigureDetailOverlay(
backOverlay is not null ? backOverlay.StateMedia["ShowDetail"].File : 0u,
backOverlay?.X ?? 0f, backOverlay?.Y ?? 0f,
backOverlay?.Width ?? 0f, backOverlay?.Height ?? 0f,
frontOverlay is not null ? frontOverlay.StateMedia["ShowDetail"].File : 0u,
frontOverlay?.X ?? 0f, frontOverlay?.Y ?? 0f,
frontOverlay?.Width ?? 0f, frontOverlay?.Height ?? 0f,
DetailOverlaySpec(backOverlay, containers[0]),
DetailOverlaySpec(frontOverlay, containers[1]),
passToChildren);
}
}
@ -672,6 +673,23 @@ public static class DatWidgetFactory
&& c.StateMedia.TryGetValue("ShowDetail", out var media)
&& media.File != 0);
/// <summary>
/// Builds one absorbed overlay spec: the ShowDetail sprite, the authored
/// container-local rect, the authored raw edge-anchor modes, and the
/// container's authored size (the overlay's reflow parent — the container
/// itself authors L1/T1/R1/B1, so its current box always equals the
/// meter's). A null overlay yields the empty spec (Sprite 0 never draws).
/// </summary>
private static UiMeterDetailOverlaySpec DetailOverlaySpec(
ElementInfo? overlay, ElementInfo container)
=> overlay is null
? default
: new UiMeterDetailOverlaySpec(
overlay.StateMedia["ShowDetail"].File,
overlay.X, overlay.Y, overlay.Width, overlay.Height,
overlay.Left, overlay.Top, overlay.Right, overlay.Bottom,
container.Width, container.Height);
private static bool HasStatefulFill(ElementInfo container)
=> container.States.Any(pair =>
pair.Key != UiStateInfo.DirectStateId