feat(ui): vitals — click toggles retail's numeric/graphical detail modes
Port of gmVitalsUI's press toggle, derived end-to-end from the named
retail decomp + the authored DAT data (installed-DAT probe 2026-08-17):
- gmVitalsUI::ListenToElementMessage @0x004BFC00: mouse press (msg 0x1C,
dwParam1 7=left or 0xA=right — the same param pair the spellbook's
select/favorite handler @0x0048C033 disambiguates) flips
SetState(m_state == HideDetail ? ShowDetail : HideDetail). Both floaty
subclasses (gmFloatyVitalsUI 0x1000004D / gmFloatySideVitalsUI
0x10000056) inherit it verbatim.
- UIElement::SetState @0x00464E70 cascades through the authored
PassToChildren chain: root and meters author media-less
HideDetail/ShowDetail StateDescs with PassToChildren=true.
- HideDetail (0x10000006) = the NUMERIC mode: the cur/max labels author
{0x3B:false} (0x3B = invisible; UIElement::OnSetAttribute case 8
@0x00462DAE is SetVisible(value == 0)), the 0x100004A9 overlays author
File=0.
- ShowDetail (0x10000007) = the GRAPHICAL mode: labels author {0x3B:true}
(numbers hidden); each bar shows its authored icon pair — dim back icon
unclipped over the track, bright front icon clipped with the front
container to the fill fraction (UIElement_Meter::DrawChildren
@0x0046FBD0 clips the whole element-id-2 child; m_pcChildImage =
GetChildRecursive(this, 2) @0x0046F7E3). Health heart 0x06007490/91
(18x16 @66,0), stamina sword 0x06007492/93 (85x16 @32,0), mana scepter
0x06007494/95 (100x16 @25,0) — identical authoring in both 0x2100006C
and 0x21000075.
- Initial state is the authored Undef (numbers visible, no icons —
visually HideDetail); retail's first press lands on HideDetail, then
the pair toggles forever. NOT persisted: SaveScreenLayout @0x004EAD50
writes window rects only, and no PlayerModule option is touched — the
mode resets per session, per window.
- Presses on drag bars / resize grips do not toggle: retail's
UIElement_Dragbar @0x0046C850 and UIElement_Resizebar @0x0046B930
consume the press (return 2) before it can bubble to the root.
Implementation: new UiVitalsRoot behavioral widget registered for the
three gmVitals class ids (press handler + state flip over the existing
UiDatElement state machine); UiMeter absorbs the two 0x100004A9 overlays
(ConfigureDetailOverlay + ShowDetail-keyed draw, back unclipped / front
fill-clipped) and forwards the detail states to its absorbed text child;
UiText.ApplyDatState gains the same named-state-only 0x3B honor
UiDatElement already had (the DirectState 0x3B class stays gated — #408).
8 new fixture-driven conformance tests (toggle sequence, right-press,
label cascade, chrome exclusions, per-window independence, overlay
extraction). App suite Release live-DAT: 5495 passed / 3 skips.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
302d90209d
commit
306a1670d3
6 changed files with 480 additions and 10 deletions
|
|
@ -386,6 +386,22 @@ public sealed class UiText : UiElement, IUiDatStateful
|
|||
&& TryColor(color, out Vector4 resolvedColor))
|
||||
DefaultColor = resolvedColor;
|
||||
|
||||
// Per-state Invisible (dat property 0x3B): retail's SetState applies the
|
||||
// committed state's properties through UIElement::OnSetAttribute, whose
|
||||
// case 8 (@0x00462DAE, property id 0x33 + 8 = 0x3B) is
|
||||
// `SetVisible(value == 0)`. Same NAMED-states-only scoping as
|
||||
// UiDatElement.TrySetRetailState (a DirectState 0x3B is the
|
||||
// construction-time "authored invisible" class — #408, separately
|
||||
// gated). First consumer here: the vitals cur/max number labels
|
||||
// (0x100000EB/ED/EF) author HideDetail={0x3B:false} /
|
||||
// ShowDetail={0x3B:true} — the numbers hide when the click toggle
|
||||
// switches the window to the graphical icon mode.
|
||||
if (stateId != UiStateInfo.DirectStateId
|
||||
&& state is not null
|
||||
&& state.Properties.Values.TryGetValue(0x3Bu, out var invisibleProp)
|
||||
&& invisibleProp.Kind == UiPropertyKind.Bool)
|
||||
Visible = !invisibleProp.BoolValue;
|
||||
|
||||
// Retail's state cascade also swaps the element's AUTHORED string
|
||||
// when the incoming state carries its own 0x17 (the friends row's
|
||||
// status cell: 'Online'/'Offline' with per-state colors). Resolved
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue