feat(ui): importer carries dat FontColor (0x1B) onto text widgets; character colors from dat where present

LayoutImporter.ReadState now reads Properties 0x1B (ColorBaseProperty, ARGB bytes) and stores the normalized Vector4 in ElementInfo.FontColor (nullable). ElementReader.Merge propagates it with the same non-null-derived-wins rule as FontDid and HJustify. DatWidgetFactory.BuildText seeds UiText.DefaultColor from FontColor when present.

Diagnosis for LayoutDesc 0x2100002E: ALL 12 header and footer text elements carry NO dat color. Every color is runtime set by CharacterStatController. Comments added at each callsite. No hardcoded colors deleted.

Tests added: 3 ElementReader FontColor Merge + 3 DatWidgetFactory DefaultColor. 702 passed, 0 failed. Screenshots: character window, vitals, toolbar all unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-26 10:15:55 +02:00
parent 41430420b3
commit 6e0be4bd34
7 changed files with 154 additions and 1 deletions

View file

@ -45,6 +45,19 @@ public sealed class UiText : UiElement
/// the host from <see cref="UiHost.Keyboard"/>.</summary>
public Silk.NET.Input.IKeyboard? Keyboard { get; set; }
/// <summary>
/// Default line color used by controllers when they do not supply a per-line
/// <see cref="Vector4"/> color explicitly. Set by <c>DatWidgetFactory.BuildText</c>
/// from <c>ElementInfo.FontColor</c> when the dat carries a 0x1B ColorBaseProperty;
/// otherwise white (<see cref="Vector4.One"/>).
///
/// <para>Controllers that supply a per-line color via <see cref="LinesProvider"/>
/// (e.g. <c>new UiText.Line(text, explicitColor)</c>) are unaffected — they always
/// win over this default. This property is only a convenience starting point for
/// controllers that want to read the dat color rather than hard-code it.</para>
/// </summary>
public Vector4 DefaultColor { get; set; } = Vector4.One;
/// <summary>Backing fill behind the text. Defaults to transparent so an unbound
/// UiText (no controller) draws nothing. Set to the retail translucent value by
/// the controller (e.g. <c>ChatWindowController</c>).</summary>