Port the authored effect row template, remaining-time and selection details, synchronize the full gmPanelUI child geometry, and route the burden indicator to Character Information panel 3. Co-authored-by: OpenAI Codex <codex@openai.com>
5.6 KiB
Retail shared main-panel geometry — pseudocode
Date: 2026-07-17 Symptom: moving Inventory and then opening Character/Skills or Magic opens the new panel at its own stale saved position instead of the position just used.
Retail oracle
Named Sept-2013 retail symbols:
gmPanelUI::SetupChildren @ 0x004BC9E0gmPanelUI::RecvNotice_SetPanelVisibility @ 0x004BC6F0gmPanelUI::PostInit @ 0x004BD010gmPanelUI::ResizeTo @ 0x004BC6E0
Verbatim acclient.h ownership:
gmPanelUI : UIElement_Field
SmartArray<PanelChildInfo> m_childrenInfoArray
UIElement* m_currentlyShownPanel
UIElement* m_previouslyShownPanel
UIElement* m_pPanelPagesFrame
bool m_bStretchMode
PanelChildInfo
UIElement* child
uint panelID
SetupChildren resolves each known panel element recursively, stores the
child pointer together with its property-0x10000029 panel ID, and initially
hides every child. It does not create independent top-level windows.
Retail behavior
SetPanelVisibility(panelId, show):
requested = find m_childrenInfoArray entry by panelId
if requested is missing:
return
if show:
if requested.child == m_currentlyShownPanel:
requested.child.SetVisible(true)
parent.SetVisible(true)
return
previous = m_currentlyShownPanel
m_currentlyShownPanel = requested.child
if previous is visible:
if requested restores previous and previous does not:
m_previouslyShownPanel = previous
else:
m_previouslyShownPanel = null
send SetPanelVisibility(previous.panelID, false)
requested.child.SetVisible(true)
parent.SetVisible(true)
return
if requested.child == m_currentlyShownPanel:
requested.child.SetVisible(false)
if m_previouslyShownPanel exists:
send SetPanelVisibility(previous.panelID, true)
m_previouslyShownPanel = null
else:
m_currentlyShownPanel = null
parent.SetVisible(false)
return
requested.child.SetVisible(false)
The decisive geometry fact is structural: Inventory, Character Information,
Character/Skills, Magic, Effects, and the other detail pages are children of
one gmPanelUI. The switch changes child visibility; there is no child move,
resize, or per-panel top-level rectangle. Moving or resizing the parent
therefore changes the one rectangle subsequently used by every child.
Resize follow-up
The production end-of-retail LayoutDesc supplies the missing geometry oracle:
LayoutDesc 0x2100006E
gmPanelUI host 0x100005FE 310 x 372
content parent 0x10000180 300 x 362, anchored on all edges
Character Information 0x10000183 panel 3, 300 x 362
Helpful Effects 0x10000184 panel 4, 300 x 362
Harmful Effects 0x10000185 panel 5, 300 x 362
Inventory child 0x1000018B panel 7, 300 x 362
Character/Skills child 0x1000018E panel 11, 300 x 362
Magic child 0x10000190 panel 13, 300 x 362
top-center 0x1000065C Type 2 Dragbar, cursor 0x06006119
bottom-center 0x10000660 Type 9 Resizebar, cursor 0x06005E66
Every primary child therefore participates in the shared host's vertical
resize; Magic is not a fixed-height exception. Named
gmPanelUI::ResizeTo @ 0x004BC6E0 delegates directly to
UIElement::ResizeTo @ 0x00463C30, whose only size limits are effective DAT
properties 0x3C..0x3F. There is no retail 760-pixel Character limit and no
maximum captured from the host's original screen position.
acdream retains independent wrappers under IA-12, so the faithful adaptation is to give each registered child wrapper the same bottom-only vertical resize policy, leave its maximum unbounded by an authored substitute, and calculate the available desktop extent from its current position during the resize. The viewport remains the physical limit; an old static maximum must not become a smaller limit after the shared panel moves.
acdream port shape
acdream imports these child LayoutDesc roots independently, so each currently
has its own retained wrapper. RetailPanelUiController already ports retail's
one-active-child and restore-previous lifecycle. Complete that logical-parent
ownership by adding one canonical rectangle for all registered main-panel
children, including Character Information 3, Helpful/Harmful 4/5,
Inventory 7, Character/Skills 11, and Magic 13:
on registered child frame moved or resized:
canonicalGeometry = frame left, top, width, height
apply canonicalGeometry to every hidden sibling
before showing a registered child:
if canonicalGeometry exists:
apply canonicalGeometry to requested child frame
else:
canonicalGeometry = requested child frame geometry
before hiding the active child:
capture its current geometry as canonicalGeometry
The controller owns this synchronization and subscribes to typed
RetailWindowHandle.Moved and Resized events. Toolbar, indicator, and
keyboard commands, restore-previous effects, persistence restore, and direct
window dragging all therefore pass through the same owner. Each wrapper
retains its own imported content tree, but its outer rectangle and bottom-only
resize contract mirror the shared retail host.
ACE contains no client UI implementation, and the in-tree WorldBuilder
reference contains no gmPanelUI port, so neither supplies a competing
behavioral interpretation. The named retail client and verbatim header are the
oracle for this UI ownership rule.