feat(ui): port favorite spell bar overflow

Import the retail arrow-only spell bar scrollbar from LayoutDesc, preserve authored end-button extents and HideDisabled behavior in the shared retained widget, and bind each favorite list to its sole horizontal pixel-scroll model. Match retail selection exposure for off-screen spells and pin the behavior with real-fixture conformance tests.

Document the six-slice world-interaction completion program as the active pre-M4 work order.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-23 06:35:53 +02:00
parent 20e2998adb
commit 02c29e67c8
12 changed files with 582 additions and 45 deletions

View file

@ -223,6 +223,60 @@ public class DatWidgetFactoryTests
Assert.Equal(0u, bar.DownSprite);
}
[Fact]
public void Type11_HorizontalScrollbar_ImportsAuthoredArrowButtonsAndHideDisabled()
{
const uint DecrementId = 0x10000071u;
const uint IncrementId = 0x10000072u;
const uint DecrementSprite = 0x06004CDCu;
const uint IncrementSprite = 0x06004CDEu;
var decrement = new ElementInfo
{
Id = DecrementId, Type = 1u, Width = 23f, Height = 36f,
};
decrement.States[UiStateInfo.DirectStateId] = new UiStateInfo
{
Id = UiStateInfo.DirectStateId,
Image = new UiImageMedia(DecrementSprite, 1),
};
var increment = new ElementInfo
{
Id = IncrementId, Type = 1u, Width = 23f, Height = 36f,
};
increment.States[UiStateInfo.DirectStateId] = new UiStateInfo
{
Id = UiStateInfo.DirectStateId,
Image = new UiImageMedia(IncrementSprite, 1),
};
var info = new ElementInfo
{
Type = 11u,
Id = SpellcastingUiController.FavoriteScrollbarId,
Width = 685f,
Height = 36f,
Children = [decrement, increment],
};
var state = new UiStateInfo { Id = UiStateInfo.DirectStateId };
state.Properties.Values[0x77u] = new UiPropertyValue
{ Kind = UiPropertyKind.Enum, UnsignedValue = IncrementId };
state.Properties.Values[0x78u] = new UiPropertyValue
{ Kind = UiPropertyKind.Enum, UnsignedValue = DecrementId };
state.Properties.Values[0x79u] = Bool(true);
info.States[UiStateInfo.DirectStateId] = state;
var bar = Assert.IsType<UiScrollbar>(
DatWidgetFactory.Create(info, NoTex, null));
Assert.True(bar.Horizontal);
Assert.True(bar.HideWhenDisabled);
Assert.Equal(23f, bar.DecrementButtonExtent);
Assert.Equal(23f, bar.IncrementButtonExtent);
Assert.Equal(DecrementSprite, bar.UpSprite);
Assert.Equal(IncrementSprite, bar.DownSprite);
Assert.Equal(0u, bar.TrackSprite);
Assert.Equal(0u, bar.ThumbSprite);
}
[Fact]
public void RetailToolbarFixture_buildsEditableStackEntry_andAuthoredHorizontalSlider()
{