1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 10:12:54 +08:00

Merge pull request #11017 from peppy/fix-song-select-temporary-selection-loss

Fix current beatmap temporarily becoming empty during ruleset change
This commit is contained in:
Dan Balasescu 2020-12-01 17:55:08 +09:00 committed by GitHub
commit 1cea39ed55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 2 deletions

View File

@ -643,6 +643,55 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("Selected beatmap correct", () => songSelect.Carousel.SelectedBeatmap == filteredBeatmap);
}
[Test]
public void TestChangingRulesetOnMultiRulesetBeatmap()
{
int changeCount = 0;
AddStep("change convert setting", () => config.Set(OsuSetting.ShowConvertedBeatmaps, false));
AddStep("bind beatmap changed", () =>
{
Beatmap.ValueChanged += onChange;
changeCount = 0;
});
changeRuleset(0);
createSongSelect();
AddStep("import multi-ruleset map", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
manager.Import(createTestBeatmapSet(usableRulesets)).Wait();
});
int previousSetID = 0;
AddUntilStep("wait for selection", () => !Beatmap.IsDefault);
AddStep("record set ID", () => previousSetID = Beatmap.Value.BeatmapSetInfo.ID);
AddAssert("selection changed once", () => changeCount == 1);
AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0);
changeRuleset(3);
AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
AddUntilStep("selection changed", () => changeCount > 1);
AddAssert("Selected beatmap still same set", () => Beatmap.Value.BeatmapSetInfo.ID == previousSetID);
AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.ID == 3);
AddAssert("selection changed only fired twice", () => changeCount == 2);
AddStep("unbind beatmap changed", () => Beatmap.ValueChanged -= onChange);
AddStep("change convert setting", () => config.Set(OsuSetting.ShowConvertedBeatmaps, true));
// ReSharper disable once AccessToModifiedClosure
void onChange(ValueChangedEvent<WorkingBeatmap> valueChangedEvent) => changeCount++;
}
[Test]
public void TestDifficultyIconSelectingForDifferentRuleset()
{

View File

@ -376,7 +376,7 @@ namespace osu.Game.Screens.Select
if (selectionChangedDebounce?.Completed == false)
{
selectionChangedDebounce.RunTask();
selectionChangedDebounce.Cancel(); // cancel the already scheduled task.
selectionChangedDebounce?.Cancel(); // cancel the already scheduled task.
selectionChangedDebounce = null;
}
@ -465,19 +465,30 @@ namespace osu.Game.Screens.Select
void run()
{
// clear pending task immediately to track any potential nested debounce operation.
selectionChangedDebounce = null;
Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}");
if (transferRulesetValue())
{
Mods.Value = Array.Empty<Mod>();
// transferRulesetValue() may trigger a refilter. If the current selection does not match the new ruleset, we want to switch away from it.
// transferRulesetValue() may trigger a re-filter. If the current selection does not match the new ruleset, we want to switch away from it.
// The default logic on WorkingBeatmap change is to switch to a matching ruleset (see workingBeatmapChanged()), but we don't want that here.
// We perform an early selection attempt and clear out the beatmap selection to avoid a second ruleset change (revert).
if (beatmap != null && !Carousel.SelectBeatmap(beatmap, false))
beatmap = null;
}
if (selectionChangedDebounce != null)
{
// a new nested operation was started; switch to it for further selection.
// this avoids having two separate debounces trigger from the same source.
selectionChangedDebounce.RunTask();
return;
}
// We may be arriving here due to another component changing the bindable Beatmap.
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
if (!EqualityComparer<BeatmapInfo>.Default.Equals(beatmap, Beatmap.Value.BeatmapInfo))