1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-04 10:24:05 +08:00

Merge pull request #34625 from peppy/fix-song-select-event-feedback

Fix selection being finalised immediately on beatmap updates arriving
This commit is contained in:
Bartłomiej Dach
2025-08-12 14:57:01 +02:00
committed by GitHub
Unverified
2 changed files with 49 additions and 11 deletions
@@ -10,6 +10,7 @@ using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Screens.Select.Filter;
using osu.Game.Screens.SelectV2;
using osuTK.Input;
namespace osu.Game.Tests.Visual.SongSelectV2
{
@@ -198,6 +199,42 @@ namespace osu.Game.Tests.Visual.SongSelectV2
assertPanelSelected<PanelBeatmap>(0);
}
[Test]
public void TestDebounceNotBypassedOnUpdate()
{
BeatmapInfo? selectedBefore = null;
BeatmapInfo? selectedBeatmapDuringDebounce = null;
// we're testing the song select side debounce, so let's make filtering immediate
AddStep("set filter debounce delay to zero", () => Carousel.DebounceDelay = 0);
WaitForFiltering();
AddUntilStep("wait for global beatmap selection", () => !Beatmap.IsDefault);
AddStep("store selection", () => selectedBefore = Beatmap.Value.BeatmapInfo);
AddStep("traverse to next panel and update simultaneously", () =>
{
InputManager.Key(Key.Right);
Beatmaps.Delete(Beatmaps.GetAllUsableBeatmapSets().Last());
// check selection during debounce
Scheduler.AddDelayed(() => selectedBeatmapDuringDebounce = Beatmap.Value.BeatmapInfo, Screens.SelectV2.SongSelect.SELECTION_DEBOUNCE / 2f);
});
WaitForFiltering();
AddUntilStep("wait for pre-debounce selection", () => selectedBeatmapDuringDebounce, () => Is.Not.Null);
AddAssert("selection during debounce didn't change", () => selectedBeatmapDuringDebounce, () => Is.EqualTo(selectedBefore));
// Due to nunit runs having limited precision this tends to fail when headless, even though you'd expect the previous step to fail.
// Interactively, things fail as expected.
AddUntilStep("selection has changed after debounce", () => selectedBeatmapDuringDebounce, () => Is.Not.EqualTo(Beatmap.Value.BeatmapInfo));
}
private void waitForFiltering(int filterCount = 1)
{
AddUntilStep("wait for filter count", () => Carousel.FilterCount, () => Is.EqualTo(filterCount));
+12 -11
View File
@@ -467,7 +467,6 @@ namespace osu.Game.Screens.SelectV2
/// - Immediately update the selection the carousel.
/// - After <see cref="SELECTION_DEBOUNCE"/>, update the global beatmap. This in turn causes song select visuals (title, details, leaderboard) to update.
/// This debounce is intended to avoid high overheads from churning lookups while a user is changing selection via rapid keyboard operations.
/// To complete the operation immediately, call <see cref="finaliseBeatmapSelection"/>.
/// </remarks>
/// <param name="beatmap">The beatmap to be selected.</param>
private void queueBeatmapSelection(BeatmapInfo beatmap)
@@ -488,15 +487,6 @@ namespace osu.Game.Screens.SelectV2
}, SELECTION_DEBOUNCE);
}
/// <summary>
/// If any pending selection exists from <see cref="queueBeatmapSelection"/>, run it immediately.
/// </summary>
private void finaliseBeatmapSelection()
{
if (selectionDebounce?.State == ScheduledDelegate.RunState.Waiting)
selectionDebounce?.RunTask();
}
private bool ensureGlobalBeatmapValid()
{
if (!this.IsCurrentScreen())
@@ -548,6 +538,12 @@ namespace osu.Game.Screens.SelectV2
finaliseBeatmapSelection();
return validSelection;
void finaliseBeatmapSelection()
{
if (selectionDebounce?.State == ScheduledDelegate.RunState.Waiting)
selectionDebounce?.RunTask();
}
}
private bool checkBeatmapValidForSelection(BeatmapInfo beatmap, FilterCriteria? criteria)
@@ -789,7 +785,12 @@ namespace osu.Game.Screens.SelectV2
// but also in this case we want support for formatting a number within a string).
filterControl.StatusText = count != 1 ? $"{count:#,0} matches" : $"{count:#,0} match";
ensureGlobalBeatmapValid();
// If there's already a selection update in progress, let's not interrupt it.
// Interrupting could cause the debounce interval to be reduced.
//
// `ensureGlobalBeatmapValid` is run post-selection which will resolve any pending incompatibilities (see `Beatmap` bindable callback).
if (selectionDebounce?.State != ScheduledDelegate.RunState.Waiting)
ensureGlobalBeatmapValid();
updateWedgeVisibility();
}