fix(ui): vendor dropdown polish — authored arrow-cap with open/closed flip, downward popup, left-aligned rows
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
Three gate findings, each settled by authored data rather than invention: the button face is retail's two-piece assembly and the 17x19 arrow-cap 0x1000034E now renders with its authored Normal(closed)/Highlight(open) states; the popup direction is an AUTHORED attribute (UIElement_Menu::Open pc:120210-120252 — bool attr 5, chat authors upward=true, the vendor menu authors nothing and defaults downward), so both menus are now byte-faithful with no special case; and the 19/20px text indents were chat-specific checkbox/LED clearances the vendor rows don't author — measured against the live retail font, "Spell Components" overflowed by 11px and now fits with 8px to spare. Chat's menu defaults are bit-identical and its tests untouched. AP-161's arrow-cap note closes. #351 files the pre-existing FarLoad Debug flake (three sightings today, never in clean-room Release). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5224e43890
commit
33b45ee581
5 changed files with 404 additions and 25 deletions
|
|
@ -176,18 +176,68 @@ public sealed class VendorUiController : IRetainedPanelController
|
|||
/// literally what vendor's OWN button-face child (<c>0x1000034D</c>)
|
||||
/// resolves to in the fixture, and <c>0x060012B4</c> (the row
|
||||
/// template's "Highlight" state) is the paired open/pressed look. This
|
||||
/// is a deliberate, bounded choice: retail's actual closed-button
|
||||
/// chrome is a separate two-piece label+arrow assembly
|
||||
/// (<c>0x1000034D</c> label + <c>0x1000034E</c> a 17x19 arrow cap with
|
||||
/// its own Normal/Highlight sprites <c>0x060012B1</c>/<c>0x060012B2</c>),
|
||||
/// and <see cref="UiMenu"/>'s existing single-texture 3-slice
|
||||
/// <c>DrawButtonFace</c> (end caps sized for chat's 46px LED-arrow
|
||||
/// texture) does not model a second overlaid arrow icon. Reworking
|
||||
/// <c>DrawButtonFace</c> into a two-piece label+arrow renderer would
|
||||
/// have meant redesigning UiMenu's draw model for a purely cosmetic
|
||||
/// gain while the actual reported bug (nothing renders at all) is
|
||||
/// fixed by this simpler substitution; the arrow glyph gap is recorded
|
||||
/// as a residual visual approximation (see the register, AP-161).
|
||||
/// remains a deliberate, bounded choice — <see cref="UiMenu"/>'s
|
||||
/// single-texture 3-slice <c>DrawButtonFace</c> (end caps sized for
|
||||
/// chat's 46px LED-arrow texture) is not redesigned into a two-piece
|
||||
/// label+arrow renderer for this plain gold body.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>G6 (vendor gate finding, item 1 — the missing green arrow
|
||||
/// indicator): closes the arrow-cap half of AP-161's residual.</b>
|
||||
/// Retail's actual closed-button chrome IS a separate two-piece
|
||||
/// label+arrow assembly — label <c>0x1000034D</c> (100x18, HJustify
|
||||
/// LEFT, verified via the fixture) + a SEPARATE 17x19 arrow-cap image
|
||||
/// <c>0x1000034E</c> docked at the button's right edge (X=100,Y=0
|
||||
/// within the 117-wide button), with its own Normal/Highlight states
|
||||
/// resolving to <c>0x060012B1</c> (closed)/<c>0x060012B2</c> (open) —
|
||||
/// verified live via <c>tools/VendorLayoutScan</c>'s <c>resolved</c>
|
||||
/// command reading the element's two StateMedia images directly out of
|
||||
/// <c>client_local_English.dat</c>. <see cref="UiMenu.ArrowCapClosedSprite"/>/
|
||||
/// <see cref="UiMenu.ArrowCapOpenSprite"/> draw this AS AN OVERLAY on top
|
||||
/// of the existing 3-slice body (additive, not a DrawButtonFace rewrite)
|
||||
/// so the green arrow now flips down (closed)/up (open) exactly like
|
||||
/// retail, without touching chat's face (whose arrow is baked into its
|
||||
/// own texture and never sets these).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>G7 (vendor gate finding, item 2 — the popup opened upward instead
|
||||
/// of downward).</b> Retail's <c>UIElement_Menu::Open</c>
|
||||
/// (<c>pc:120210-120252</c>, <c>0x0046cc30</c>) places the popup at
|
||||
/// <c>ScreenY1(button)</c> (the button's own BOTTOM edge — i.e. BELOW
|
||||
/// it) unless the menu authors bool attribute 5 true, in which case it
|
||||
/// places it at <c>ScreenY0(button) - popupHeight</c> (ABOVE).
|
||||
/// <c>UIElement::GetAttribute_Bool</c> (<c>pc:106749-106778</c>) defaults
|
||||
/// an ABSENT attribute to false. Element <c>0x100000BF</c>'s resolved
|
||||
/// attribute bag (the same fixture cited throughout this doc) carries NO
|
||||
/// property "5" at all — unlike chat's channel menu (<c>0x10000014</c> in
|
||||
/// LayoutDesc <c>0x21000006</c>), which explicitly authors property "5" =
|
||||
/// <c>true</c>. So retail opens vendor's dropdown DOWNWARD and chat's
|
||||
/// UPWARD — two different authored choices, not one hardcoded direction.
|
||||
/// <see cref="UiMenu.OpenUpward"/> (default <c>true</c>, preserving
|
||||
/// chat's untouched behavior) is set <c>false</c> here to match.
|
||||
/// Retail's <c>Open</c> has no dynamic screen-edge clamp or flip of its
|
||||
/// own — the direction is the fixed authored attribute, full stop — so
|
||||
/// none is added here either; see <see cref="UiMenu.OpenUpward"/>'s own
|
||||
/// doc for the citation.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>G8 (vendor gate finding, item 3 — popup/button text overflowing
|
||||
/// instead of sitting flush left).</b> <see cref="UiMenu.TextIndent"/>
|
||||
/// (19px) and <see cref="UiMenu.ButtonTextIndent"/> (20px) are CHAT's
|
||||
/// own authored offsets — clearing space for a baked-in row checkbox and
|
||||
/// a button-face LED socket, respectively. Vendor's row template
|
||||
/// (<c>0x10000352</c>, live-dat verified <c>HJustify=Left</c>) has no
|
||||
/// checkbox child at all, and vendor's button label child
|
||||
/// (<c>0x1000034D</c>) is itself <c>HJustify=Left</c> at X=0 with no LED
|
||||
/// art — so both indents are set to 0 here, retail's own left-justified
|
||||
/// <c>UiText</c> convention for an icon-less label (every OTHER
|
||||
/// dat-driven <c>UiText</c> in this codebase sets <c>Padding=0f</c>).
|
||||
/// Reusing chat's 19px row indent measurably overflowed the authored
|
||||
/// 100px-wide row: the longest category label, "Spell Components",
|
||||
/// measures 92px at the default retail font (<c>Font 0x40000000</c>,
|
||||
/// live-measured via <c>tools/VendorLayoutScan measure</c>) —
|
||||
/// 19+92=111px > the 100px row, an 11px overflow; with 0px it fits
|
||||
/// with 8px to spare.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
private const int TypeMenuRowsPerColumn = 6;
|
||||
|
|
@ -197,6 +247,10 @@ public sealed class VendorUiController : IRetainedPanelController
|
|||
private const uint TypeMenuItemHighlightSprite = 0x060012B4u;
|
||||
private const uint TypeMenuNormalSprite = 0x060012B3u;
|
||||
private const uint TypeMenuPressedSprite = 0x060012B4u;
|
||||
// G6: the separate arrow-cap overlay (element 0x1000034E) — see the
|
||||
// class doc's "G6" paragraph above.
|
||||
private const uint TypeMenuArrowCapClosedSprite = 0x060012B1u;
|
||||
private const uint TypeMenuArrowCapOpenSprite = 0x060012B2u;
|
||||
|
||||
// G5 (vendor gate finding): the popup's docked scrollbar (element
|
||||
// 0x10000351, verified via tools/VendorLayoutScan against the live dat —
|
||||
|
|
@ -413,6 +467,22 @@ public sealed class VendorUiController : IRetainedPanelController
|
|||
_typeMenu.ScrollThumbBottomSprite = TypeMenuScrollThumbBottomSprite;
|
||||
_typeMenu.ScrollUpSprite = TypeMenuScrollUpSprite;
|
||||
_typeMenu.ScrollDownSprite = TypeMenuScrollDownSprite;
|
||||
// G6: the separate open/closed arrow-cap overlay — see the class
|
||||
// doc's "G6" paragraph above.
|
||||
_typeMenu.ArrowCapClosedSprite = TypeMenuArrowCapClosedSprite;
|
||||
_typeMenu.ArrowCapOpenSprite = TypeMenuArrowCapOpenSprite;
|
||||
// G7: retail authors NO bool attribute 5 on this menu, so
|
||||
// UIElement_Menu::Open's absent-defaults-false path opens the popup
|
||||
// DOWNWARD (ScreenY1, the button's own bottom edge) — see the class
|
||||
// doc's "G7" paragraph above. Chat's own menu is unaffected (its
|
||||
// controller never touches this property, leaving UiMenu's true
|
||||
// default).
|
||||
_typeMenu.OpenUpward = false;
|
||||
// G8: vendor's row/button-label children carry no checkbox/LED art
|
||||
// to clear (unlike chat's), so both indents are flush-left (0) —
|
||||
// see the class doc's "G8" paragraph above.
|
||||
_typeMenu.TextIndent = 0f;
|
||||
_typeMenu.ButtonTextIndent = 0f;
|
||||
_typeMenu.OnSelect = payload =>
|
||||
{
|
||||
if (payload is uint mask) SelectCategory(mask);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue