fix(ui): complete retail inventory scroll polish
Preserve pixel scroll offsets across inventory rebuilds, crop partially visible rows with nested geometry/UV clips, and replace the obsolete 560px resize ceiling with available screen height. Keep retail's row-sized wheel step while allowing continuous scrollbar thumb positions. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
ea72c395c9
commit
15aa3b9aff
15 changed files with 379 additions and 34 deletions
|
|
@ -291,6 +291,21 @@ public class InventoryControllerTests
|
|||
Assert.Same(grid.Scroll, bar.Model); // the bar drives the grid's scroll
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Inventory_refresh_preserves_contents_pixel_scroll_offset()
|
||||
{
|
||||
var (layout, grid, _, _, _, _, _, _) = BuildLayout();
|
||||
var objects = new ClientObjectTable();
|
||||
objects.AddOrUpdate(new ClientObject { ObjectId = Player, ItemsCapacity = 102 });
|
||||
Bind(layout, objects);
|
||||
grid.Scroll.SetScrollY(40);
|
||||
|
||||
objects.UpdateIntProperty(Player, 5u, 1000);
|
||||
|
||||
Assert.Equal(40, grid.Scroll.ScrollY);
|
||||
Assert.Equal(-8f, grid.GetItem(6)!.Top);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Contents_grid_pads_empty_slots_to_main_pack_capacity()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ public sealed class RetailWindowFrameTests
|
|||
grid.LayoutCells();
|
||||
|
||||
Assert.Equal(251f, grid.Height);
|
||||
Assert.Equal(42, grid.Children.Count(child => child.Visible));
|
||||
Assert.Equal(48, grid.Children.Count(child => child.Visible));
|
||||
Assert.Equal(224f, grid.GetItem(42)!.Top); // final row intersects 251px view by 27px
|
||||
}
|
||||
|
||||
private static void ApplyAnchors(UiElement parent)
|
||||
|
|
|
|||
36
tests/AcDream.App.Tests/UI/UiClipRectTests.cs
Normal file
36
tests/AcDream.App.Tests/UI/UiClipRectTests.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using AcDream.App.UI;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.App.Tests.UI;
|
||||
|
||||
public sealed class UiClipRectTests
|
||||
{
|
||||
[Fact]
|
||||
public void TryClipSprite_cropsGeometryAndMatchingUvs()
|
||||
{
|
||||
var clip = new UiClipRect(0f, 0f, 100f, 100f);
|
||||
float x = -8f, y = 88f, w = 32f, h = 32f;
|
||||
float u0 = 0f, v0 = 0f, u1 = 1f, v1 = 1f;
|
||||
|
||||
bool visible = UiClipRect.TryClipSprite(
|
||||
clip, ref x, ref y, ref w, ref h, ref u0, ref v0, ref u1, ref v1);
|
||||
|
||||
Assert.True(visible);
|
||||
Assert.Equal((0f, 88f, 24f, 12f), (x, y, w, h));
|
||||
Assert.Equal((0.25f, 0f, 1f, 0.375f), (u0, v0, u1, v1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Intersection_andFullyOutsideSprite_areEmpty()
|
||||
{
|
||||
UiClipRect intersection = UiClipRect.Intersect(
|
||||
new UiClipRect(0f, 0f, 20f, 20f),
|
||||
new UiClipRect(30f, 30f, 40f, 40f));
|
||||
float x = 0f, y = 0f, w = 10f, h = 10f;
|
||||
float u0 = 0f, v0 = 0f, u1 = 1f, v1 = 1f;
|
||||
|
||||
Assert.True(intersection.IsEmpty);
|
||||
Assert.False(UiClipRect.TryClipSprite(
|
||||
intersection, ref x, ref y, ref w, ref h, ref u0, ref v0, ref u1, ref v1));
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,40 @@ public sealed class UiItemListScrollTests
|
|||
Assert.True(list.GetItem(18)!.Visible); // row 3 now visible
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Pixel_scroll_keeps_partiallyVisible_edge_rows()
|
||||
{
|
||||
var list = Grid(30);
|
||||
|
||||
list.Scroll.SetScrollY(8);
|
||||
list.LayoutCells();
|
||||
|
||||
Assert.True(list.GetItem(0)!.Visible);
|
||||
Assert.Equal(-8f, list.GetItem(0)!.Top);
|
||||
Assert.True(list.GetItem(18)!.Visible);
|
||||
Assert.Equal(88f, list.GetItem(18)!.Top);
|
||||
Assert.False(list.GetItem(24)!.Visible);
|
||||
Assert.Null(list.HitTest(5f, -1f));
|
||||
Assert.IsType<UiItemSlot>(list.HitTest(5f, 1f));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deferred_rebuild_preserves_pixel_scroll_offset()
|
||||
{
|
||||
var list = Grid(30);
|
||||
list.Scroll.SetScrollY(40);
|
||||
|
||||
using (list.DeferLayout())
|
||||
{
|
||||
list.Flush();
|
||||
for (int i = 0; i < 30; i++)
|
||||
list.AddItem(new UiItemSlot());
|
||||
}
|
||||
|
||||
Assert.Equal(40, list.Scroll.ScrollY);
|
||||
Assert.Equal(-8f, list.GetItem(6)!.Top);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scroll_survives_the_per_frame_anchor_pass()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue