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:
parent
41430420b3
commit
6e0be4bd34
7 changed files with 154 additions and 1 deletions
|
|
@ -1,3 +1,4 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
namespace AcDream.App.Tests.UI.Layout;
|
||||
|
|
@ -299,4 +300,55 @@ public class DatWidgetFactoryTests
|
|||
t.Centered = false; // controller override
|
||||
Assert.False(t.Centered); // override wins
|
||||
}
|
||||
|
||||
// ── DefaultColor from dat FontColor (importer Fix B) ─────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// When ElementInfo.FontColor is set (dat carried 0x1B ColorBaseProperty),
|
||||
/// DatWidgetFactory.BuildText must copy it onto UiText.DefaultColor.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BuildText_FontColorPresent_SetsDefaultColor()
|
||||
{
|
||||
var gold = new Vector4(1f, 0.82f, 0.36f, 1f);
|
||||
var info = new ElementInfo { Type = 12, Width = 100, Height = 20, FontColor = gold };
|
||||
var t = Assert.IsType<UiText>(DatWidgetFactory.Create(info, NoTex, null));
|
||||
Assert.Equal(gold, t.DefaultColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When ElementInfo.FontColor is null (dat carried no 0x1B), DefaultColor must
|
||||
/// stay at white (Vector4.One) — the backward-compatible default.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BuildText_FontColorAbsent_DefaultColorIsWhite()
|
||||
{
|
||||
var info = new ElementInfo { Type = 12, Width = 100, Height = 20, FontColor = null };
|
||||
var t = Assert.IsType<UiText>(DatWidgetFactory.Create(info, NoTex, null));
|
||||
Assert.Equal(Vector4.One, t.DefaultColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backward-compat guarantee: a controller that sets LinesProvider with an
|
||||
/// explicit per-line color AFTER build is unaffected by DefaultColor.
|
||||
/// The controller's per-line color is stored in the Line record, not DefaultColor,
|
||||
/// so DefaultColor changing from dat does not touch existing controller bindings.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BuildText_ControllerExplicitLineColor_UnaffectedByDefaultColor()
|
||||
{
|
||||
// Dat sets a parchment color.
|
||||
var parchment = new Vector4(0.92f, 0.90f, 0.82f, 1f);
|
||||
var info = new ElementInfo { Type = 12, Width = 100, Height = 20, FontColor = parchment };
|
||||
var t = Assert.IsType<UiText>(DatWidgetFactory.Create(info, NoTex, null));
|
||||
|
||||
// Controller overrides with an explicit gold color in the Line record.
|
||||
var gold = new Vector4(1f, 0.82f, 0.36f, 1f);
|
||||
t.LinesProvider = () => new[] { new UiText.Line("text", gold) };
|
||||
|
||||
// The line's color is gold (controller wins), NOT the dat parchment.
|
||||
Assert.Equal(gold, t.LinesProvider()[0].Color);
|
||||
// DefaultColor still holds the dat parchment (unmodified by the controller binding).
|
||||
Assert.Equal(parchment, t.DefaultColor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
namespace AcDream.App.Tests.UI.Layout;
|
||||
|
|
@ -214,4 +215,45 @@ public class ElementReaderTests
|
|||
var merged = ElementReader.Merge(base_, derived);
|
||||
Assert.Equal(VJustify.Bottom, merged.VJustify);
|
||||
}
|
||||
|
||||
// ── FontColor — Merge propagation (Fix B) ────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// When the derived element has an explicit (non-null) FontColor, the derived value
|
||||
/// wins in Merge — same "non-null derived wins" rule used for FontDid and HJustify.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Merge_DerivedFontColor_OverridesBaseNull()
|
||||
{
|
||||
var base_ = new ElementInfo { FontColor = null };
|
||||
var derived = new ElementInfo { FontColor = new Vector4(1f, 0f, 0f, 1f) };
|
||||
var merged = ElementReader.Merge(base_, derived);
|
||||
Assert.Equal(new Vector4(1f, 0f, 0f, 1f), merged.FontColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the derived element has no FontColor (null), the base's FontColor is inherited.
|
||||
/// A null-derived must NOT override a non-null base.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Merge_DerivedFontColorNull_InheritsBaseColor()
|
||||
{
|
||||
var gold = new Vector4(1f, 0.82f, 0.36f, 1f);
|
||||
var base_ = new ElementInfo { FontColor = gold };
|
||||
var derived = new ElementInfo { FontColor = null }; // default — no dat property
|
||||
var merged = ElementReader.Merge(base_, derived);
|
||||
Assert.Equal(gold, merged.FontColor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When neither base nor derived carries a FontColor, the merged result is null.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Merge_BothFontColorNull_MergedIsNull()
|
||||
{
|
||||
var base_ = new ElementInfo { FontColor = null };
|
||||
var derived = new ElementInfo { FontColor = null };
|
||||
var merged = ElementReader.Merge(base_, derived);
|
||||
Assert.Null(merged.FontColor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue