diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs index 76bd9ef758..9a32cf42b0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -353,6 +353,8 @@ namespace osu.Game.Rulesets.Osu.Tests { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + protected override bool PauseOnFocusLost => false; + public ScoreAccessibleReplayPlayer(Score score) : base(score, false, false) { diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs index 81fab5b4b3..55e8a810fd 100644 --- a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -328,7 +328,7 @@ namespace osu.Game.Tests.Visual.Background public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR); } - private class TestPlayer : Player + private class TestPlayer : Visual.TestPlayer { protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs index 624e5f08bd..e5dc092c73 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); } - private class ScoreAccessiblePlayer : Player + private class ScoreAccessiblePlayer : TestPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs index 81ef41ceec..53ac990183 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -195,7 +195,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Player CreatePlayer(Ruleset ruleset) => new PausePlayer(); - protected class PausePlayer : Player + protected class PausePlayer : TestPlayer { public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; @@ -207,12 +207,6 @@ namespace osu.Game.Tests.Visual.Gameplay public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; - protected override void LoadComplete() - { - base.LoadComplete(); - HUDOverlay.HoldToQuit.PauseOnFocusLost = false; - } - public override void OnEntering(IScreen last) { base.OnEntering(last); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index 4ec0299c9a..b9a0421db7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay Player player = null; SlowLoadPlayer slowPlayer = null; - AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => player = new Player(false, false)))); + AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => player = new TestPlayer(false, false)))); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); AddUntilStep("wait for player to be current", () => player.IsCurrentScreen()); @@ -102,17 +102,17 @@ namespace osu.Game.Tests.Visual.Gameplay public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; } - private class TestPlayer : Player + private class TestPlayer : Visual.TestPlayer { public new Bindable> Mods => base.Mods; - public TestPlayer() - : base(false, false) + public TestPlayer(bool allowPause = true, bool showResults = true) + : base(allowPause, showResults) { } } - protected class SlowLoadPlayer : Player + protected class SlowLoadPlayer : Visual.TestPlayer { public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(false); diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs index 263070ab21..a302c978d2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs @@ -33,6 +33,8 @@ namespace osu.Game.Tests.Visual.Gameplay public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; + protected override bool PauseOnFocusLost => false; + public ScoreAccessibleReplayPlayer(Score score) : base(score) { diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 446df94aca..91c14591b1 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -25,6 +25,8 @@ namespace osu.Game.Screens.Play.HUD { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + public readonly Bindable IsPaused = new Bindable(); + private readonly Button button; public Action Action @@ -51,7 +53,8 @@ namespace osu.Game.Screens.Play.HUD button = new Button { HoverGained = () => text.FadeIn(500, Easing.OutQuint), - HoverLost = () => text.FadeOut(500, Easing.OutQuint) + HoverLost = () => text.FadeOut(500, Easing.OutQuint), + IsPaused = { BindTarget = IsPaused } } }; AutoSizeAxes = Axes.Both; @@ -94,6 +97,8 @@ namespace osu.Game.Screens.Play.HUD private CircularProgress circularProgress; private Circle overlayCircle; + public readonly Bindable IsPaused = new Bindable(); + protected override bool AllowMultipleFires => true; public Action HoverGained; @@ -217,7 +222,7 @@ namespace osu.Game.Screens.Play.HUD private void updateActive() { - if (!pauseOnFocusLost) return; + if (!pauseOnFocusLost || IsPaused.Value) return; if (gameActive.Value) AbortConfirm(); diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index ee229ab93e..017bf70133 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -131,14 +131,12 @@ namespace osu.Game.Screens.Play { base.LoadComplete(); - replayLoaded.ValueChanged += replayLoadedValueChanged; - replayLoaded.TriggerChange(); + replayLoaded.BindValueChanged(replayLoadedValueChanged, true); } private void replayLoadedValueChanged(ValueChangedEvent e) { PlayerSettingsOverlay.ReplayLoaded = e.NewValue; - HoldToQuit.PauseOnFocusLost = !e.NewValue; if (e.NewValue) { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fd9ddec314..92f53d3f9e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -40,6 +40,11 @@ namespace osu.Game.Screens.Play public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; + /// + /// Whether gameplay should pause when the game window focus is lost. + /// + protected virtual bool PauseOnFocusLost => true; + public Action RestartRequested; public bool HasFailed { get; private set; } @@ -132,7 +137,11 @@ namespace osu.Game.Screens.Play DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, Mods.Value) { - HoldToQuit = { Action = performUserRequestedExit }, + HoldToQuit = + { + Action = performUserRequestedExit, + IsPaused = { BindTarget = GameplayClockContainer.IsPaused } + }, PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, KeyCounter = { Visible = { BindTarget = DrawableRuleset.HasReplayLoaded } }, RequestSeek = GameplayClockContainer.Seek, @@ -167,6 +176,8 @@ namespace osu.Game.Screens.Play } }; + DrawableRuleset.HasReplayLoaded.BindValueChanged(e => HUDOverlay.HoldToQuit.PauseOnFocusLost = !e.NewValue && PauseOnFocusLost, true); + // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs index 40aa90f2d1..dc3ef1a85b 100644 --- a/osu.Game/Tests/Visual/AllPlayersTestCase.cs +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -76,6 +76,6 @@ namespace osu.Game.Tests.Visual return Player; } - protected virtual Player CreatePlayer(Ruleset ruleset) => new Player(false, false); + protected virtual Player CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false); } } diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index 85eacc7e09..5e453f0ac8 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -56,6 +56,6 @@ namespace osu.Game.Tests.Visual LoadScreen(Player); } - protected virtual Player CreatePlayer(Ruleset ruleset) => new Player(false, false); + protected virtual Player CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false); } } diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs new file mode 100644 index 0000000000..b93a1466e0 --- /dev/null +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual +{ + public class TestPlayer : Player + { + protected override bool PauseOnFocusLost => false; + + public TestPlayer(bool allowPause = true, bool showResults = true) + : base(allowPause, showResults) + { + } + } +}