diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomListing.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomListing.cs
index 7f6fb97e0c..85dfdd9af9 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomListing.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomListing.cs
@@ -144,7 +144,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("4 rooms visible", () => container.DrawableRooms.Count(r => r.IsPresent) == 4);
- AddStep("filter one room", () => container.Filter.Value = new FilterCriteria { SearchString = rooms.First().Name });
+ AddStep("filter one room", () => container.Filter.Value = new LoungeFilterCriteria { SearchString = rooms.First().Name });
AddUntilStep("1 rooms visible", () => container.DrawableRooms.Count(r => r.IsPresent) == 1);
@@ -160,13 +160,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("add rooms", () => rooms.AddRange(GenerateRooms(3, new CatchRuleset().RulesetInfo)));
// Todo: What even is this case...?
- AddStep("set empty filter criteria", () => container.Filter.Value = new FilterCriteria());
+ AddStep("set empty filter criteria", () => container.Filter.Value = new LoungeFilterCriteria());
AddUntilStep("5 rooms visible", () => container.DrawableRooms.Count(r => r.IsPresent) == 5);
- AddStep("filter osu! rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo });
+ AddStep("filter osu! rooms", () => container.Filter.Value = new LoungeFilterCriteria { Ruleset = new OsuRuleset().RulesetInfo });
AddUntilStep("2 rooms visible", () => container.DrawableRooms.Count(r => r.IsPresent) == 2);
- AddStep("filter catch rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo });
+ AddStep("filter catch rooms", () => container.Filter.Value = new LoungeFilterCriteria { Ruleset = new CatchRuleset().RulesetInfo });
AddUntilStep("3 rooms visible", () => container.DrawableRooms.Count(r => r.IsPresent) == 3);
}
@@ -183,11 +183,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("both rooms visible", () => container.DrawableRooms.Count(r => r.IsPresent) == 2);
- AddStep("filter public rooms", () => container.Filter.Value = new FilterCriteria { Permissions = RoomPermissionsFilter.Public });
+ AddStep("filter public rooms", () => container.Filter.Value = new LoungeFilterCriteria { Permissions = RoomPermissionsFilter.Public });
AddUntilStep("private room hidden", () => container.DrawableRooms.All(r => !r.Room.HasPassword));
- AddStep("filter private rooms", () => container.Filter.Value = new FilterCriteria { Permissions = RoomPermissionsFilter.Private });
+ AddStep("filter private rooms", () => container.Filter.Value = new LoungeFilterCriteria { Permissions = RoomPermissionsFilter.Private });
AddUntilStep("public room hidden", () => container.DrawableRooms.All(r => r.Room.HasPassword));
}
diff --git a/osu.Game/Online/Rooms/GetRoomsRequest.cs b/osu.Game/Online/Rooms/GetRoomsRequest.cs
index 2d0d572e84..a665cb730e 100644
--- a/osu.Game/Online/Rooms/GetRoomsRequest.cs
+++ b/osu.Game/Online/Rooms/GetRoomsRequest.cs
@@ -15,7 +15,7 @@ namespace osu.Game.Online.Rooms
private readonly RoomStatusFilter? status;
private readonly string category;
- public GetRoomsRequest(FilterCriteria filterCriteria)
+ public GetRoomsRequest(LoungeFilterCriteria filterCriteria)
{
mode = filterCriteria.Mode;
category = filterCriteria.Category;
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterCriteria.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/LoungeFilterCriteria.cs
similarity index 93%
rename from osu.Game/Screens/OnlinePlay/Lounge/Components/FilterCriteria.cs
rename to osu.Game/Screens/OnlinePlay/Lounge/Components/LoungeFilterCriteria.cs
index 121dffde1f..9778b855fc 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterCriteria.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/LoungeFilterCriteria.cs
@@ -5,7 +5,7 @@ using osu.Game.Rulesets;
namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
- public class FilterCriteria
+ public class LoungeFilterCriteria
{
public string SearchString = string.Empty;
public RoomModeFilter Mode;
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomListing.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomListing.cs
index f04de97f9b..78d0b6360f 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomListing.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomListing.cs
@@ -31,7 +31,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
///
/// The current filter criteria. Should be managed externally.
///
- public readonly Bindable Filter = new Bindable();
+ public readonly Bindable Filter = new Bindable();
///
/// The currently user-selected room.
@@ -87,7 +87,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
Filter.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true);
}
- private void applyFilterCriteria(FilterCriteria? criteria)
+ private void applyFilterCriteria(LoungeFilterCriteria? criteria)
{
roomFlow.Children.ForEach(r =>
{
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeListingPoller.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeListingPoller.cs
index d92ae7eb6e..34209cee7f 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeListingPoller.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeListingPoller.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
private IAPIProvider api { get; set; } = null!;
public required Action RoomsReceived { get; init; }
- public readonly IBindable Filter = new Bindable();
+ public readonly IBindable Filter = new Bindable();
private GetRoomsRequest? lastPollRequest;
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs
index b4b039501f..d1473bacc5 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs
@@ -73,7 +73,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
private IDisposable? joiningRoomOperation;
- private readonly Bindable filter = new Bindable();
+ private readonly Bindable filter = new Bindable();
private readonly Bindable hasListingResults = new Bindable();
private readonly IBindable operationInProgress = new Bindable();
private readonly IBindable isIdle = new BindableBool();
@@ -262,7 +262,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
filter.Value = CreateFilterCriteria();
}
- protected virtual FilterCriteria CreateFilterCriteria() => new FilterCriteria
+ protected virtual LoungeFilterCriteria CreateFilterCriteria() => new LoungeFilterCriteria
{
SearchString = searchTextBox.Current.Value,
Ruleset = ruleset.Value,
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs
index 5e2619eae3..2b61f3240d 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs
@@ -56,7 +56,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
StatusDropdown.Current.BindValueChanged(_ => showInProgress.Alpha = StatusDropdown.Current.Value == RoomModeFilter.Open ? 1 : 0, true);
}
- protected override FilterCriteria CreateFilterCriteria()
+ protected override LoungeFilterCriteria CreateFilterCriteria()
{
var criteria = base.CreateFilterCriteria();
criteria.Category = @"realtime";
diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs
index cc4065a82b..a095a5c0ef 100644
--- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs
@@ -38,7 +38,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
return base.CreateFilterControls().Append(categoryDropdown);
}
- protected override FilterCriteria CreateFilterCriteria()
+ protected override LoungeFilterCriteria CreateFilterCriteria()
{
var criteria = base.CreateFilterCriteria();
diff --git a/osu.Game/Screens/Select/FilterControl.DifficultyRangeSlider.cs b/osu.Game/Screens/Select/FilterControl.DifficultyRangeSlider.cs
index 902b335c62..718e55df13 100644
--- a/osu.Game/Screens/Select/FilterControl.DifficultyRangeSlider.cs
+++ b/osu.Game/Screens/Select/FilterControl.DifficultyRangeSlider.cs
@@ -45,7 +45,7 @@ namespace osu.Game.Screens.Select
}
[BackgroundDependencyLoader]
- private void load(OverlayColourProvider colourProvider, OsuColour colours)
+ private void load(OverlayColourProvider colourProvider)
{
SliderContainer.AddRange(new Drawable[]
{
diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs
index 32dd22da3e..c8c4343637 100644
--- a/osu.Game/Screens/Select/FilterControl.cs
+++ b/osu.Game/Screens/Select/FilterControl.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -13,6 +12,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
+using osu.Framework.Threading;
using osu.Game.Beatmaps;
using osu.Game.Collections;
using osu.Game.Configuration;
@@ -244,8 +244,20 @@ namespace osu.Game.Screens.Select
});
searchTextBox.Current.BindValueChanged(_ => updateCriteria());
- difficultyRangeSlider.LowerBound.BindValueChanged(_ => updateCriteria());
- difficultyRangeSlider.UpperBound.BindValueChanged(_ => updateCriteria());
+
+ ScheduledDelegate? sliderDebounce = null;
+
+ // For slider dragging (where input events can arrive very often), even creating criteria can have
+ // overhead, especially when a collection is selected (see ToImmutableHashSet() call).
+ void debouncedUpdateCriteria()
+ {
+ sliderDebounce?.Cancel();
+ sliderDebounce = Scheduler.AddDelayed(() => updateCriteria(), 50);
+ }
+
+ difficultyRangeSlider.LowerBound.BindValueChanged(_ => debouncedUpdateCriteria());
+ difficultyRangeSlider.UpperBound.BindValueChanged(_ => debouncedUpdateCriteria());
+
showConvertedBeatmapsButton.Active.BindValueChanged(_ => updateCriteria());
sortDropdown.Current.BindValueChanged(_ => updateCriteria());
groupDropdown.Current.BindValueChanged(_ => updateCriteria());
@@ -258,7 +270,7 @@ namespace osu.Game.Screens.Select
updateCriteria();
});
- collectionsSubscription = realm.RegisterForNotifications(r => r.All(), (collections, changeSet) =>
+ collectionsSubscription = realm.RegisterForNotifications(r => r.All(), (_, changeSet) =>
{
if (changeSet != null && groupDropdown.Current.Value.Value == GroupMode.Collections)
updateCriteria();
@@ -293,7 +305,7 @@ namespace osu.Game.Screens.Select
AllowConvertedBeatmaps = showConvertedBeatmapsButton.Active.Value,
Ruleset = ruleset.Value,
Mods = mods.Value,
- CollectionBeatmapMD5Hashes = collectionDropdown.Current.Value?.Collection?.PerformRead(c => c.BeatmapMD5Hashes).ToImmutableHashSet(),
+ Collection = collectionDropdown.Current.Value?.Collection,
LocalUserId = isValidUser ? localUser.Value.Id : null,
LocalUserUsername = isValidUser ? localUser.Value.Username : null,
};
diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs
index 1c70132850..750938ceb8 100644
--- a/osu.Game/Screens/Select/FilterCriteria.cs
+++ b/osu.Game/Screens/Select/FilterCriteria.cs
@@ -3,11 +3,13 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using osu.Game.Beatmaps;
using osu.Game.Collections;
+using osu.Game.Database;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Filter;
using osu.Game.Rulesets.Mods;
@@ -111,10 +113,24 @@ namespace osu.Game.Screens.Select
}
}
+ private ImmutableHashSet? collectionBeatmapMD5Hashes;
+ private Live? collection;
+
///
/// Hashes from the to filter to.
///
- public IEnumerable? CollectionBeatmapMD5Hashes { get; set; }
+ public IEnumerable? CollectionBeatmapMD5Hashes =>
+ collectionBeatmapMD5Hashes ??= Collection?.PerformRead(c => c.BeatmapMD5Hashes.ToImmutableHashSet());
+
+ public Live? Collection
+ {
+ get => collection;
+ set
+ {
+ collection = value;
+ collectionBeatmapMD5Hashes = null;
+ }
+ }
public IRulesetFilterCriteria? RulesetCriteria { get; set; }