1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-18 11:02:57 +08:00

Add scroll position maintaining

This commit is contained in:
Dean Herbert 2025-01-10 20:24:14 +09:00
parent 288be46b17
commit ad04681b28
No known key found for this signature in database
2 changed files with 61 additions and 5 deletions

View File

@ -10,6 +10,7 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Testing;
using osu.Framework.Utils;
@ -34,6 +35,8 @@ namespace osu.Game.Tests.Visual.SongSelect
private OsuTextFlowContainer stats = null!;
private BeatmapCarouselV2 carousel = null!;
private OsuScrollContainer scroll => carousel.ChildrenOfType<OsuScrollContainer>().Single();
private int beatmapCount;
public TestSceneBeatmapCarouselV2()
@ -136,6 +139,33 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("remove all beatmaps", () => beatmapSets.Clear());
}
[Test]
public void TestScrollPositionVelocityMaintained()
{
Quad positionBefore = default;
AddStep("add 10 beatmaps", () =>
{
for (int i = 0; i < 10; i++)
beatmapSets.Add(TestResources.CreateTestBeatmapSetInfo(RNG.Next(1, 4)));
});
AddUntilStep("visual item added", () => carousel.ChildrenOfType<BeatmapCarouselPanel>().Count(), () => Is.GreaterThan(0));
AddStep("scroll to last item", () => scroll.ScrollToEnd(false));
AddStep("select last beatmap", () => carousel.CurrentSelection = beatmapSets.First());
AddUntilStep("wait for scroll finished", () => scroll.Current, () => Is.EqualTo(scroll.Target));
AddStep("save selected screen position", () => positionBefore = carousel.ChildrenOfType<BeatmapCarouselPanel>().FirstOrDefault(p => p.Item!.Selected.Value)!.ScreenSpaceDrawQuad);
AddStep("remove first beatmap", () => beatmapSets.Remove(beatmapSets.Last()));
AddUntilStep("sorting finished", () => carousel.IsFiltering, () => Is.False);
AddAssert("select screen position unchanged", () => carousel.ChildrenOfType<BeatmapCarouselPanel>().Single(p => p.Item!.Selected.Value).ScreenSpaceDrawQuad,
() => Is.EqualTo(positionBefore));
}
[Test]
public void TestAddRemoveOneByOne()
{

View File

@ -94,7 +94,13 @@ namespace osu.Game.Screens.SelectV2
get => currentSelection;
set
{
if (currentSelectionCarouselItem != null)
currentSelectionCarouselItem.Selected.Value = false;
currentSelection = value;
currentSelectionCarouselItem = null;
currentSelectionYPosition = null;
updateSelection();
}
}
@ -211,17 +217,37 @@ namespace osu.Game.Screens.SelectV2
#region Selection handling
private object? currentSelection;
private CarouselItem? currentSelectionCarouselItem;
private double? currentSelectionYPosition;
private void updateSelection()
{
currentSelectionCarouselItem = null;
if (displayedCarouselItems == null) return;
// TODO: this is ugly, we probably should stop exposing CarouselItem externally.
foreach (var item in Items)
item.Selected.Value = item.Model == currentSelection;
foreach (var item in displayedCarouselItems)
item.Selected.Value = item.Model == currentSelection;
{
bool isSelected = item.Model == currentSelection;
if (isSelected)
{
currentSelectionCarouselItem = item;
if (currentSelectionYPosition != item.CarouselYPosition)
{
if (currentSelectionYPosition != null)
{
float adjustment = (float)(item.CarouselYPosition - currentSelectionYPosition.Value);
scroll.OffsetScrollPosition(adjustment);
}
currentSelectionYPosition = item.CarouselYPosition;
}
}
item.Selected.Value = isSelected;
}
}
#endregion