diff --git a/Directory.Build.props b/Directory.Build.props
index 21b8b402e0..2cd40c8675 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -16,9 +16,9 @@
-
+
-
+
$(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset
diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
index aed8e19fb2..81fd1b66e5 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
@@ -24,10 +24,12 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Taiko;
+using osu.Game.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Carousel;
using osu.Game.Screens.Select.Filter;
+using osu.Game.Users;
using osuTK.Input;
namespace osu.Game.Tests.Visual.SongSelect
@@ -110,7 +112,7 @@ namespace osu.Game.Tests.Visual.SongSelect
createSongSelect();
- AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault);
+ waitForInitialSelection();
WorkingBeatmap selected = null;
@@ -135,7 +137,7 @@ namespace osu.Game.Tests.Visual.SongSelect
createSongSelect();
- AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault);
+ waitForInitialSelection();
WorkingBeatmap selected = null;
@@ -189,7 +191,7 @@ namespace osu.Game.Tests.Visual.SongSelect
createSongSelect();
- AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault);
+ waitForInitialSelection();
WorkingBeatmap selected = null;
@@ -769,6 +771,76 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("Check first item in group selected", () => Beatmap.Value.BeatmapInfo == groupIcon.Items.First().Beatmap);
}
+ [Test]
+ public void TestChangeRulesetWhilePresentingScore()
+ {
+ BeatmapInfo getPresentBeatmap() => manager.QueryBeatmap(b => !b.BeatmapSet.DeletePending && b.RulesetID == 0);
+ BeatmapInfo getSwitchBeatmap() => manager.QueryBeatmap(b => !b.BeatmapSet.DeletePending && b.RulesetID == 1);
+
+ changeRuleset(0);
+
+ createSongSelect();
+
+ addRulesetImportStep(0);
+ addRulesetImportStep(1);
+
+ AddStep("present score", () =>
+ {
+ // this ruleset change should be overridden by the present.
+ Ruleset.Value = getSwitchBeatmap().Ruleset;
+
+ songSelect.PresentScore(new ScoreInfo
+ {
+ User = new User { Username = "woo" },
+ Beatmap = getPresentBeatmap(),
+ Ruleset = getPresentBeatmap().Ruleset
+ });
+ });
+
+ AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
+
+ AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.Equals(getPresentBeatmap()));
+ AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0);
+ }
+
+ [Test]
+ public void TestChangeBeatmapWhilePresentingScore()
+ {
+ BeatmapInfo getPresentBeatmap() => manager.QueryBeatmap(b => !b.BeatmapSet.DeletePending && b.RulesetID == 0);
+ BeatmapInfo getSwitchBeatmap() => manager.QueryBeatmap(b => !b.BeatmapSet.DeletePending && b.RulesetID == 1);
+
+ changeRuleset(0);
+
+ addRulesetImportStep(0);
+ addRulesetImportStep(1);
+
+ createSongSelect();
+
+ AddStep("present score", () =>
+ {
+ // this beatmap change should be overridden by the present.
+ Beatmap.Value = manager.GetWorkingBeatmap(getSwitchBeatmap());
+
+ songSelect.PresentScore(new ScoreInfo
+ {
+ User = new User { Username = "woo" },
+ Beatmap = getPresentBeatmap(),
+ Ruleset = getPresentBeatmap().Ruleset
+ });
+ });
+
+ AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
+
+ AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.Equals(getPresentBeatmap()));
+ AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0);
+ }
+
+ private void waitForInitialSelection()
+ {
+ AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault);
+ AddUntilStep("wait for difficulty panels visible", () => songSelect.Carousel.ChildrenOfType().Any());
+ }
+
private int getBeatmapIndex(BeatmapSetInfo set, BeatmapInfo info) => set.Beatmaps.FindIndex(b => b == info);
private int getCurrentBeatmapIndex() => getBeatmapIndex(songSelect.Carousel.SelectedBeatmapSet, songSelect.Carousel.SelectedBeatmap);
@@ -876,6 +948,8 @@ namespace osu.Game.Tests.Visual.SongSelect
public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
public new BeatmapCarousel Carousel => base.Carousel;
+ public new void PresentScore(ScoreInfo score) => base.PresentScore(score);
+
protected override bool OnStart()
{
StartRequested?.Invoke();
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index d7c30dc9ff..34ad1df6bc 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -140,7 +140,7 @@ namespace osu.Game.Beatmaps
{
var beatmapIds = beatmapSet.Beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList();
- LogForModel(beatmapSet, "Validating online IDs...");
+ LogForModel(beatmapSet, $"Validating online IDs for {beatmapSet.Beatmaps.Count} beatmaps...");
// ensure all IDs are unique
if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1))
diff --git a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs
index a33f4eb30d..5ecb477a2f 100644
--- a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs
+++ b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs
@@ -91,6 +91,8 @@ namespace osu.Game.Overlays.SearchableList
protected override void Dispose(bool isDisposing)
{
+ base.Dispose(isDisposing);
+
bindable.ValueChanged -= Bindable_ValueChanged;
}
}
diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs
index 179aab54a3..21ddc5685d 100644
--- a/osu.Game/Screens/Select/PlaySongSelect.cs
+++ b/osu.Game/Screens/Select/PlaySongSelect.cs
@@ -7,6 +7,7 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Framework.Screens;
using osu.Game.Graphics;
+using osu.Game.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking;
using osu.Game.Users;
@@ -32,9 +33,12 @@ namespace osu.Game.Screens.Select
Edit();
}, Key.Number4);
- ((PlayBeatmapDetailArea)BeatmapDetails).Leaderboard.ScoreSelected += score => this.Push(new ResultsScreen(score));
+ ((PlayBeatmapDetailArea)BeatmapDetails).Leaderboard.ScoreSelected += PresentScore;
}
+ protected void PresentScore(ScoreInfo score) =>
+ FinaliseSelection(score.Beatmap, score.Ruleset, () => this.Push(new ResultsScreen(score)));
+
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea();
public override void OnResuming(IScreen last)
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index 5b7c9082f3..d613b0ae8d 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -342,13 +342,17 @@ namespace osu.Game.Screens.Select
/// Call to make a selection and perform the default action for this SongSelect.
///
/// An optional beatmap to override the current carousel selection.
- /// Whether to trigger .
- public void FinaliseSelection(BeatmapInfo beatmap = null, bool performStartAction = true)
+ /// An optional ruleset to override the current carousel selection.
+ /// An optional custom action to perform instead of .
+ public void FinaliseSelection(BeatmapInfo beatmap = null, RulesetInfo ruleset = null, Action customStartAction = null)
{
// This is very important as we have not yet bound to screen-level bindables before the carousel load is completed.
if (!Carousel.BeatmapSetsLoaded)
return;
+ if (ruleset != null)
+ Ruleset.Value = ruleset;
+
transferRulesetValue();
// while transferRulesetValue will flush, it only does so if the ruleset changes.
@@ -369,7 +373,12 @@ namespace osu.Game.Screens.Select
selectionChangedDebounce = null;
}
- if (performStartAction && OnStart())
+ if (customStartAction != null)
+ {
+ customStartAction();
+ Carousel.AllowSelection = false;
+ }
+ else if (OnStart())
Carousel.AllowSelection = false;
}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 91c89cbc20..9db5fe562c 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 9ff7e3fc02..82253a0418 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -76,7 +76,7 @@
-
+