1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-12 23:12:59 +08:00

Refactor how grouping is performed

This commit is contained in:
Dean Herbert 2025-02-03 19:53:46 +09:00
parent 6a18d18feb
commit c7780c9fdc
No known key found for this signature in database
4 changed files with 85 additions and 54 deletions

View File

@ -130,7 +130,7 @@ namespace osu.Game.Tests.Visual.SongSelect
});
}
protected void SortBy(FilterCriteria criteria) => AddStep($"sort by {criteria.Sort}", () => Carousel.Filter(criteria));
protected void SortBy(FilterCriteria criteria) => AddStep($"sort {criteria.Sort} group {criteria.Group}", () => Carousel.Filter(criteria));
protected void WaitForDrawablePanels() => AddUntilStep("drawable panels loaded", () => Carousel.ChildrenOfType<ICarouselPanel>().Count(), () => Is.GreaterThan(0));
protected void WaitForSorting() => AddUntilStep("sorting finished", () => Carousel.IsFiltering, () => Is.False);

View File

@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.SongSelect
public void TestSorting()
{
AddBeatmaps(10);
SortBy(new FilterCriteria { Sort = SortMode.Difficulty });
SortBy(new FilterCriteria { Group = GroupMode.Difficulty, Sort = SortMode.Difficulty });
SortBy(new FilterCriteria { Sort = SortMode.Artist });
}

View File

@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.SongSelect
CreateCarousel();
SortBy(new FilterCriteria { Sort = SortMode.Difficulty });
SortBy(new FilterCriteria { Group = GroupMode.Difficulty, Sort = SortMode.Difficulty });
}
[Test]

View File

@ -8,6 +8,7 @@ using System.Threading;
using System.Threading.Tasks;
using osu.Game.Beatmaps;
using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Filter;
namespace osu.Game.Screens.SelectV2
{
@ -35,71 +36,101 @@ namespace osu.Game.Screens.SelectV2
public async Task<IEnumerable<CarouselItem>> Run(IEnumerable<CarouselItem> items, CancellationToken cancellationToken) => await Task.Run(() =>
{
bool groupSetsTogether;
setItems.Clear();
groupItems.Clear();
var criteria = getCriteria();
int starGroup = int.MinValue;
if (criteria.SplitOutDifficulties)
{
var diffItems = new List<CarouselItem>(items.Count());
GroupDefinition? group = null;
foreach (var item in items)
{
var b = (BeatmapInfo)item.Model;
if (b.StarRating > starGroup)
{
starGroup = (int)Math.Floor(b.StarRating);
group = new GroupDefinition($"{starGroup} - {++starGroup} *");
diffItems.Add(new CarouselItem(group) { DrawHeight = GroupPanel.HEIGHT });
}
if (!groupItems.TryGetValue(group!, out var related))
groupItems[group!] = related = new HashSet<CarouselItem>();
related.Add(item);
diffItems.Add(item);
item.IsVisible = false;
}
return diffItems;
}
CarouselItem? lastItem = null;
var newItems = new List<CarouselItem>(items.Count());
// Add criteria groups.
switch (criteria.Group)
{
default:
groupSetsTogether = true;
newItems.AddRange(items);
break;
case GroupMode.Difficulty:
groupSetsTogether = false;
int starGroup = int.MinValue;
foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
if (item.Model is BeatmapInfo b)
{
// Add set header
if (lastItem == null || (lastItem.Model is BeatmapInfo b2 && b2.BeatmapSet!.OnlineID != b.BeatmapSet!.OnlineID))
{
newItems.Add(new CarouselItem(b.BeatmapSet!)
{
DrawHeight = BeatmapSetPanel.HEIGHT,
});
}
var b = (BeatmapInfo)item.Model;
if (!setItems.TryGetValue(b.BeatmapSet!, out var related))
setItems[b.BeatmapSet!] = related = new HashSet<CarouselItem>();
related.Add(item);
if (b.StarRating > starGroup)
{
starGroup = (int)Math.Floor(b.StarRating);
newItems.Add(new CarouselItem(new GroupDefinition($"{starGroup} - {++starGroup} *")) { DrawHeight = GroupPanel.HEIGHT });
}
newItems.Add(item);
}
break;
}
// Add set headers wherever required.
CarouselItem? lastItem = null;
if (groupSetsTogether)
{
for (int i = 0; i < newItems.Count; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var item = newItems[i];
if (item.Model is BeatmapInfo beatmap)
{
if (groupSetsTogether)
{
bool newBeatmapSet = lastItem == null || (lastItem.Model is BeatmapInfo lastBeatmap && lastBeatmap.BeatmapSet!.ID != beatmap.BeatmapSet!.ID);
if (newBeatmapSet)
{
newItems.Insert(i, new CarouselItem(beatmap.BeatmapSet!) { DrawHeight = BeatmapSetPanel.HEIGHT });
i++;
}
if (!setItems.TryGetValue(beatmap.BeatmapSet!, out var related))
setItems[beatmap.BeatmapSet!] = related = new HashSet<CarouselItem>();
related.Add(item);
item.IsVisible = false;
}
}
lastItem = item;
}
}
// Link group items to their headers.
GroupDefinition? lastGroup = null;
foreach (var item in newItems)
{
cancellationToken.ThrowIfCancellationRequested();
if (item.Model is GroupDefinition group)
{
lastGroup = group;
continue;
}
if (lastGroup != null)
{
if (!groupItems.TryGetValue(lastGroup, out var groupRelated))
groupItems[lastGroup] = groupRelated = new HashSet<CarouselItem>();
groupRelated.Add(item);
item.IsVisible = false;
}
}
return newItems;
}, cancellationToken).ConfigureAwait(false);