fix(chat): CH6c review fixes — opaque default, opacity-transition register clauses
BLOCKER: ChatSettings.DefaultOpacity shipped retail's base ChatInterface value (0.5) as ONE shared global default applied to every RetailWindowManager-registered window, not just the four floating chat windows retail itself fades. That faded the whole out-of-box registered UI (radar, vitals, toolbar, main chat, ...) to 50% opacity, including several windows that can never take keyboard focus and so were stuck at 0.5 permanently. Fixed to gmMainChatUI's 1.0/1.0 override (0x004CD0F0) instead — retail-identical opaque presentation for the 11 non-chat windows and the main chat window; only the four floating chat windows now diverge from retail's 0.5-while-idle default, and the Settings -> Chat transparency slider remains fully user-settable. AP-190 reworded and gains two new decomp-verified clauses: (3) retail eases opacity toward its target by 5% of the delta per tick (ChatInterface::ListenToGlobalMessage @0x004F3840, armed from the focus element-messages at @0x004F5275) where acdream snaps -- deferred, needs a UI frame-tick hook the opacity controller doesn't have; (4) retail's focus predicate is the chat ENTRY FIELD specifically (ChatInterface::IsTextEntryFocused @0x004F30A0) where acdream uses any-focusable-descendant. Both findings + the pre-existing UiMenu.cs PushAlphaAbsolute(1f) popup bypass are folded into the window-shell research doc's opacity section. NITs: fixed the stale "text bypasses the alpha" comment in UiElement.DrawSelfAndChildren (CH6c already routed DrawStringDat/ DrawString through the same ApplyAlpha chokepoint as sprites/rects); added RetailWindowManager.WindowUnregistered + wired RetailWindowOpacityController to detach and forget a window unregistered while it held focus (previously only Dispose detached, leaking any window unregistered mid-focus for the rest of the session); added post-Dispose no-op guards to the three Set* opacity mutators; added a DrawString (BitmapFont path) alpha regression test and a DrawStringDat outline/background-pass alpha test (the existing tests only ever exercised the foreground/fill pass). Also fixes RuntimeSettingsControllerTests.SettingsViewModelSavePreserves SectionAndTargetOrder's now-stale "target-chat-opacity:0.5:1" expectation (caught by the full-suite run this fix requires) to match the new 1.0 default. Campaign ledger CH6c row updated to APPROVE-WITH-FIXES. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
964af62e25
commit
cc58289967
14 changed files with 319 additions and 18 deletions
File diff suppressed because one or more lines are too long
|
|
@ -287,7 +287,7 @@ implementer per slice against a pinned contract (per
|
|||
| Jump-in-air root cause (round-2 item 1, resolved) | `a5a7eb4f` | Runtime tests 1,323/0 | — | round-3 probe evidence pinpointed a missing `OnInterfaceText` wire on the production controller-commit path (`RuntimeLocalPlayerMovementState.CommitRuntimeOwnedController`); FIXED, regression test added |
|
||||
| User gate round 3 | `98de4f5a` | Debug (all projects): 12,329 passed / 4 skipped / 1 failed (pre-existing #351 Debug-only flake — reproduces identically on the pristine pre-round-3 commit, not a regression); Release (every project reachable while a live `AcDream.App.exe` client — PID 15064, must not be killed per project policy — holds its own Release binaries locked, blocking `AcDream.App`/`AcDream.App.Tests`/`AcDream.Core.Tests` specifically): `AcDream.UI.Abstractions.Tests` (the layer this round's `/help` fix lives in) 867/867, plus `Core.Net.Tests` 823/823, `Runtime.Tests` 1,323/1,323, `Content.Tests` 130/130, `Headless.Tests` 89/89, `Bake.Tests` 15/15, `Cli.Tests` 4/4 — all 0 failed | — | findings (a)-(c) fixed this commit — SpewBox flush-top + retail dat font, `/help`/`/help death` exact retail print sequence (see "User gate — round 3" below) |
|
||||
| CH6b floating windows 1–4 | `22020ef2`, reworked `1aa77099` | 12,420 passed / 4 skipped / 0 failed | REJECT (docs/research/2026-08-10-ch6ab-review-findings.md) → reworked `1aa77099` — SHOULD-FIXES 2/3/4/5 + NITs 1-5 applied | pending — no client launches this session (hard constraint); needs the next connected round for keybind/mirror/filter visual confirmation, plus the new 0x2100005B fixture's resolved-type assumptions |
|
||||
| CH6c opacity | `a819687c` | 12,459 passed / 4 skipped / 0 failed | pending (no subagent review pass this session — implementer-only) | pending — needs the next connected round for visual confirmation (window fade on focus change, Settings slider live-apply) |
|
||||
| CH6c opacity | `a819687c` | 12,459 passed / 4 skipped / 0 failed | APPROVE-WITH-FIXES; fixed this commit — BLOCKER (out-of-box `DefaultOpacity` 0.5→1.0), AP-190 reworded + two new decomp-verified clauses (retail's per-tick ease, retail's entry-field-specific focus predicate), NITs (`UiElement.cs` stale comment, `WindowUnregistered` detach, post-Dispose `Set*` guards, `DrawString`/outline-pass alpha tests) | pending — needs the next connected round for visual confirmation (window fade on focus change, Settings slider live-apply) |
|
||||
|
||||
### CH4 closeout (2026-08-09)
|
||||
|
||||
|
|
|
|||
|
|
@ -503,15 +503,63 @@ than per-window: only a NEVER-SAVED option (a fresh character, nothing in the
|
|||
through, and even then only until the user's first slider drag pushes one
|
||||
shared value into every live window via `RecvNotice_GameplayOptionChanged`.
|
||||
|
||||
acdream ships ONE shared global default — the base `ChatInterface` value,
|
||||
0.5/1.0 — applied uniformly to every window including the main chat window
|
||||
(register row AP-190 in `docs/architecture/retail-divergence-register.md`),
|
||||
rather than replicating `gmMainChatUI`'s per-class 1.0/1.0 override. The
|
||||
**CH6c review-fix round (2026-08-10): the shared default above was WRONG.**
|
||||
Shipping the base `ChatInterface` value (0.5/1.0) as ONE shared global
|
||||
default, combined with the scope extension to every registered window, faded
|
||||
the WHOLE registered UI (radar, vitals, toolbar, main chat, ...) to 50%
|
||||
opacity out of the box — including several windows that can never take
|
||||
keyboard focus at all, so they were stuck at 0.5 permanently. acdream now
|
||||
ships `gmMainChatUI`'s per-class 1.0/1.0 override (`0x004CD0F0`) as the
|
||||
shared global default instead (register row AP-190 in
|
||||
`docs/architecture/retail-divergence-register.md`), which is retail-identical
|
||||
for the 11 non-chat windows and the main chat window and leaves only the four
|
||||
floating chat windows diverging from retail's 0.5-while-idle fade — a
|
||||
default-VALUE divergence the transparency slider still fully covers. The
|
||||
linking invariant (active >= default, restored by dragging the OTHER value —
|
||||
verified from `SetDefaultOpacity`/`SetActiveOpacity`'s own bodies, matching
|
||||
the summary already recorded above) is ported exactly regardless of which
|
||||
default seeds it.
|
||||
|
||||
### 3.1 Two more residuals found at the CH6c review (not yet ported)
|
||||
|
||||
Both are decomp-verified and both are recorded as new AP-190 clauses; neither
|
||||
is implemented this round.
|
||||
|
||||
**(a) Retail eases opacity between endpoints; acdream snaps.**
|
||||
`ChatInterface::ListenToGlobalMessage @0x004F3840` is the handler for global
|
||||
message id `3`, armed (`UIListener::RegisterForGlobalMessage(this, 3)`) from
|
||||
the element-focus messages `0x1A`/`0x1E`/`0x28`/`0x29`/`0x2E` inside the
|
||||
window's `ListenToElementMessage` switch at `0x004F5275`. Once armed, every
|
||||
tick nudges the live opacity toward whichever endpoint
|
||||
`IsTextEntryFocused` currently selects by 5% of the endpoint delta
|
||||
(`fabsl(target - current) * 0.05f`), and unregisters from the global message
|
||||
once the value lands within FP-epsilon of the target. acdream's
|
||||
`RetailWindowOpacityController.Apply` sets the target opacity directly on the
|
||||
focus-change event — the START and END states are retail-exact, but the
|
||||
transition is an instant snap instead of a roughly 20-tick fade. Porting the
|
||||
lerp needs a UI frame-tick hook `RetailWindowOpacityController` does not have
|
||||
today (it only reacts to `DescendantFocusChanged`); deferred.
|
||||
|
||||
**(b) Retail's focus predicate is the chat entry field specifically; acdream's
|
||||
is any focusable descendant.** `ChatInterface::IsTextEntryFocused @0x004F30A0`
|
||||
tests `GetFocusDescendant(rootElement) == this->m_chatEntry` — literally the
|
||||
window's text-entry element, not "some descendant of this window has focus."
|
||||
acdream's `RetailWindowHandle.DescendantFocusChanged` (the event
|
||||
`RetailWindowOpacityController` subscribes to) fires whenever ANY focusable
|
||||
descendant of the window gains focus. For a window with exactly one
|
||||
focusable child the two predicates coincide; for a window with several (a
|
||||
settings panel's multiple controls, for example) acdream's broader predicate
|
||||
holds ActiveOpacity while retail would already have faded back to
|
||||
DefaultOpacity once focus left the specific text-entry widget.
|
||||
|
||||
**Pre-existing, unrelated: `UiMenu.cs:293`'s opacity bypass.** Popup menus
|
||||
call `ctx.PushAlphaAbsolute(1f)` before drawing so a menu always reads solid
|
||||
even when it is opened from a translucent (faded) window — this is a
|
||||
deliberate acdream-only presentation choice (menus must stay legible
|
||||
regardless of the host window's current fade state), not a divergence from
|
||||
either of the two opacity mechanisms documented in this section, and it
|
||||
predates the CH6c slice.
|
||||
|
||||
---
|
||||
|
||||
## 4. Persistence — how filters, geometry, visibility and title survive
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue