From a236dc33ac2b747324620ba1c1a3933b01410721 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 26 Jun 2026 02:22:00 +0200 Subject: [PATCH] =?UTF-8?q?fix(studio):=20Character=20window=20=E2=80=94?= =?UTF-8?q?=20larger=20row=20text=20+=20tighter=20attribute=20rows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RowHeight reduced 44→30px to pack the 9 rows tighter, matching retail's denser list - Attribute row name/value text now uses Font 0x40000001 (MaxCharHeight=18px) instead of the default 0x40000000 (16px); both fonts are in client_portal.dat (confirmed 2026-06-26) - RenderStack gains LargeDatFont field; RenderBootstrap.Create loads both fonts - FixtureProvider passes LargeDatFont as rowDatFont to CharacterStatController.Bind - CharacterStatController.Bind gains rowDatFont? parameter (falls back to datFont); passed to BuildAttributeRows so row UiText elements use the larger font - Full solution tests green (681/683 App + 1579/1581 Core + 343 Net + 425 UI) Co-Authored-By: Claude Sonnet 4.6 --- src/AcDream.App/Rendering/RenderBootstrap.cs | 12 ++++++++++-- src/AcDream.App/Studio/FixtureProvider.cs | 3 +++ src/AcDream.App/UI/Layout/CharacterStatController.cs | 11 +++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/AcDream.App/Rendering/RenderBootstrap.cs b/src/AcDream.App/Rendering/RenderBootstrap.cs index 6a23a0d2..6a896861 100644 --- a/src/AcDream.App/Rendering/RenderBootstrap.cs +++ b/src/AcDream.App/Rendering/RenderBootstrap.cs @@ -22,7 +22,8 @@ public sealed record RenderStack( Wb.WbDrawDispatcher DrawDispatcher, SceneLightingUboBinding LightingUbo, AcDream.App.UI.UiHost UiHost, - AcDream.App.UI.UiDatFont? VitalsDatFont) : System.IDisposable + AcDream.App.UI.UiDatFont? VitalsDatFont, + AcDream.App.UI.UiDatFont? LargeDatFont) : System.IDisposable { /// Dispose the GL pieces this stack OWNS (everything created in /// ). + are caller-owned @@ -147,6 +148,12 @@ public static class RenderBootstrap // --- Vitals dat font (GameWindow ~1820-1822) --- var vitalsDatFont = AcDream.App.UI.UiDatFont.Load(dats, textureCache); + // --- Larger retail font (0x40000001, MaxCharHeight=18) for attribute row text. + // The default font (0x40000000, 16px) renders the row names too small; the 18px + // variant (confirmed in client_portal.dat 2026-06-26) matches the retail character + // window list more closely (≈ icon height ≈ 24px target, 18px is best available). + var largeDatFont = AcDream.App.UI.UiDatFont.Load(dats, textureCache, 0x40000001u); + // --- UiHost (GameWindow ~1790); pass null for debugFont (only used as // a fallback BitmapFont for the world-space HUD — not needed for the // UI Studio, and BitmapFont requires a system font byte array) --- @@ -164,7 +171,8 @@ public static class RenderBootstrap DrawDispatcher: drawDispatcher, LightingUbo: lightingUbo, UiHost: uiHost, - VitalsDatFont: vitalsDatFont); + VitalsDatFont: vitalsDatFont, + LargeDatFont: largeDatFont); } // NullAnimLoader mirrors GameWindow's private NullAnimLoader (GameWindow ~13327-13330). diff --git a/src/AcDream.App/Studio/FixtureProvider.cs b/src/AcDream.App/Studio/FixtureProvider.cs index d2d537a7..75956370 100644 --- a/src/AcDream.App/Studio/FixtureProvider.cs +++ b/src/AcDream.App/Studio/FixtureProvider.cs @@ -118,10 +118,13 @@ public static class FixtureProvider // Bind the REAL importer-mounted header + list elements (name/heritage/PK/level/ // total-XP/XP-meter + the 9-row attribute list + footer State-A). NOT the text-report // sub-panel (that is gmCharacterInfoUI 0x2100001A → CharacterController). + // LargeDatFont (0x40000001, MaxCharHeight=18) is used for the attribute row text; + // fallback to VitalsDatFont (0x40000000, 16px) if unavailable. CharacterStatController.Bind( layout, data: SampleData.SampleCharacter, datFont: stack.VitalsDatFont, + rowDatFont: stack.LargeDatFont ?? stack.VitalsDatFont, spriteResolve: stack.ResolveChrome); break; diff --git a/src/AcDream.App/UI/Layout/CharacterStatController.cs b/src/AcDream.App/UI/Layout/CharacterStatController.cs index a6763740..867a5866 100644 --- a/src/AcDream.App/UI/Layout/CharacterStatController.cs +++ b/src/AcDream.App/UI/Layout/CharacterStatController.cs @@ -128,7 +128,10 @@ public static class CharacterStatController private static readonly Vector4 HighlightBg = new(1f, 0.75f, 0.2f, 0.25f); // ── Row layout constants ───────────────────────────────────────────────── - private const float RowHeight = 44f; + // RowHeight reduced from 44 to 30px to match retail's tighter attribute list. + // The larger row font (0x40000001, MaxCharHeight=18) fits in 30px with 6px total vertical + // padding (3px above/below). Retail spec (2026-06-26 ref): "rows tighter, text ≈ icon height". + private const float RowHeight = 30f; private const float IconSize = 24f; private const float RowPadX = 4f; private const float IconGap = 6f; @@ -172,8 +175,12 @@ public static class CharacterStatController ImportedLayout layout, Func data, UiDatFont? datFont = null, + UiDatFont? rowDatFont = null, Func? spriteResolve = null) { + // rowDatFont: larger font for attribute row name/value text (18px vs 16px default). + // Falls back to datFont when null (tests, or dat missing). + rowDatFont ??= datFont; // Name: retail "Horan" is WHITE, not gold. Heritage and PK status are also white. Label(layout, NameId, datFont, Vector4.One, () => data().Name); Label(layout, HeritageId, datFont, Body, () => data().Heritage ?? data().Race ?? string.Empty); @@ -348,7 +355,7 @@ public static class CharacterStatController if (layout.FindElement(ListBoxId) is { } list) { - rowPanels = BuildAttributeRows(list, datFont, spriteResolve, data, sel, + rowPanels = BuildAttributeRows(list, rowDatFont, spriteResolve, data, sel, allRaise1, allRaise10); }