diff --git a/src/AcDream.App/UI/Layout/DatWidgetFactory.cs b/src/AcDream.App/UI/Layout/DatWidgetFactory.cs index 6a44d86b..4bb9ef62 100644 --- a/src/AcDream.App/UI/Layout/DatWidgetFactory.cs +++ b/src/AcDream.App/UI/Layout/DatWidgetFactory.cs @@ -49,15 +49,25 @@ public static class DatWidgetFactory public static UiElement? Create(ElementInfo info, Func resolve, UiDatFont? datFont) { + // Retail Type 3 = UIElement_Field (reg :126190), but in acdream's CURRENT layouts + // (vitals 0x2100006C / chat 0x21000006) Type-3 elements are sprite-bearing chrome + + // containers (the 8-piece bevel corners/edges, the transcript/input panels), NOT + // editable fields — retail draws those as inert media-bearing Fields, which our + // UiDatElement reproduces pixel-for-pixel (and without the spurious focus/edit + // affordance a UiField would add). The one true editable field, the chat input + // (0x10000016), resolves to Type 12 and is controller-placed as a UiField. So Type 3 + // stays on the generic fallback here; register it as UiField only when a window + // actually carries a factory-built editable Type-3 field (and UiField grows a + // background-media draw + an opt-in editable flag at that point). UiField (the widget) + // still ships — it just isn't wired into the factory switch yet. UiElement e = info.Type switch { 1 => new UiButton(info, resolve), // UIElement_Button (reg :125828) - 3 => new UiField(), // UIElement_Field (reg :126190) 6 => new UiMenu(), // UIElement_Menu (reg :120163) 7 => BuildMeter(info, resolve, datFont), // UIElement_Meter 11 => new UiScrollbar(), // UIElement_Scrollbar (reg :124137) 12 => BuildText(info, resolve), // UIElement_Text (reg :115655) - _ => new UiDatElement(info, resolve), // generic fallback for all other types + _ => new UiDatElement(info, resolve), // generic fallback (incl. Type 3 chrome/containers) }; // Propagate position + size (pixel-exact from the dat). diff --git a/tests/AcDream.App.Tests/UI/Layout/DatWidgetFactoryTests.cs b/tests/AcDream.App.Tests/UI/Layout/DatWidgetFactoryTests.cs index 05f4929a..ce7e63f9 100644 --- a/tests/AcDream.App.Tests/UI/Layout/DatWidgetFactoryTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/DatWidgetFactoryTests.cs @@ -100,13 +100,21 @@ public class DatWidgetFactoryTests Assert.IsType(e); } - // ── Test 5e: Type 3 → UiField ──────────────────────────────────────────── + // ── Test 5e: Type 3 is NOT registered — chrome/containers stay generic ──── + // + // Retail Type 3 = UIElement_Field, but acdream's Type-3 dat elements (vitals/chat + // bevel chrome + the transcript/input container panels) are inert sprite-bearing + // chrome, not editable fields. They stay on the UiDatElement fallback so their + // sprites render and they gain no spurious focus/edit affordance. The one true + // editable field (the chat input, 0x10000016) resolves to Type 12 and is + // controller-placed as a UiField. Register Type 3 → UiField only when a window + // carries a factory-built editable Type-3 field. [Fact] - public void Type3_Field_MakesUiField() + public void Type3_NotRegistered_FallsBackToGeneric() { var e = DatWidgetFactory.Create(new ElementInfo { Type = 3, Width = 200, Height = 16 }, NoTex, null); - Assert.IsType(e); + Assert.IsType(e); } // ── Test 5d: Type 6 → UiMenu ───────────────────────────────────────────── diff --git a/tests/AcDream.App.Tests/UI/Layout/LayoutConformanceTests.cs b/tests/AcDream.App.Tests/UI/Layout/LayoutConformanceTests.cs index e56839d9..ba336aac 100644 --- a/tests/AcDream.App.Tests/UI/Layout/LayoutConformanceTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/LayoutConformanceTests.cs @@ -76,20 +76,18 @@ public class LayoutConformanceTests } } - // ── Test 3: Chrome TL corner type ──────────────────────────────────────── + // ── Test 3: Chrome TL corner sprite ─────────────────────────────────────── // - // NOTE: As of Task 6 (widget-generalization), Type-3 elements are built as - // UiField (UIElement_Field, reg :126190) rather than UiDatElement. The - // chrome corner (0x10000633) is a Type-3 dat element and is now a UiField. - // Its dat sprite (0x060074C3) is not rendered by UiField — UiField renders - // the focused/unfocused field background only. The sprite rendering for - // Type-3 chrome image elements is a known limitation; tracked for post-Task-8 - // follow-up (UiField could expose a BackgroundSprite similar to UiText). + // NOTE: Type 3 is retail UIElement_Field, but acdream's Type-3 elements here are + // sprite-bearing CHROME (the 8-piece bevel corners), so they stay on the generic + // UiDatElement fallback (NOT registered as UiField in the factory — see + // DatWidgetFactory.Create). This test guards that the chrome corner keeps drawing + // its dat sprite; if a future change routes Type 3 → UiField, the corner sprite + // would vanish and this assertion fails — which is the intended early warning. /// - /// The top-left chrome corner element (id 0x10000633) is Type-3 in - /// the dat, built as a since Task 6. Confirms the - /// element exists in the tree. + /// The top-left chrome corner element (id 0x10000633) must be a + /// whose active media file id is 0x060074C3. /// [Fact] public void VitalsTree_ChromeCornerHasExpectedSprite() @@ -98,8 +96,9 @@ public class LayoutConformanceTests var elem = layout.FindElement(0x10000633u); Assert.NotNull(elem); - // Type-3 elements are now built as UiField (UIElement_Field, Task 6). - Assert.IsType(elem); + var datElem = Assert.IsType(elem); + var (file, _) = datElem.ActiveMedia(); + Assert.Equal(0x060074C3u, file); } // ── Test 4 (N4): Inheritance resolution — FontDid propagated from base ───