fix(ui): Campaign LA gate round 2 — character-select scales as one authored canvas
Third iteration on the screen, completing AD-98. The previous substitution
stretched only the root BACKGROUND while the child widgets stayed at their
authored 800x600 pixel positions - and the background painting carries
visual anchors (the World/Characters captions are art), so the user gate
showed captions overlapping the listbox and every widget misaligned
against the stretched art.
Retail model (established at 71bf24fb): fixed-canvas pre-world screens
render at authored 800x600 and the whole composed frame stretches once at
presentation; the blitter has no stretch mode. Our equivalent now does the
same one stage earlier:
- UiRoot.FixedCanvasSize: while the char-select screen is active, the
retained tree lays out in its authored canvas and Draw scopes a uniform
scale onto TextRenderer.CanvasScale; the mouse entry points apply the
exact inverse so MouseX/MouseY and every hit test live in canvas space.
- TextRenderer.AppendQuad is the single emission chokepoint - sprites,
rects, AND glyphs scale together, including retail-authentic non-uniform
aspect distortion and stretched text. World-space HUD stays native (the
scale resets outside UiRoot.Draw).
- CharacterManagementUiController stops resizing Root to the viewport;
activate/deactivate/dispose set and clear the host canvas.
- UiDatElement returns to retail-pure copy-or-tile; the interim
StretchOwnBackgroundToFill flag is deleted.
- AD-98 updated to describe the completed substitution.
Tests: canvas-scale quad math, inverse input mapping (window click lands
on the canvas-space widget), degenerate-size guards, controller keeps
authored extent + sets/clears the canvas. App suite 5085/6 skips; live-DAT
char-select probes 3/3.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
71bf24fb6f
commit
73041d7015
8 changed files with 277 additions and 106 deletions
|
|
@ -38,6 +38,7 @@ internal sealed class CharacterManagementUiController : IDisposable
|
|||
private readonly List<UiButton> _rows = [];
|
||||
private readonly Dictionary<UiButton, uint> _rowIds = [];
|
||||
|
||||
private Vector2 _authoredCanvas;
|
||||
private RuntimeGenerationToken _lastGeneration;
|
||||
private long _lastRevision = long.MinValue;
|
||||
private uint _deleteDialogContext;
|
||||
|
|
@ -74,24 +75,22 @@ internal sealed class CharacterManagementUiController : IDisposable
|
|||
|
||||
Root.Left = 0f;
|
||||
Root.Top = 0f;
|
||||
Root.Anchors = AnchorEdges.Left | AnchorEdges.Top
|
||||
| AnchorEdges.Right | AnchorEdges.Bottom;
|
||||
if (host.Width > 0f)
|
||||
Root.Width = host.Width;
|
||||
if (host.Height > 0f)
|
||||
Root.Height = host.Height;
|
||||
Root.ClickThrough = false;
|
||||
Root.Visible = false;
|
||||
|
||||
// Campaign LA gate round 2: this root is resized to the live viewport just
|
||||
// above, which is bigger than its authored 800x600 canvas at almost every
|
||||
// real resolution. Its own DirectState background (RenderSurface 0x06007576)
|
||||
// must scale to fill that resized rect, not tile — see
|
||||
// UiDatElement.StretchOwnBackgroundToFill's doc comment for the retail
|
||||
// mechanism (a fixed-canvas screen stretched once at presentation) this
|
||||
// substitutes.
|
||||
if (Root is UiDatElement rootBackground)
|
||||
rootBackground.StretchOwnBackgroundToFill = true;
|
||||
// Campaign LA gate round 2 (register AD-98): the root KEEPS its authored
|
||||
// 800×600 extent — retail never resizes it (zero edge anchors, verified
|
||||
// against the installed DAT) and its blitter has no stretch mode; the
|
||||
// whole composed screen stretches once at presentation. Our equivalent:
|
||||
// while this screen is active, the host stretches the ENTIRE canvas —
|
||||
// widgets, glyphs, and the painted background (which carries the
|
||||
// "World"/"Characters" captions as art) — as one unit via
|
||||
// UiRoot.FixedCanvasSize. Resizing the root here instead is exactly the
|
||||
// half-substitution that misaligned the widgets against the stretched
|
||||
// art at the 2026-08-15 user gate.
|
||||
_authoredCanvas = new Vector2(
|
||||
Root.Width > 0f ? Root.Width : 800f,
|
||||
Root.Height > 0f ? Root.Height : 600f);
|
||||
|
||||
// Create Character belongs to a future campaign. Keep retail's
|
||||
// authored control in place and visibly ghosted; do not hide it or
|
||||
|
|
@ -246,6 +245,7 @@ internal sealed class CharacterManagementUiController : IDisposable
|
|||
{
|
||||
_active = true;
|
||||
Root.Visible = true;
|
||||
_host.FixedCanvasSize = _authoredCanvas;
|
||||
_host.BringToFront(Root);
|
||||
}
|
||||
|
||||
|
|
@ -310,6 +310,7 @@ internal sealed class CharacterManagementUiController : IDisposable
|
|||
}
|
||||
finally
|
||||
{
|
||||
_host.FixedCanvasSize = null;
|
||||
_enter.OnClick = null;
|
||||
_delete.OnClick = null;
|
||||
_restore.OnClick = null;
|
||||
|
|
@ -665,6 +666,7 @@ internal sealed class CharacterManagementUiController : IDisposable
|
|||
{
|
||||
_active = false;
|
||||
Root.Visible = false;
|
||||
_host.FixedCanvasSize = null;
|
||||
}
|
||||
foreach (UiButton row in _rows)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue