fix(ui): select and examine favorite spells like retail

This commit is contained in:
Erik 2026-07-24 06:47:54 +02:00
parent 043ab10b3c
commit 3e31b0ac70
23 changed files with 974 additions and 34 deletions

View file

@ -44,6 +44,7 @@ public sealed class SpellcastingUiController : IRetainedPanelController
private readonly Func<uint, uint> _resolveSpellIcon;
private readonly Func<ClientObject, uint> _resolveItemDragIcon;
private readonly Action<uint> _useItem;
private readonly Action<uint>? _examineSpell;
private readonly Action<int, int, uint>? _addFavorite;
private readonly Action<int, uint>? _removeFavorite;
private readonly UiShortcutDigitGraphics? _shortcutDigits;
@ -74,6 +75,7 @@ public sealed class SpellcastingUiController : IRetainedPanelController
Func<uint, uint> resolveSpellIcon,
Func<ClientObject, uint> resolveItemDragIcon,
Action<uint> useItem,
Action<uint>? examineSpell,
SelectionState selection,
Action<int, int, uint>? addFavorite,
Action<int, uint>? removeFavorite,
@ -94,6 +96,7 @@ public sealed class SpellcastingUiController : IRetainedPanelController
_resolveSpellIcon = resolveSpellIcon;
_resolveItemDragIcon = resolveItemDragIcon;
_useItem = useItem;
_examineSpell = examineSpell;
_addFavorite = addFavorite;
_removeFavorite = removeFavorite;
_shortcutDigits = shortcutDigits;
@ -120,7 +123,11 @@ public sealed class SpellcastingUiController : IRetainedPanelController
for (int i = 0; i < _lists.Length; i++)
{
if (_lists[i] is not { } list || _scrollbars[i] is not { } scrollbar)
if (_lists[i] is not { } list)
continue;
list.PrimaryCatalogEntryPressed = SelectSpell;
list.ExamineCatalogEntryRequested = _examineSpell;
if (_scrollbars[i] is not { } scrollbar)
continue;
list.HorizontalScroll = true;
scrollbar.Horizontal = true;
@ -161,7 +168,8 @@ public sealed class SpellcastingUiController : IRetainedPanelController
Action<int, int, uint>? addFavorite,
Action<int, uint>? removeFavorite,
UiShortcutDigitGraphics? shortcutDigits = null,
uint emptySlotSprite = 0u)
uint emptySlotSprite = 0u,
Action<uint>? examineSpell = null)
{
if (layout.FindElement(CastButtonId) is not UiButton cast
|| layout.FindElement(EndowmentId) is not { } endowmentHost)
@ -185,7 +193,7 @@ public sealed class SpellcastingUiController : IRetainedPanelController
return new SpellcastingUiController(
layout, spellbook, casting, objects, playerGuid, resolveSpellIcon,
resolveItemDragIcon, useItem, selection,
resolveItemDragIcon, useItem, examineSpell, selection,
addFavorite, removeFavorite,
tabs, groups, lists, scrollbars, cast, endowmentHost,
shortcutDigits, emptySlotSprite);
@ -357,8 +365,11 @@ public sealed class SpellcastingUiController : IRetainedPanelController
DropSpellbookShortcut(shortcut, targetTab, position);
},
};
slot.Clicked = () => SelectSpell(id);
slot.DoubleClicked = () => { SelectSpell(id); CastSelected(); };
// gmSpellcastingUI::ListenToElementMessage @ 0x004C7AB0
// selects on left press (message parameter 7). A completed
// double click casts, but release is not required merely to
// change the current spell.
slot.DoubleClicked = CastSelected;
list.AddItem(slot);
}
}
@ -557,6 +568,12 @@ public sealed class SpellcastingUiController : IRetainedPanelController
_objects.ObjectRemoved -= OnObjectChanged;
_objects.Cleared -= OnObjectsCleared;
foreach (UiElement tab in _tabs) SetClick(tab, null);
foreach (UiItemList? list in _lists)
{
if (list is null) continue;
list.PrimaryCatalogEntryPressed = null;
list.ExamineCatalogEntryRequested = null;
}
_cast.OnClick = null;
}