fix(ui): restore retail spell tabs and spellbook
Bind the spellbook and component-book tabs as their authored stateful text controls, propagate Closed/Open state into the retained DAT child tree, and keep authored label colors live across state changes. Match retail UIElement_Text zero-margin construction so the Magic favorite captions I through VIII are no longer clipped. Add a real portal.dat spellbook fixture plus controller, state-propagation, and text-layout regression coverage. Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
parent
07be994d97
commit
ad30c37a48
15 changed files with 13492 additions and 38 deletions
|
|
@ -14,7 +14,9 @@ public enum SpellbookWindowPage { Spells, Components }
|
|||
/// <summary>
|
||||
/// Binds retail's combined spellbook/component-book LayoutDesc 0x21000034.
|
||||
/// The spell page mirrors gmSpellbookUI filters; the component page mirrors
|
||||
/// ComponentTracker and exposes the 0..5000 desired purchase level field.
|
||||
/// ComponentTracker and exposes the 0..5000 desired purchase level field. The
|
||||
/// two authored tabs are stateful UIElement_Text controls, matching
|
||||
/// <c>gmSpellbookUI::PostInit @ 0x0048B2B0</c> and the resolved retail layout.
|
||||
/// </summary>
|
||||
public sealed class SpellbookWindowController : IRetainedPanelController
|
||||
{
|
||||
|
|
@ -54,8 +56,8 @@ public sealed class SpellbookWindowController : IRetainedPanelController
|
|||
private readonly Action _close;
|
||||
private readonly UiElement _spellPage;
|
||||
private readonly UiElement _componentPage;
|
||||
private readonly UiButton _spellTab;
|
||||
private readonly UiButton _componentTab;
|
||||
private readonly UiElement _spellTab;
|
||||
private readonly UiElement _componentTab;
|
||||
private readonly UiButton _closeButton;
|
||||
private readonly UiItemList _spellList;
|
||||
private readonly UiItemList _componentList;
|
||||
|
|
@ -82,8 +84,8 @@ public sealed class SpellbookWindowController : IRetainedPanelController
|
|||
Action close,
|
||||
UiElement spellPage,
|
||||
UiElement componentPage,
|
||||
UiButton spellTab,
|
||||
UiButton componentTab,
|
||||
UiElement spellTab,
|
||||
UiElement componentTab,
|
||||
UiButton closeButton,
|
||||
UiItemList spellList,
|
||||
UiItemList componentList)
|
||||
|
|
@ -108,8 +110,8 @@ public sealed class SpellbookWindowController : IRetainedPanelController
|
|||
_spellList = spellList;
|
||||
_componentList = componentList;
|
||||
|
||||
spellTab.OnClick = () => ShowPage(SpellbookWindowPage.Spells);
|
||||
componentTab.OnClick = () => ShowPage(SpellbookWindowPage.Components);
|
||||
SetClick(spellTab, () => ShowPage(SpellbookWindowPage.Spells));
|
||||
SetClick(componentTab, () => ShowPage(SpellbookWindowPage.Components));
|
||||
closeButton.OnClick = close;
|
||||
foreach ((uint id, uint mask) in FilterButtons)
|
||||
{
|
||||
|
|
@ -151,8 +153,8 @@ public sealed class SpellbookWindowController : IRetainedPanelController
|
|||
{
|
||||
if (layout.FindElement(SpellPageId) is not { } spellPage
|
||||
|| layout.FindElement(ComponentPageId) is not { } componentPage
|
||||
|| layout.FindElement(SpellTabId) is not UiButton spellTab
|
||||
|| layout.FindElement(ComponentTabId) is not UiButton componentTab
|
||||
|| layout.FindElement(SpellTabId) is not { } spellTab
|
||||
|| layout.FindElement(ComponentTabId) is not { } componentTab
|
||||
|| layout.FindElement(CloseId) is not UiButton closeButton
|
||||
|| layout.FindElement(SpellListId) is not UiItemList spellList)
|
||||
return null;
|
||||
|
|
@ -187,8 +189,8 @@ public sealed class SpellbookWindowController : IRetainedPanelController
|
|||
CurrentPage = page;
|
||||
_spellPage.Visible = page == SpellbookWindowPage.Spells;
|
||||
_componentPage.Visible = page == SpellbookWindowPage.Components;
|
||||
_spellTab.Selected = page == SpellbookWindowPage.Spells;
|
||||
_componentTab.Selected = page == SpellbookWindowPage.Components;
|
||||
SetTabOpen(_spellTab, page == SpellbookWindowPage.Spells);
|
||||
SetTabOpen(_componentTab, page == SpellbookWindowPage.Components);
|
||||
}
|
||||
|
||||
private void ConfigureSpellList()
|
||||
|
|
@ -449,9 +451,29 @@ public sealed class SpellbookWindowController : IRetainedPanelController
|
|||
_objects.ObjectRemoved -= OnObjectRemoved;
|
||||
_objects.ObjectMoved -= OnObjectMoved;
|
||||
_objects.ContainerContentsReplaced -= OnContainerContentsReplaced;
|
||||
_spellTab.OnClick = null;
|
||||
_componentTab.OnClick = null;
|
||||
SetClick(_spellTab, null);
|
||||
SetClick(_componentTab, null);
|
||||
_closeButton.OnClick = null;
|
||||
foreach ((UiButton button, _) in _filters) button.OnClick = null;
|
||||
}
|
||||
|
||||
private static void SetClick(UiElement element, Action? action)
|
||||
{
|
||||
element.ClickThrough = action is null;
|
||||
switch (element)
|
||||
{
|
||||
case UiButton button: button.OnClick = action; break;
|
||||
case UiText text: text.OnClick = action; break;
|
||||
case UiDatElement dat: dat.OnClick = action; break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetTabOpen(UiElement element, bool open)
|
||||
{
|
||||
if (element is IUiDatStateful stateful
|
||||
&& stateful.TrySetRetailState(open ? RetailUiStateIds.Open : RetailUiStateIds.Closed))
|
||||
return;
|
||||
if (element is UiButton button)
|
||||
button.Selected = open;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue