fix(ui): complete retail indicator detail panels
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>
This commit is contained in:
parent
a96767ba6d
commit
d1d603105f
24 changed files with 3696 additions and 147 deletions
|
|
@ -569,6 +569,8 @@ negative root 0x10000121 (inherits 0x10000122)
|
|||
shared effects template 0x10000122
|
||||
effect list 0x10000123
|
||||
information text 0x10000126
|
||||
effect row template 0x10000128 (300 x 32)
|
||||
row icon / name / duration 0x10000129 / 0x1000012A / 0x1000012B
|
||||
effect UI type property 0x1000000C
|
||||
```
|
||||
|
||||
|
|
@ -622,6 +624,16 @@ an active token stores its spell ID, so every layer of that spell highlights
|
|||
together and shows the shared name/description; clicking either layer again
|
||||
clears the selection.
|
||||
|
||||
`InfoRegion::InfoRegion @ 0x004F1450` creates each row with
|
||||
`UIElement_ListBox::AddItemFromTemplateList(template 0)`. In installed retail
|
||||
data the icon is x=0 width 32, name is x=37 width 188, and duration is x=225
|
||||
width 50. `EffectInfoRegion::Update @ 0x004F1C00` formats finite time as
|
||||
`m:ss` or `h:mm:ss`; a negative/permanent duration leaves the field empty.
|
||||
`gmEffectsUI::UpdateSelection @ 0x004B7F90` displays localized
|
||||
`ID_Effects_Info_SelectASpell` while nothing is selected, otherwise spell name
|
||||
plus two newlines plus description. Normal rows use state 1 and every row with
|
||||
the selected spell ID uses Highlight state 6.
|
||||
|
||||
## Portal presentation boundary
|
||||
|
||||
Recall and portal presentation remains DAT-driven. `/ls` starts the retail
|
||||
|
|
|
|||
|
|
@ -223,15 +223,44 @@ For every toolbar or indicator detail page:
|
|||
register page with gmPanelUI panel id
|
||||
when shown:
|
||||
hide the current child
|
||||
move the requested child to the shared main-panel placement
|
||||
apply the shared main-panel rectangle to the requested child
|
||||
show only the requested child
|
||||
when a page with bool property 0x10000049 closes:
|
||||
restore the deferred ordinary child
|
||||
```
|
||||
|
||||
Helpful/Harmful, Link Status, Vitae, and the Mini Game shell therefore share
|
||||
the same retained host position as Inventory, Character, and Magic. They do
|
||||
not remember independent positions.
|
||||
Character Information, Helpful/Harmful, Link Status, Vitae, and the Mini Game
|
||||
shell therefore share the same retained host size and position as Inventory,
|
||||
Character/Skills, and Magic. They do not remember independent rectangles.
|
||||
|
||||
The burden/backpack indicator sends panel id `3`, whose production child is
|
||||
root `0x10000183` under LayoutDesc `0x2100006E`. Panel `11` is the separate
|
||||
Attributes/Skills child and is not the burden indicator destination.
|
||||
|
||||
### Helpful and harmful effect rows
|
||||
|
||||
```text
|
||||
gmEffectsUI::RebuildList @ 0x004B8350:
|
||||
sort visible enchantment tokens alphabetically by spell name
|
||||
AddItemFromTemplateList(template 0)
|
||||
|
||||
EffectInfoRegion row template 0x10000128 (LayoutDesc 0x2100001B):
|
||||
icon 0x10000129 at x=0, 32 x 32
|
||||
name 0x1000012A at x=37, 188 x 32
|
||||
time left 0x1000012B at x=225, 50 x 32
|
||||
|
||||
gmEffectsUI::UpdateSelection @ 0x004B7F90:
|
||||
no selected spell -> display ID_Effects_Info_SelectASpell
|
||||
selected spell -> display name + "\n\n" + description
|
||||
matching rows use Highlight state 6; other rows use Normal state 1
|
||||
|
||||
gmEffectsUI::SetSelectedSpell @ 0x004B8290:
|
||||
clicking the selected spell again clears selection
|
||||
```
|
||||
|
||||
The installed local.dat resolves `ID_Effects_Info_SelectASpell` to
|
||||
`SELECT A SPELL`. Remaining finite durations use `m:ss` below one hour and
|
||||
`h:mm:ss` at one hour or more.
|
||||
|
||||
### End character session
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Retail shared main-panel placement — pseudocode
|
||||
# Retail shared main-panel geometry — pseudocode
|
||||
|
||||
**Date:** 2026-07-17
|
||||
**Symptom:** moving Inventory and then opening Character/Skills or Magic opens
|
||||
|
|
@ -73,10 +73,11 @@ SetPanelVisibility(panelId, show):
|
|||
requested.child.SetVisible(false)
|
||||
```
|
||||
|
||||
The decisive placement fact is structural: Inventory, Character/Skills, and
|
||||
Magic are children of one `gmPanelUI`. The switch changes child visibility;
|
||||
there is no child move and no per-panel top-level position. Dragging the parent
|
||||
therefore moves the one position subsequently used by every child.
|
||||
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
|
||||
|
||||
|
|
@ -86,9 +87,12 @@ 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
|
||||
Inventory child 0x1000018B 300 x 362, anchored on all edges
|
||||
Character child 0x1000018E 300 x 362, anchored on all edges
|
||||
Magic child 0x10000190 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
|
||||
|
|
@ -102,7 +106,8 @@ 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 primary wrapper the same bottom-only vertical resize policy,
|
||||
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
|
||||
|
|
@ -113,31 +118,31 @@ smaller limit after the shared panel moves.
|
|||
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 placement for the primary toolbar children
|
||||
(Inventory `7`, Character `11`, Magic `13`):
|
||||
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`:
|
||||
|
||||
```text
|
||||
on primary child frame moved:
|
||||
canonicalPosition = moved frame position
|
||||
move every other primary child frame to canonicalPosition
|
||||
on registered child frame moved or resized:
|
||||
canonicalGeometry = frame left, top, width, height
|
||||
apply canonicalGeometry to every hidden sibling
|
||||
|
||||
before showing a primary child:
|
||||
if canonicalPosition exists:
|
||||
move requested child frame to canonicalPosition
|
||||
before showing a registered child:
|
||||
if canonicalGeometry exists:
|
||||
apply canonicalGeometry to requested child frame
|
||||
else:
|
||||
canonicalPosition = requested child frame position
|
||||
canonicalGeometry = requested child frame geometry
|
||||
|
||||
before hiding the active primary child:
|
||||
capture its current position as canonicalPosition
|
||||
before hiding the active child:
|
||||
capture its current geometry as canonicalGeometry
|
||||
```
|
||||
|
||||
The controller owns this synchronization and subscribes to typed
|
||||
`RetailWindowHandle.Moved` events. Toolbar commands, keyboard commands,
|
||||
restore-previous effects, persistence restore, and direct window dragging all
|
||||
therefore pass through the same owner. Panel-authored size/resize policy stays
|
||||
with the active child, but the three primary wrappers apply the shared host's
|
||||
same vertical resize contract; only placement is synchronized between the
|
||||
independent frames.
|
||||
`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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue