diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs index db66c01814..df42ba9d16 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs @@ -77,6 +77,7 @@ namespace osu.Game.Tests.Visual testEmptyTraversal(); testHiding(); testSelectingFilteredRuleset(); + testFilterByStarRange(); testCarouselRootIsRandom(); } @@ -245,6 +246,54 @@ namespace osu.Game.Tests.Visual AddAssert("Selection is non-null", () => currentSelection != null); } + /// + /// Test filtering by restricting the desired star range + /// + private void testFilterByStarRange() + { + var manyStarDiffs = createTestBeatmapSet(set_count + 1); + manyStarDiffs.Beatmaps.Clear(); + + for (int i = 0; i < 12; i++) + { + manyStarDiffs.Beatmaps.Add(new BeatmapInfo + { + OnlineBeatmapID = manyStarDiffs.ID * 10 + i, + Path = $"randomDiff{i}.osu", + Version = $"Totally Normal {i}", + StarDifficulty = i, + BaseDifficulty = new BeatmapDifficulty + { + OverallDifficulty = 5, + } + }); + } + + AddStep("add set with many stars", () => carousel.UpdateBeatmapSet(manyStarDiffs)); + + AddStep("select added set", () => carousel.SelectBeatmap(manyStarDiffs.Beatmaps[0], false)); + + AddStep("Filter to 1-3 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 1, DisplayStarsMaximum = 3 }, false)); + checkVisibleItemCount(diff: false, count: 1); + checkVisibleItemCount(diff: true, count: 3); + + AddStep("Filter to 3-3 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 3, DisplayStarsMaximum = 3 }, false)); + checkVisibleItemCount(diff: false, count: 1); + checkVisibleItemCount(diff: true, count: 1); + + AddStep("Filter to 4-2 stars", () => carousel.Filter(new FilterCriteria { DisplayStarsMinimum = 4, DisplayStarsMaximum = 2 }, false)); + checkVisibleItemCount(diff: false, count: 0); + checkVisibleItemCount(diff: true, count: 0); + + AddStep("remove added set", () => + { + carousel.RemoveBeatmapSet(manyStarDiffs); + manyStarDiffs = null; + }); + + AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); + } + /// /// Test random non-repeating algorithm /// diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 272332f1ce..c9ed2f3573 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -26,6 +26,12 @@ namespace osu.Game.Screens.Select.Carousel bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps; + if(criteria.DisplayStarsMinimum.HasValue) + match &= Beatmap.StarDifficulty >= criteria.DisplayStarsMinimum; + + if (criteria.DisplayStarsMaximum.HasValue) + match &= Beatmap.StarDifficulty <= criteria.DisplayStarsMaximum; + if (!string.IsNullOrEmpty(criteria.SearchText)) match &= Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteria.SearchText, StringComparison.InvariantCultureIgnoreCase) >= 0) || diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index fce7af1400..78b452b6f5 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -32,14 +32,13 @@ namespace osu.Game.Screens.Select public SortMode Sort { - get { return sort; } + get => sort; set { - if (sort != value) - { - sort = value; - FilterChanged?.Invoke(CreateCriteria()); - } + if (sort == value) return; + + sort = value; + FilterChanged?.Invoke(CreateCriteria()); } } @@ -47,14 +46,13 @@ namespace osu.Game.Screens.Select public GroupMode Group { - get { return group; } + get => group; set { - if (group != value) - { - group = value; - FilterChanged?.Invoke(CreateCriteria()); - } + if (group == value) return; + + group = value; + FilterChanged?.Invoke(CreateCriteria()); } } @@ -64,7 +62,9 @@ namespace osu.Game.Screens.Select Sort = sort, SearchText = searchTextBox.Text, AllowConvertedBeatmaps = showConverted, - Ruleset = ruleset.Value + Ruleset = ruleset.Value, + DisplayStarsMinimum = minimumStars, + DisplayStarsMaximum = maximumStars, }; public Action Exit; @@ -168,7 +168,9 @@ namespace osu.Game.Screens.Select private readonly IBindable ruleset = new Bindable(); - private Bindable showConverted; + private readonly Bindable showConverted = new Bindable(); + private readonly Bindable minimumStars = new Bindable(); + private readonly Bindable maximumStars = new Bindable(); public readonly Box Background; @@ -177,8 +179,14 @@ namespace osu.Game.Screens.Select { sortTabs.AccentColour = colours.GreenLight; - showConverted = config.GetBindable(OsuSetting.ShowConvertedBeatmaps); - showConverted.ValueChanged += val => updateCriteria(); + config.BindWith(OsuSetting.ShowConvertedBeatmaps, showConverted); + showConverted.ValueChanged += _ => updateCriteria(); + + config.BindWith(OsuSetting.DisplayStarsMinimum, minimumStars); + minimumStars.ValueChanged += _ => updateCriteria(); + + config.BindWith(OsuSetting.DisplayStarsMaximum, maximumStars); + maximumStars.ValueChanged += _ => updateCriteria(); ruleset.BindTo(parentRuleset); ruleset.BindValueChanged(_ => updateCriteria(), true); diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index bea806f00f..f97eb1bea1 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -13,5 +13,7 @@ namespace osu.Game.Screens.Select public string SearchText; public RulesetInfo Ruleset; public bool AllowConvertedBeatmaps; + public double? DisplayStarsMinimum; + public double? DisplayStarsMaximum; } }