From 3c8f871b2815ca8f4618dbf2e51870e31324cae8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Dec 2020 17:39:08 +0900 Subject: [PATCH 1/3] Move player constructor configuration to dedicated class; add AllowRestart parameter --- .../TestSceneHoldNoteInput.cs | 6 +- .../TestSceneOutOfOrderHits.cs | 6 +- .../TestSceneLegacyBeatmapSkin.cs | 6 +- .../TestSceneOutOfOrderHits.cs | 6 +- .../TestSceneSliderInput.cs | 6 +- .../Screens/Multi/Play/TimeshiftPlayer.cs | 4 +- .../RealtimeMultiplayer/RealtimePlayer.cs | 7 +- osu.Game/Screens/Play/Player.cs | 140 +++++++++--------- osu.Game/Screens/Play/PlayerConfiguration.cs | 23 +++ osu.Game/Screens/Play/ReplayPlayer.cs | 4 +- osu.Game/Screens/Ranking/ResultsScreen.cs | 15 +- osu.Game/Tests/Visual/TestPlayer.cs | 6 +- 12 files changed, 146 insertions(+), 83 deletions(-) create mode 100644 osu.Game/Screens/Play/PlayerConfiguration.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 5cb1519196..596430f9e5 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -355,7 +355,11 @@ namespace osu.Game.Rulesets.Mania.Tests protected override bool PauseOnFocusLost => false; public ScoreAccessibleReplayPlayer(Score score) - : base(score, false, false) + : base(score, new PlayerConfiguration + { + AllowPause = false, + ShowResults = false, + }) { } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs index cecac38f70..18891f8c58 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs @@ -176,7 +176,11 @@ namespace osu.Game.Rulesets.Mania.Tests protected override bool PauseOnFocusLost => false; public ScoreAccessibleReplayPlayer(Score score) - : base(score, false, false) + : base(score, new PlayerConfiguration + { + AllowPause = false, + ShowResults = false, + }) { } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 3ff37c4147..a768626005 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -74,7 +74,11 @@ namespace osu.Game.Rulesets.Osu.Tests private readonly bool userHasCustomColours; public ExposedPlayer(bool userHasCustomColours) - : base(false, false) + : base(new PlayerConfiguration + { + AllowPause = false, + ShowResults = false, + }) { this.userHasCustomColours = userHasCustomColours; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs index 32a36ab317..296b421a11 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs @@ -439,7 +439,11 @@ namespace osu.Game.Rulesets.Osu.Tests protected override bool PauseOnFocusLost => false; public ScoreAccessibleReplayPlayer(Score score) - : base(score, false, false) + : base(score, new PlayerConfiguration + { + AllowPause = false, + ShowResults = false, + }) { } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 0164fb8bf4..2cc031405e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -378,7 +378,11 @@ namespace osu.Game.Rulesets.Osu.Tests protected override bool PauseOnFocusLost => false; public ScoreAccessibleReplayPlayer(Score score) - : base(score, false, false) + : base(score, new PlayerConfiguration + { + AllowPause = false, + ShowResults = false, + }) { } } diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index e8462088f1..f07f1c2fb0 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -37,8 +37,8 @@ namespace osu.Game.Screens.Multi.Play [Resolved] private IBindable ruleset { get; set; } - public TimeshiftPlayer(PlaylistItem playlistItem, bool allowPause = true) - : base(allowPause) + public TimeshiftPlayer(PlaylistItem playlistItem, PlayerConfiguration configuration = null) + : base(configuration) { PlaylistItem = playlistItem; } diff --git a/osu.Game/Screens/Multi/RealtimeMultiplayer/RealtimePlayer.cs b/osu.Game/Screens/Multi/RealtimeMultiplayer/RealtimePlayer.cs index c6d44686b5..4b878f43d0 100644 --- a/osu.Game/Screens/Multi/RealtimeMultiplayer/RealtimePlayer.cs +++ b/osu.Game/Screens/Multi/RealtimeMultiplayer/RealtimePlayer.cs @@ -12,6 +12,7 @@ using osu.Game.Online.Multiplayer; using osu.Game.Online.RealtimeMultiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Play; +using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Multi.RealtimeMultiplayer @@ -31,7 +32,11 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer private readonly ManualResetEventSlim startedEvent = new ManualResetEventSlim(); public RealtimePlayer(PlaylistItem playlistItem) - : base(playlistItem, false) + : base(playlistItem, new PlayerConfiguration + { + AllowPause = false, + AllowRestart = false, + }) { } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c539dff5d9..a1c91ab26b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -128,18 +128,14 @@ namespace osu.Game.Screens.Play /// protected virtual bool CheckModsAllowFailure() => Mods.Value.OfType().All(m => m.PerformFail()); - private readonly bool allowPause; - private readonly bool showResults; + public readonly PlayerConfiguration Configuration; /// /// Create a new player instance. /// - /// Whether pausing should be allowed. If not allowed, attempting to pause will quit. - /// Whether results screen should be pushed on completion. - public Player(bool allowPause = true, bool showResults = true) + public Player(PlayerConfiguration configuration = null) { - this.allowPause = allowPause; - this.showResults = showResults; + this.Configuration = configuration ??= new PlayerConfiguration(); } private GameplayBeatmap gameplayBeatmap; @@ -317,59 +313,77 @@ namespace osu.Game.Screens.Play } }; - private Drawable createOverlayComponents(WorkingBeatmap working) => new Container + private Drawable createOverlayComponents(WorkingBeatmap working) { - RelativeSizeAxes = Axes.Both, - Children = new[] + var container = new Container { - DimmableStoryboard.OverlayLayerContainer.CreateProxy(), - BreakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) + RelativeSizeAxes = Axes.Both, + Children = new[] { - Clock = DrawableRuleset.FrameStableClock, - ProcessCustomClock = false, - Breaks = working.Beatmap.Breaks - }, - // display the cursor above some HUD elements. - DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), - DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(), - HUDOverlay = new HUDOverlay(ScoreProcessor, HealthProcessor, DrawableRuleset, Mods.Value) - { - HoldToQuit = + DimmableStoryboard.OverlayLayerContainer.CreateProxy(), + BreakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { - Action = performUserRequestedExit, - IsPaused = { BindTarget = GameplayClockContainer.IsPaused } + Clock = DrawableRuleset.FrameStableClock, + ProcessCustomClock = false, + Breaks = working.Beatmap.Breaks }, - PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, - KeyCounter = + // display the cursor above some HUD elements. + DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), + DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(), + HUDOverlay = new HUDOverlay(ScoreProcessor, HealthProcessor, DrawableRuleset, Mods.Value) { - AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded }, - IsCounting = false + HoldToQuit = + { + Action = performUserRequestedExit, + IsPaused = { BindTarget = GameplayClockContainer.IsPaused } + }, + PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, + KeyCounter = + { + AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded }, + IsCounting = false + }, + RequestSeek = time => + { + GameplayClockContainer.Seek(time); + GameplayClockContainer.Start(); + }, + Anchor = Anchor.Centre, + Origin = Anchor.Centre }, - RequestSeek = time => + skipOverlay = new SkipOverlay(DrawableRuleset.GameplayStartTime) { - GameplayClockContainer.Seek(time); - GameplayClockContainer.Start(); + RequestSkip = GameplayClockContainer.Skip }, - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }, - skipOverlay = new SkipOverlay(DrawableRuleset.GameplayStartTime) - { - RequestSkip = GameplayClockContainer.Skip - }, - FailOverlay = new FailOverlay - { - OnRetry = Restart, - OnQuit = performUserRequestedExit, - }, - PauseOverlay = new PauseOverlay - { - OnResume = Resume, - Retries = RestartCount, - OnRetry = Restart, - OnQuit = performUserRequestedExit, - }, - new HotkeyRetryOverlay + FailOverlay = new FailOverlay + { + OnRetry = Restart, + OnQuit = performUserRequestedExit, + }, + PauseOverlay = new PauseOverlay + { + OnResume = Resume, + Retries = RestartCount, + OnRetry = Restart, + OnQuit = performUserRequestedExit, + }, + new HotkeyExitOverlay + { + Action = () => + { + if (!this.IsCurrentScreen()) return; + + fadeOut(true); + performImmediateExit(); + }, + }, + failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, }, + } + }; + + if (Configuration.AllowRestart) + { + container.Add(new HotkeyRetryOverlay { Action = () => { @@ -378,20 +392,11 @@ namespace osu.Game.Screens.Play fadeOut(true); Restart(); }, - }, - new HotkeyExitOverlay - { - Action = () => - { - if (!this.IsCurrentScreen()) return; - - fadeOut(true); - performImmediateExit(); - }, - }, - failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, }, + }); } - }; + + return container; + } private void onBreakTimeChanged(ValueChangedEvent isBreakTime) { @@ -490,6 +495,9 @@ namespace osu.Game.Screens.Play /// public void Restart() { + if (!Configuration.AllowRestart) + return; + // at the point of restarting the track should either already be paused or the volume should be zero. // stopping here is to ensure music doesn't become audible after exiting back to PlayerLoader. musicController.Stop(); @@ -529,7 +537,7 @@ namespace osu.Game.Screens.Play ValidForResume = false; - if (!showResults) return; + if (!Configuration.ShowResults) return; scoreSubmissionTask ??= Task.Run(async () => { @@ -628,7 +636,7 @@ namespace osu.Game.Screens.Play private bool canPause => // must pass basic screen conditions (beatmap loaded, instance allows pause) - LoadedBeatmapSuccessfully && allowPause && ValidForResume + LoadedBeatmapSuccessfully && Configuration.AllowPause && ValidForResume // replays cannot be paused and exit immediately && !DrawableRuleset.HasReplayLoaded.Value // cannot pause if we are already in a fail state diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs new file mode 100644 index 0000000000..475a234679 --- /dev/null +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Screens.Play +{ + public class PlayerConfiguration + { + /// + /// Whether pausing should be allowed. If not allowed, attempting to pause will quit. + /// + public bool AllowPause { get; set; } = true; + + /// + /// Whether results screen should be pushed on completion. + /// + public bool ShowResults { get; set; } = true; + + /// + /// Whether the player should be allowed to trigger a restart. + /// + public bool AllowRestart { get; set; } = true; + } +} diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index a07213cb33..e23cc22929 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -16,8 +16,8 @@ namespace osu.Game.Screens.Play // Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108) protected override bool CheckModsAllowFailure() => false; - public ReplayPlayer(Score score, bool allowPause = true, bool showResults = true) - : base(allowPause, showResults) + public ReplayPlayer(Score score, PlayerConfiguration configuration = null) + : base(configuration) { Score = score; } diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 528a1842af..8a12427798 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -164,15 +164,18 @@ namespace osu.Game.Screens.Ranking { buttons.Add(new RetryButton { Width = 300 }); - AddInternal(new HotkeyRetryOverlay + if (player?.Configuration.AllowRestart == true) { - Action = () => + AddInternal(new HotkeyRetryOverlay { - if (!this.IsCurrentScreen()) return; + Action = () => + { + if (!this.IsCurrentScreen()) return; - player?.Restart(); - }, - }); + player?.Restart(); + }, + }); + } } } diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index f016d29f38..f47391ce6a 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -37,7 +37,11 @@ namespace osu.Game.Tests.Visual public readonly List Results = new List(); public TestPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false) - : base(allowPause, showResults) + : base(new PlayerConfiguration + { + AllowPause = allowPause, + ShowResults = showResults + }) { PauseOnFocusLost = pauseOnFocusLost; } From f9fd909187c3839101e3c52aa476e2460b3e0778 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Dec 2020 18:07:38 +0900 Subject: [PATCH 2/3] Fix missed inspections --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a1c91ab26b..f1fb27e154 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -135,7 +135,7 @@ namespace osu.Game.Screens.Play /// public Player(PlayerConfiguration configuration = null) { - this.Configuration = configuration ??= new PlayerConfiguration(); + Configuration = configuration ?? new PlayerConfiguration(); } private GameplayBeatmap gameplayBeatmap; From 61a5d3ef4ae8d7724eb02686a01a33e85cbc4e0c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Dec 2020 13:32:35 +0900 Subject: [PATCH 3/3] Remove double handling of restart allowance on results screen (already handled locally) --- osu.Game/Screens/Ranking/ResultsScreen.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 8a12427798..528a1842af 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -164,18 +164,15 @@ namespace osu.Game.Screens.Ranking { buttons.Add(new RetryButton { Width = 300 }); - if (player?.Configuration.AllowRestart == true) + AddInternal(new HotkeyRetryOverlay { - AddInternal(new HotkeyRetryOverlay + Action = () => { - Action = () => - { - if (!this.IsCurrentScreen()) return; + if (!this.IsCurrentScreen()) return; - player?.Restart(); - }, - }); - } + player?.Restart(); + }, + }); } }