From 5b24800b0e9c88af8747f9e33a3c14b97ca1f4d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jan 2022 12:37:17 +0900 Subject: [PATCH 1/2] Avoid applying filter in `UpdateBeatmapSet` flow --- osu.Game/Screens/Select/BeatmapCarousel.cs | 12 +++++---- .../Screens/Select/Carousel/CarouselGroup.cs | 27 +++++++++++++++++-- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 75ad0511e6..6d3d7aa185 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -300,16 +300,18 @@ namespace osu.Game.Screens.Select root.AddChild(newSet); - // only reset scroll position if already near the scroll target. - // without this, during a large beatmap import it is impossible to navigate the carousel. - applyActiveCriteria(false, alwaysResetScrollPosition: false); - // check if we can/need to maintain our current selection. if (previouslySelectedID != null) select((CarouselItem)newSet.Beatmaps.FirstOrDefault(b => b.BeatmapInfo.ID == previouslySelectedID) ?? newSet); itemsCache.Invalidate(); - Schedule(() => BeatmapSetsChanged?.Invoke()); + Schedule(() => + { + if (!Scroll.UserScrolling) + ScrollToSelected(true); + + BeatmapSetsChanged?.Invoke(); + }); }); /// diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index b85e868b89..7e4c5fad72 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; namespace osu.Game.Screens.Select.Carousel { @@ -36,7 +37,21 @@ namespace osu.Game.Screens.Select.Carousel { i.State.ValueChanged += state => ChildItemStateChanged(i, state.NewValue); i.ChildID = ++currentChildID; - InternalChildren.Add(i); + + if (lastCriteria != null) + { + i.Filter(lastCriteria); + + int index = InternalChildren.BinarySearch(i, criteriaComparer); + if (index < 0) index = ~index; // BinarySearch hacks multiple return values with 2's complement. + + InternalChildren.Insert(index, i); + } + else + { + // criteria may be null for initial population. the filtering will be applied post-add. + InternalChildren.Add(i); + } } public CarouselGroup(List items = null) @@ -62,14 +77,22 @@ namespace osu.Game.Screens.Select.Carousel }; } + private Comparer criteriaComparer; + + [CanBeNull] + private FilterCriteria lastCriteria; + public override void Filter(FilterCriteria criteria) { base.Filter(criteria); InternalChildren.ForEach(c => c.Filter(criteria)); + // IEnumerable.OrderBy() is used instead of List.Sort() to ensure sorting stability - var criteriaComparer = Comparer.Create((x, y) => x.CompareTo(criteria, y)); + criteriaComparer = Comparer.Create((x, y) => x.CompareTo(criteria, y)); InternalChildren = InternalChildren.OrderBy(c => c, criteriaComparer).ToList(); + + lastCriteria = criteria; } protected virtual void ChildItemStateChanged(CarouselItem item, CarouselItemState value) From bed7b69464ed1b6971ae84ee81885d6ce90c5fed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jan 2022 13:09:03 +0900 Subject: [PATCH 2/2] Apply NRT to `CarouselGroup` --- .../Screens/Select/Carousel/CarouselGroup.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index 7e4c5fad72..6ebe314072 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -3,7 +3,8 @@ using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; + +#nullable enable namespace osu.Game.Screens.Select.Carousel { @@ -12,7 +13,7 @@ namespace osu.Game.Screens.Select.Carousel /// public class CarouselGroup : CarouselItem { - public override DrawableCarouselItem CreateDrawableRepresentation() => null; + public override DrawableCarouselItem? CreateDrawableRepresentation() => null; public IReadOnlyList Children => InternalChildren; @@ -24,6 +25,10 @@ namespace osu.Game.Screens.Select.Carousel /// private ulong currentChildID; + private Comparer? criteriaComparer; + + private FilterCriteria? lastCriteria; + public virtual void RemoveChild(CarouselItem i) { InternalChildren.Remove(i); @@ -54,7 +59,7 @@ namespace osu.Game.Screens.Select.Carousel } } - public CarouselGroup(List items = null) + public CarouselGroup(List? items = null) { if (items != null) InternalChildren = items; @@ -77,11 +82,6 @@ namespace osu.Game.Screens.Select.Carousel }; } - private Comparer criteriaComparer; - - [CanBeNull] - private FilterCriteria lastCriteria; - public override void Filter(FilterCriteria criteria) { base.Filter(criteria);