fix(studio): switch character skills tab on visible list

This commit is contained in:
Erik 2026-06-26 17:08:24 +02:00
parent e7e943a580
commit 5f92493742
2 changed files with 94 additions and 1 deletions

View file

@ -399,7 +399,9 @@ public static class CharacterStatController
// last duplicate) so we get the wider-label copies (195px) for the unselected state.
BindFooterDynamic(layout, datFont, data, activeTab, attrSel, skillSel);
UiElement? statList = layout.FindElement(ListBoxId);
UiElement? statList =
FindInPageContaining(layout, NameId, static el => HasDatElementId(el, ListBoxId))
?? layout.FindElement(ListBoxId);
RebuildActiveList();
if (layout.Root is { } tabRoot2 && spriteResolve is not null)
@ -1228,6 +1230,31 @@ public static class CharacterStatController
return null;
}
/// <summary>Finds the first descendant matching <paramref name="predicate"/> inside the
/// root-level tab page that contains <paramref name="anchorId"/>. This is required for
/// duplicated tab-page ids such as the character list box (0x1000023D): <see cref="ImportedLayout"/>
/// stores only the last duplicate in its id dictionary, which may be in a hidden page.</summary>
private static UiElement? FindInPageContaining(
ImportedLayout layout,
uint anchorId,
Func<UiElement, bool> predicate)
{
if (layout.FindElement(anchorId) is not { } anchor || layout.Root is not { } root)
return null;
foreach (var page in root.Children)
{
if (page.Children.Count == 0) continue;
if (!ContainsWidget(page, anchor)) continue;
return FindInSubtree(page, predicate);
}
return null;
}
private static bool HasDatElementId(UiElement element, uint id)
=> element is UiDatElement datElement && datElement.ElementId == id;
private static bool ContainsWidget(UiElement node, UiElement target)
{
if (ReferenceEquals(node, target)) return true;