fix(ui): round-5 review polish — S1 block outline pass, S2 non-UiText outline paths, S3 citation fix

Collects the post-gate polish left uncommitted by the killed round-5 agent
(S1/S3 + review fixes N1/N3/N4) and completes the missing S2 half:

- S1: UiText multi-line transcript + colored-run label now submit EVERY
  line/run's outline pass before ANY fill pass, matching retail's
  UIElement_Text::DrawSelf @0x00467aa0 whole-block walk. DrawStringDatPass
  is exposed for block-level batching; single lines keep DrawStringDat.
- S2 (completed this commit): authored outline 0x21/0x22 now reaches every
  text-bearing widget — UiButton, UiDatElement, UiField, UiMeter, UiMenu,
  UiCatalogSlot — seeded from the element's effective-default state exactly
  like UiText (BuildButton lifts the label-bearing Text child's authored
  value first, same chain as the label color). Per-STATE outline switching
  (dialog/character/combat buttons author 0x21 in state 0x3 only) is NOT
  ported — filed as register row AP-192 in this commit.
- S3: ChatWindowController reconciliation comment corrects the misread
  indicator action ids 0x10000514-17 -> 0x10000114-17 and re-attributes the
  id-coincidence to the pagination widget's m_prevButton/m_nextButton, not
  gmFriendsUI; register + window-shell research doc corrected to match.
- N1: LayoutImporter's duplicate per-state any-state-first-wins 0x21 read is
  deleted — ElementReader.ApplyCanonicalLegacyProjection's DirectState-then-
  effective-default resolution is the single source (the duplicate would have
  lit state-0x3-only outlines permanently once S2 widened consumption).
- N3: the outline pass tints with the outline color's OWN alpha, not the
  fill's (retail tints m_curOutlineColor and m_curTextColor independently).
- N4: the outline-inflated glyph SOURCE rect is clamped to the atlas bounds
  with matching dest shrink, porting CreateCharRectPair @0x00441480's edge
  behavior — edge glyphs crop instead of sampling a neighbour's texels.

Full Release suite: 12,610 passed / 4 skipped / 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-10 22:15:20 +02:00
parent ed0dbff90a
commit aa6635aebf
14 changed files with 258 additions and 66 deletions

View file

@ -389,7 +389,11 @@ public static class DatWidgetFactory
ElementId = info.Id,
SpriteResolve = resolve,
DatFont = datFont,
// Outline 0x21 from the meter element (round-5 review S2).
Outline = info.Outline,
};
if (info.OutlineColor.HasValue)
m.OutlineColor = info.OutlineColor.Value;
// The two 3-slice containers are Type-3 children of the meter element.
// ReadOrder determines draw order: the back track has a LOWER ReadOrder
@ -574,11 +578,15 @@ public static class DatWidgetFactory
OneLine = oneLine,
Centered = info.HJustify == HJustify.Center,
RightAligned = info.HJustify == HJustify.Right,
// Outline 0x21 from the field element (round-5 review S2).
Outline = info.Outline,
};
if (info.TryGetEffectiveInteger(0x1Eu, out int maxCharacters))
field.MaxCharacters = maxCharacters;
if (info.FontColor.HasValue)
field.TextColor = info.FontColor.Value;
if (info.OutlineColor.HasValue)
field.OutlineColor = info.OutlineColor.Value;
return field;
}
@ -683,7 +691,13 @@ public static class DatWidgetFactory
LabelFont = labelFont,
LabelColor = labelInfo.FontColor ?? info.FontColor
?? System.Numerics.Vector4.One,
// Outline 0x21 / OutlineColor 0x22 follow the same lift chain as the label
// and its color: the label-bearing Text child's authored value first, the
// button's own second (round-5 review S2).
Outline = labelInfo.Outline || info.Outline,
};
if ((labelInfo.OutlineColor ?? info.OutlineColor) is { } buttonOutlineColor)
button.OutlineColor = buttonOutlineColor;
if (face is not null)
{
@ -724,7 +738,11 @@ public static class DatWidgetFactory
: elementFont,
LabelColor = info.FontColor ?? System.Numerics.Vector4.One,
LabelAlign = UiButton.LabelAlignment.Left,
// Outline 0x21 from the checkbox element itself (round-5 review S2).
Outline = info.Outline,
};
if (info.OutlineColor.HasValue)
button.OutlineColor = info.OutlineColor.Value;
if (indicator is not null)
{