fix(ui): match retail spell bar controls
Place favorite-bar arrows by their authored sides, import rollover and pressed media through the shared scrollbar, and preserve manual offsets across passive refreshes. Carry the mixed-parent DAT anchor chain to a fixed 18-cell favorite viewport so overflow controls and the Cast button remain inside the retail-sized combat frame. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
02c29e67c8
commit
0134122c28
17 changed files with 424 additions and 59 deletions
|
|
@ -126,8 +126,11 @@ public static class DatWidgetFactory
|
|||
|
||||
/// <summary>
|
||||
/// Bind inherited scrollbar media structurally. Property 0x77 names the
|
||||
/// increment button and 0x78 the decrement button; the remaining Type-1
|
||||
/// child is the thumb with ordered top/middle/bottom image slices.
|
||||
/// increment button and 0x78 the decrement button; retail
|
||||
/// <c>UIElement_Scrollbar::UpdateScrollingArea @ 0x00470AA0</c> then places
|
||||
/// those referenced child buttons by their authored leading/trailing
|
||||
/// positions. The remaining Type-1 child is the thumb with ordered
|
||||
/// top/middle/bottom image slices.
|
||||
/// </summary>
|
||||
private static UiScrollbar BuildScrollbar(
|
||||
ElementInfo info,
|
||||
|
|
@ -144,17 +147,31 @@ public static class DatWidgetFactory
|
|||
uint decrementId = ReferencedElementId(info, 0x78u);
|
||||
ElementInfo? increment = info.Children.FirstOrDefault(child => child.Id == incrementId);
|
||||
ElementInfo? decrement = info.Children.FirstOrDefault(child => child.Id == decrementId);
|
||||
bar.UpSprite = decrement is null ? 0u : DefaultImage(decrement);
|
||||
bar.DownSprite = increment is null ? 0u : DefaultImage(increment);
|
||||
ElementInfo? leadingButton = new[] { increment, decrement }
|
||||
.Where(child => child is not null)
|
||||
.OrderBy(child => bar.Horizontal ? child!.X : child!.Y)
|
||||
.ThenBy(child => child!.ReadOrder)
|
||||
.FirstOrDefault();
|
||||
ElementInfo? trailingButton = new[] { increment, decrement }
|
||||
.Where(child => child is not null)
|
||||
.OrderByDescending(child => bar.Horizontal ? child!.X : child!.Y)
|
||||
.ThenByDescending(child => child!.ReadOrder)
|
||||
.FirstOrDefault();
|
||||
bar.UpSprite = ButtonStateImage(leadingButton, "Normal");
|
||||
bar.UpRolloverSprite = ButtonStateImage(leadingButton, "Normal_rollover");
|
||||
bar.UpPressedSprite = ButtonStateImage(leadingButton, "Normal_pressed");
|
||||
bar.DownSprite = ButtonStateImage(trailingButton, "Normal");
|
||||
bar.DownRolloverSprite = ButtonStateImage(trailingButton, "Normal_rollover");
|
||||
bar.DownPressedSprite = ButtonStateImage(trailingButton, "Normal_pressed");
|
||||
if (info.TryGetEffectiveBool(0x79u, out bool hideDisabled))
|
||||
bar.HideWhenDisabled = hideDisabled;
|
||||
|
||||
if (bar.Horizontal)
|
||||
{
|
||||
if (decrement is { Width: > 0f })
|
||||
bar.DecrementButtonExtent = decrement.Width;
|
||||
if (increment is { Width: > 0f })
|
||||
bar.IncrementButtonExtent = increment.Width;
|
||||
if (leadingButton is { Width: > 0f })
|
||||
bar.DecrementButtonExtent = leadingButton.Width;
|
||||
if (trailingButton is { Width: > 0f })
|
||||
bar.IncrementButtonExtent = trailingButton.Width;
|
||||
|
||||
// Retail horizontal scrollbars use structural child ids: element 1 is
|
||||
// the thumb and element 4 is the optional child-authored track.
|
||||
|
|
@ -207,10 +224,10 @@ public static class DatWidgetFactory
|
|||
return bar;
|
||||
}
|
||||
|
||||
if (decrement is { Height: > 0f })
|
||||
bar.DecrementButtonExtent = decrement.Height;
|
||||
if (increment is { Height: > 0f })
|
||||
bar.IncrementButtonExtent = increment.Height;
|
||||
if (leadingButton is { Height: > 0f })
|
||||
bar.DecrementButtonExtent = leadingButton.Height;
|
||||
if (trailingButton is { Height: > 0f })
|
||||
bar.IncrementButtonExtent = trailingButton.Height;
|
||||
|
||||
ElementInfo? thumb = info.Children.FirstOrDefault(child =>
|
||||
child.Type == 1u && child.Id != incrementId && child.Id != decrementId);
|
||||
|
|
@ -272,6 +289,19 @@ public static class DatWidgetFactory
|
|||
return 0u;
|
||||
}
|
||||
|
||||
private static uint ButtonStateImage(ElementInfo? info, string stateName)
|
||||
{
|
||||
if (info is null)
|
||||
return 0u;
|
||||
if (info.StateMedia.TryGetValue(stateName, out var media))
|
||||
return media.File;
|
||||
UiStateInfo? state = info.States.Values.FirstOrDefault(
|
||||
candidate => string.Equals(candidate.Name, stateName, StringComparison.Ordinal));
|
||||
if (state?.Image is { } image)
|
||||
return image.File;
|
||||
return stateName == "Normal" ? DefaultImage(info) : 0u;
|
||||
}
|
||||
|
||||
// ── Meter ────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue