feat(ui): #409 — client-wide retail tooltip system
Full re-derivation from named-retail decomp: UIElement::StartTooltipAtMouse @0x00460D70 -> UIElementManager::StartTooltip @0x0045DE90/@0x00459700, UIElement::MouseHover @0x00462520 (P0x4B TooltipOn gate + global m_tooltipEnable), UIElementManager::CheckTooltip @0x0045B6E0 (dwell/ auto-hide timer, default 0.25s/10s), SwitchMouseOver/DeletingElement (dismissal). Corrects the earlier GF-16 investigation: P0x47 is the element-desc id WITHIN the popup LayoutDesc (P0x48), not a "behavior enum"; P0x4A is read off the popup's own instantiated root, not the trigger element. - ElementInfo/UiElement gain six tooltip data fields (P0x47/48/49/4A/4B/50), read generically by ElementReader and copied through LayoutImporter, mirroring the existing AuthoredInvisible passthrough pattern. - UiRoot's existing CheckTooltip-derived hover timer gains TooltipShow/ TooltipHide events, a per-element P0x50 delay override, and dismissal wiring at every retail-confirmed teardown site. - RetailTooltipPresenter (owned by RetailUiRuntime, mounted alongside RetailDialogFactory) builds the popup via the existing LayoutImporter dat-lock seam, auto-resizes by the measured-vs-authored text delta (word-wrapped via the existing UiText.WrapWords primitive), positions at the mouse clamped to the display, and stays topmost over dialogs via its own later per-tick BringToFront (register AD-106). - Misc.TooltipEnable/Misc.TooltipDelay are client-local UserPreferences (retail's own 2013 Config tab authors no visible row for either) — SettingsStore gains a MiscSettings section, no new options-panel row. - Live-DAT sweep: 434 elements author >=1 trigger property (243 with literal text this port shows; 191 rely on retail's dynamic InqProperty(0x49) override, deferred as register TS-85 alongside the unmodeled P0x3D wrap-width override). Gates: Release build 0 errors; App suite (live-DAT env) 5410/5407 passed/ 3 skipped (was 5379/3); Runtime 1735/0 unchanged; UI.Abstractions 926/0; full solution 14,617/14,548 passed/69 skipped/0 failed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
d3755eb231
commit
a377b9bff7
16 changed files with 1386 additions and 9 deletions
|
|
@ -107,8 +107,75 @@ horizontal `HJustify` mapping while in this code, since it shares the
|
|||
|
||||
## #409 — Client-wide UI tooltip system is unshipped (GF-16, deferred out of Campaign CC gate round 1)
|
||||
|
||||
**Status:** OPEN
|
||||
**Severity:** LOW-MEDIUM (cosmetic/discoverability — no gameplay impact, but retail shows a tooltip on hover for ~253 authored elements client-wide and acdream shows none)
|
||||
**Status:** CODE-COMPLETE 2026-08-16 (this commit) — pending the user's connected visual gate (see the gate note at the bottom of this entry).
|
||||
**Severity:** LOW-MEDIUM (cosmetic/discoverability — no gameplay impact, but retail shows a tooltip on hover for authored elements client-wide and acdream showed none before this fix)
|
||||
|
||||
**2026-08-16 re-derivation + port (this commit).** Full re-derivation from
|
||||
`docs/research/named-retail/acclient_2013_pseudo_c.txt` corrected two things
|
||||
the original GF-16 filing below got wrong from a shallower pass: **`P0x47`
|
||||
is NOT a "tooltip behavior enum" — it is the element-desc id WITHIN the
|
||||
popup LayoutDesc (`P0x48`) to instantiate as the popup's root**
|
||||
(`UIElementManager::StartTooltip @0x0045DE90` passes it straight to
|
||||
`LayoutDesc::AccessElementDesc`), and **`P0x4A` is read off the freshly
|
||||
INSTANTIATED popup's own root element, not the hovering trigger element**
|
||||
(it names that popup's text-child id). A live-DAT sweep (installed EoR
|
||||
build) found **434 elements author at least one of the five trigger
|
||||
properties** (243 with literal `P0x49` `StringInfo` text this port shows;
|
||||
the other 191 rely on retail's DYNAMIC `InqProperty(0x49)` text override,
|
||||
out of scope — see register row TS-85), superseding the original "~253"
|
||||
estimate. Layout `0x21000041` holds four 30x30 popup skins
|
||||
(`0x10000487`/`0x10000395`/`0x10000397`/`0x10000398`), each a four-piece
|
||||
bevel frame around one shared Type-12 text child `0x10000396` — confirmed
|
||||
by `TooltipLiveDatTests`.
|
||||
|
||||
**Shipped:** the six-property data layer (`ElementInfo`/`UiElement`
|
||||
`Tooltip*`/`AuthoredTooltip*` fields, `ElementReader`,
|
||||
`DatWidgetFactory.ResolveTooltipText`, `LayoutImporter.BuildWidget`); the
|
||||
hover-dwell/auto-hide/dismissal state machine (`UiRoot.Tick`'s existing
|
||||
`CheckTooltip` port gained `TooltipShow`/`TooltipHide` C# events, a
|
||||
per-element `P0x50` delay-override consult, and dismissal wiring at every
|
||||
retail-confirmed teardown site — hover-target change, owner-element
|
||||
removal, duration timeout); `RetailTooltipPresenter` (owned by
|
||||
`RetailUiRuntime`, mounted alongside `RetailDialogFactory`) — builds the
|
||||
popup via the SAME `LayoutImporter`/dat-lock seam dialogs use, auto-resizes
|
||||
by the retail measured-vs-authored-text delta (word-wrapped at the display
|
||||
width via the existing `UiText.WrapWords` primitive), positions at the
|
||||
mouse cursor clamped to the display, keeps itself topmost over dialogs via
|
||||
its own later per-tick `BringToFront` (register AD-106), and gates on both
|
||||
the global `Misc.TooltipEnable` preference (client-local, `SettingsStore`'s
|
||||
new `MiscSettings` section — retail's OWN 2013 Config tab authors no
|
||||
visible row for it either, confirmed by the OP campaign's own research, so
|
||||
no new options-panel row was added) and the widget's own `P0x4B`. **No
|
||||
click-dismissal was ported** — `UIElementManager::MouseDownEvent
|
||||
@0x0045DB60` calls the SAME `SwitchMouseOver` hover-change check that
|
||||
already drives dismissal, and it no-ops when the hit-tested element hasn't
|
||||
changed, so retail itself does not dismiss a tooltip by clicking its own
|
||||
owner.
|
||||
|
||||
**Deferred (register TS-85):** dynamic per-element tooltip text
|
||||
(`InqProperty(0x49)`, 191 elements) and the `P0x3D` per-element wrap-width
|
||||
override (zero elements author one today). **Deferred (register AD-106):**
|
||||
the topmost-z-order mechanism is a sibling-with-later-reraise adaptation,
|
||||
not retail's literal separate presentation layer.
|
||||
|
||||
**Gate note (5-10 min, `ACDREAM_RETAIL_UI=1`):** hover the mouse over any
|
||||
of these and hold still — a small tooltip box should appear after a brief
|
||||
pause (~0.25 s, matching retail's registered default) and disappear when
|
||||
you move to a different control: (1) chargen Appearance page — the rotate
|
||||
arrows beside the preview ("Rotate left."/"Rotate right.") and any color
|
||||
swatch ("Changes color of selected clothing or body part."); (2) the same
|
||||
page's hair/eyes/nose spin arrows (longer help text — should WRAP across
|
||||
multiple lines, not run off-screen); (3) any other screen with a tooltip
|
||||
you recall from retail. Confirm: the box sits right at the cursor (not
|
||||
offset), never runs off the edge of the window even near a corner, and
|
||||
disappears on its own after ~10 s if you hold still without moving away.
|
||||
No click-to-dismiss is expected — only moving off the control, or a very
|
||||
long hold, closes it.
|
||||
|
||||
---
|
||||
|
||||
**Original GF-16 filing (superseded by the re-derivation above; kept for
|
||||
investigation history).**
|
||||
|
||||
Found during Campaign CC gate round 1's Batch D root-cause investigation
|
||||
(`docs/research/2026-08-16-campaign-cc-gate-round1-findings.md`, GF-16
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue