fix(chargen): Campaign CC gate round 1 re-test 3 — R4-1..R4-4
Four visual residuals from the lead's own live-client captures of 1.0.2-cc.m, all root-caused via decomp + live-DAT evidence: - R4-1: Skills credits value overlapped mid-caption again. Root cause was a missing UiLayoutPolicy raw-edge reflow on UiButton's value-child rect (the child is base-inherited across four sibling buttons of differing widths, so its baked-in OriginalParentWidth diverges from the actual 231px-wide Skills credits button) plus an HJustify.Right value child mapped to Center instead of a real far-edge Right. - R4-2: the single-sprite scrollbar thumb tiled (GL_REPEAT) instead of drawing once — DrawTiled was reused for a small fixed marker graphic whose native size is far smaller than the track-proportional thumb rect. New DrawThumbMarker draws exactly one native-size instance. - R4-3: the skills info-box formula line clipped past the surrounding gold frame's own authored bottom edge (the pane's own raw box is 20px taller than the frame that visually contains it) — clamp the pane's Height to the frame's bottom (register AD-105, since retail's ShowSkillsText has no code relationship to the frame to cite). - R4-4: the Appearance help text started mid-sentence — the box was never touched by its page controller, so it kept UiText's chat-style PreserveEndOnLayout=true default; the scroll model's wasAtEnd check is vacuously true on its first-ever overflow transition, pinning the first render to the bottom. Set PreserveEndOnLayout=false (a static top-oriented report, not a transcript) and wired the box's own nested authored scrollbar, never wired before. App suite live-DAT env 5372/3 -> 5379/3 (+7, zero regressions). Runtime 1735/0 unchanged. Full solution 14585/4 skips/1 failure (the documented Core.Net NakEmission full-solution-only flake, confirmed standalone-pass). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
28704db4bf
commit
e6acb800cc
11 changed files with 678 additions and 12 deletions
File diff suppressed because one or more lines are too long
|
|
@ -1028,3 +1028,127 @@ render retail-shaped; four residuals visible in the captures:
|
|||
next to the article of clothing…") — the opening paragraph is either
|
||||
scrolled off (box has no visible scrollbar) or missing from the
|
||||
composition; check what retail authors/composes for that box.
|
||||
|
||||
**RE-TEST 3 fix batch (2026-08-16, R4-1..R4-4) is CODE-COMPLETE, pending the
|
||||
user's visual gate.** All four findings root-caused and fixed via decomp +
|
||||
live-DAT evidence, no invented pixel offsets. App suite live-DAT env
|
||||
5372/3 → 5379/3 (+7, zero regressions); Runtime 1735/0 unchanged; full
|
||||
solution 14585 tests / 4 skips / 1 failure (Core.Net
|
||||
`NakEmissionTests.LossSoak_TwoPercentBidirectional_ZeroMessageLoss_LedgersConverge`,
|
||||
the documented full-solution-only flake — confirmed passing standalone,
|
||||
unrelated to this batch's files). No client launches.
|
||||
|
||||
- **R4-1 FIXED — root cause was a MISSING raw-edge reflow, not a wrap/clip
|
||||
gap.** Live-DAT probe: the Skills credits value child (`0x100002f3`) is
|
||||
BASE-INHERITED across four sibling buttons of DIFFERING widths —
|
||||
Health/Stamina/Mana at 150px share the exact same child id/rect (local
|
||||
X=116) as the wider, 231px Skills credits button — and the child's own
|
||||
`OriginalParentWidth` (150, baked in wherever it was first resolved,
|
||||
matching Health's own actual width) diverges from Skills credits' real
|
||||
231px parent. `UiButton.ValueBox` was built from the child's RAW
|
||||
(un-reflowed) rect, never running it through `UiLayoutPolicy` — the SAME
|
||||
retail raw-edge system (`UIElement::UpdateForParentSizeChange
|
||||
@0x00462640`) already used for every LIVE mounted `UiElement` via
|
||||
`UiElement.ApplyAnchor`. The child's own edge modes (Left=2/Right=1,
|
||||
live-DAT-confirmed "track the far edge as the parent grows") shift the
|
||||
value box from X=116 to X=197 for Skills credits specifically — landing
|
||||
immediately after the caption's own measured 193px span (ends ≈x=196)
|
||||
instead of colliding mid-caption. Separately, `ValueAlign` mapped
|
||||
`HJustify.Right` (raw dat 3/5, live-DAT-confirmed authored on ALL four
|
||||
value children) to Center — `UIElement_Text::CalcJustification
|
||||
@0x00467260`'s own `ecx_5==3||5` branch is a DISTINCT far-edge formula,
|
||||
not Center's halved offset; added a `LabelAlignment.Right` case.
|
||||
Health/Stamina/Mana (whose `OriginalParentWidth` already matches their
|
||||
own actual width) reflow to their byte-identical raw rect — the fix is
|
||||
additive, not a per-button special case.
|
||||
Files: `src/AcDream.App/UI/Layout/DatWidgetFactory.cs` (`BuildButton`'s
|
||||
value-child block, new `ReflowValueChildRect`), `src/AcDream.App/UI/UiButton.cs`
|
||||
(`LabelAlignment.Right`, `OnDraw`'s value-draw `vx` switch). Tests:
|
||||
`DatWidgetFactoryTests.BuildButton_ValueChildBaseInheritedNarrowerParent_ReflowsToWiderButton`
|
||||
(+ its `..._OriginalParentMatchesActual_RectUnchanged` negative
|
||||
companion); live-DAT
|
||||
`CharacterCreationLiveDatTests.SkillsCreditsButton_ValueBoxReflowsPastCaption_HealthValueBoxUnchanged`
|
||||
(pins the real installed DAT's `197,0,34,28` vs `116,0,34,28`).
|
||||
- **R4-2 FIXED — the single-sprite-thumb fallback was TILING (UV-repeat)
|
||||
a small marker graphic instead of drawing it once.** The re-test-2 fix
|
||||
(R3-4/R3-7) correctly identified the thumb sprite but fed it to
|
||||
`DrawTiled` (GL_REPEAT UV wrap) — for a small fixed "diamond" marker
|
||||
drawn into a track-proportional thumb rect far taller than its own
|
||||
native size (`UIElement_Scrollbar::UpdateLayout @0x4710d0`'s
|
||||
`max(MinThumb, trackLen*ThumbRatio)` formula, unchanged/still correct
|
||||
for the rect's SIZE), the texture sampler repeated the marker several
|
||||
times down the track (~9 on Summary's overview bar, ~2 on Skills,
|
||||
matching the live capture). New `DrawThumbMarker` draws exactly ONE
|
||||
instance at the sprite's own native size, centered within the SAME
|
||||
computed rect — neither tiled (the bug) nor stretched into an elongated
|
||||
bar (a naive `DrawSprite` fix would have distorted the diamond shape).
|
||||
The shade slider's own scalar-mode draw path (`DrawVerticalScalar`) was
|
||||
never touched — it already used the correct native-size `DrawSprite`
|
||||
pattern this fix now mirrors for model-mode bars.
|
||||
File: `src/AcDream.App/UI/UiScrollbar.cs` (`DrawVerticalModel`/
|
||||
`DrawHorizontalModel`'s fallback branch, new `DrawThumbMarker`). Test:
|
||||
`UiScrollbarTests.SingleSpriteThumb_DrawsOneUntiledInstance_NotRepeatedDownTrack`
|
||||
— reads back the actual emitted quad's UV V-coordinate via
|
||||
`TextRenderer.DebugSpriteSegmentVerts` and asserts it never exceeds 1.0
|
||||
(native); confirmed this test FAILS (V=7.875) against the pre-fix
|
||||
`DrawTiled` call by temporarily reverting and re-running.
|
||||
- **R4-3 FIXED — the description pane's own authored box is genuinely
|
||||
taller than the decorative frame that visually contains it.** Live-DAT
|
||||
geometry walk: the gold frame (`0x100003fa`, the SAME GF-12 corner/edge
|
||||
sprite family as the Appearance help box) spans Y=430 H=110 (bottom
|
||||
Y=540), but the description pane (`0x100003fc`) spans Y=460 H=100
|
||||
(bottom Y=560) — 20px PAST the frame's own bottom border. Composition-
|
||||
height simulation against every one of the 38 skills carrying detail
|
||||
data (real `ChargenTableReader` descriptions + the worst-case
|
||||
description+bonus+formula line count) confirmed the pane's OWN raw
|
||||
100px interior comfortably fits every case (worst: 5 lines / 80px < 90px
|
||||
interior) — ruling out a wrap-width or line-spacing bug. The real
|
||||
mismatch is the SIBLING frame's smaller authored bottom, which the pane
|
||||
was never clamped to, letting a tall composition's last line(s) draw
|
||||
past the frame's own visible border into blank page space. Retail's
|
||||
`ShowSkillsText @0x00481250` has no code linking the panes to the frame
|
||||
(plain `SetText`, no size/clip handoff) — the frame's own authored Y+H
|
||||
is the only available ground truth, not a decomp-confirmed clip
|
||||
mechanism, so this is filed as register **AD-105** (a genuine
|
||||
inference, flagged rather than silently assumed, same shape as R3-3's
|
||||
own AD-104 scoped correction). `CharacterCreationSkillsPage`'s
|
||||
constructor now clamps `_infoText.Height` to the frame's bottom edge
|
||||
whenever it would otherwise be taller (additive; never grows it).
|
||||
File: `src/AcDream.App/UI/Layout/CharacterCreationSkillsPage.cs`
|
||||
(constructor, new `InfoBoxFrameElementId` clamp block). Tests: fixture
|
||||
`CharacterCreationUiControllerTests.SkillsPage_InfoBoxDescriptionPane_HeightClampedToFrameBottom`
|
||||
(the shared `BuildSkillsPage` fixture gained a deliberately-shorter
|
||||
frame element); live-DAT
|
||||
`CharacterCreationLiveDatTests.SkillsInfoBoxFrame_ShorterThanDescriptionPane`
|
||||
(pins the 20px real-DAT mismatch itself).
|
||||
- **R4-4 FIXED — two stacked gaps, the same "page never touched this
|
||||
element" shape as prior holdouts.** The help box (`0x100003ab`) is a
|
||||
purely DAT-authored static paragraph (no `gmCGAppearancePage` runtime
|
||||
composition function exists for it, unlike Town/Summary's
|
||||
`SetTownString`/`SetHowToText` — confirmed absent from the named
|
||||
decomp) that `CharacterCreationAppearancePage` never referenced at all,
|
||||
so it kept `UiText`'s own chat-style default
|
||||
(`PreserveEndOnLayout=true`, "keep a view that is already at the end
|
||||
pinned there"). Its content overflows a 292px-tall frame, and
|
||||
`UiScrollable.SetExtents`'s own `wasAtEnd` check is vacuously true the
|
||||
FIRST time a Scroll model transitions from its zero-initialized state
|
||||
(`ContentHeight=0/ViewHeight=0/ScrollY=0` → `MaxScroll=0` →
|
||||
`AtEnd=(0>=0)=true`) to real overflowing content — with
|
||||
`PreserveEndOnLayout` still true, that spuriously pins the very first
|
||||
render to the BOTTOM, hiding the opening paragraphs exactly as reported
|
||||
(the visible text is mid-way through the third paragraph). This is a
|
||||
static instructions box, not a chat transcript — `PreserveEndOnLayout`'s
|
||||
own doc already carves out exactly this shape ("top-oriented reports
|
||||
such as Character Information disable it"). Also wired the box's own
|
||||
NESTED authored scrollbar (property `0x72`, live-DAT-confirmed a direct
|
||||
Type-11 child of the text box — the SAME nesting shape
|
||||
`CharacterCreationSummaryPage.HowToScrollRelativeId` already uses) —
|
||||
never wired by this page before, so a user can reach the rest of the
|
||||
text even where the box's own height still doesn't fit everything.
|
||||
File: `src/AcDream.App/UI/Layout/CharacterCreationAppearancePage.cs`
|
||||
(constructor, new `HelpTextId`/`HelpScrollRelativeId` block). Tests:
|
||||
fixture
|
||||
`CharacterCreationUiControllerTests.AppearancePage_HelpText_TopOriented_AndOwnScrollbarIsWired`
|
||||
(the shared `BuildAppearancePage` fixture gained the help box + its
|
||||
nested scrollbar child, StateMedia-bearing so `UiText`'s own dat-
|
||||
children carve-out actually builds it).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue