mirror of
https://github.com/ppy/osu
synced 2024-12-15 19:36:34 +00:00
Merge pull request #11833 from frenzibyte/fix-pofl-on-cooldown
Keep pausing gameplay on focus loss if cannot on first attempt
This commit is contained in:
commit
e679a1916f
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
@ -8,21 +9,17 @@ using osu.Framework.Platform;
|
|||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Storyboards;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
[HeadlessTest] // we alter unsafe properties on the game host to test inactive window state.
|
[HeadlessTest] // we alter unsafe properties on the game host to test inactive window state.
|
||||||
public class TestScenePauseWhenInactive : OsuPlayerTestScene
|
public class TestScenePauseWhenInactive : OsuPlayerTestScene
|
||||||
{
|
{
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
|
||||||
{
|
|
||||||
var beatmap = (Beatmap)base.CreateBeatmap(ruleset);
|
|
||||||
|
|
||||||
beatmap.HitObjects.RemoveAll(h => h.StartTime < 30000);
|
|
||||||
|
|
||||||
return beatmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private GameHost host { get; set; }
|
private GameHost host { get; set; }
|
||||||
|
|
||||||
@ -33,10 +30,57 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
AddStep("resume player", () => Player.GameplayClockContainer.Start());
|
AddStep("resume player", () => Player.GameplayClockContainer.Start());
|
||||||
AddAssert("ensure not paused", () => !Player.GameplayClockContainer.IsPaused.Value);
|
AddAssert("ensure not paused", () => !Player.GameplayClockContainer.IsPaused.Value);
|
||||||
|
|
||||||
|
AddStep("progress time to gameplay", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.GameplayStartTime));
|
||||||
|
AddUntilStep("wait for pause", () => Player.GameplayClockContainer.IsPaused.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests that if a pause from focus lose is performed while in pause cooldown,
|
||||||
|
/// the player will still pause after the cooldown is finished.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestPauseWhileInCooldown()
|
||||||
|
{
|
||||||
|
AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10)));
|
||||||
|
|
||||||
|
AddStep("resume player", () => Player.GameplayClockContainer.Start());
|
||||||
|
AddStep("skip to gameplay", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.GameplayStartTime));
|
||||||
|
|
||||||
|
AddStep("set inactive", () => ((Bindable<bool>)host.IsActive).Value = false);
|
||||||
|
AddUntilStep("wait for pause", () => Player.GameplayClockContainer.IsPaused.Value);
|
||||||
|
|
||||||
|
AddStep("set active", () => ((Bindable<bool>)host.IsActive).Value = true);
|
||||||
|
|
||||||
|
AddStep("resume player", () => Player.Resume());
|
||||||
|
AddAssert("unpaused", () => !Player.GameplayClockContainer.IsPaused.Value);
|
||||||
|
|
||||||
|
bool pauseCooldownActive = false;
|
||||||
|
|
||||||
|
AddStep("set inactive again", () =>
|
||||||
|
{
|
||||||
|
pauseCooldownActive = Player.PauseCooldownActive;
|
||||||
|
((Bindable<bool>)host.IsActive).Value = false;
|
||||||
|
});
|
||||||
|
AddAssert("pause cooldown active", () => pauseCooldownActive);
|
||||||
AddUntilStep("wait for pause", () => Player.GameplayClockContainer.IsPaused.Value);
|
AddUntilStep("wait for pause", () => Player.GameplayClockContainer.IsPaused.Value);
|
||||||
AddAssert("time of pause is after gameplay start time", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= Player.DrawableRuleset.GameplayStartTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
|
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
|
||||||
|
|
||||||
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||||
|
{
|
||||||
|
return new Beatmap
|
||||||
|
{
|
||||||
|
HitObjects = new List<HitObject>
|
||||||
|
{
|
||||||
|
new HitCircle { StartTime = 30000 },
|
||||||
|
new HitCircle { StartTime = 35000 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||||
|
=> new TestWorkingBeatmap(beatmap, storyboard, Audio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,11 +427,18 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private void updatePauseOnFocusLostState()
|
private void updatePauseOnFocusLostState()
|
||||||
{
|
{
|
||||||
if (!PauseOnFocusLost || breakTracker.IsBreakTime.Value)
|
if (!PauseOnFocusLost || !pausingSupportedByCurrentState || breakTracker.IsBreakTime.Value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (gameActive.Value == false)
|
if (gameActive.Value == false)
|
||||||
Pause();
|
{
|
||||||
|
bool paused = Pause();
|
||||||
|
|
||||||
|
// if the initial pause could not be satisfied, the pause cooldown may be active.
|
||||||
|
// reschedule the pause attempt until it can be achieved.
|
||||||
|
if (!paused)
|
||||||
|
Scheduler.AddOnce(updatePauseOnFocusLostState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IBeatmap loadPlayableBeatmap()
|
private IBeatmap loadPlayableBeatmap()
|
||||||
@ -674,6 +681,9 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private double? lastPauseActionTime;
|
private double? lastPauseActionTime;
|
||||||
|
|
||||||
|
protected bool PauseCooldownActive =>
|
||||||
|
lastPauseActionTime.HasValue && GameplayClockContainer.GameplayClock.CurrentTime < lastPauseActionTime + pause_cooldown;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A set of conditionals which defines whether the current game state and configuration allows for
|
/// A set of conditionals which defines whether the current game state and configuration allows for
|
||||||
/// pausing to be attempted via <see cref="Pause"/>. If false, the game should generally exit if a user pause
|
/// pausing to be attempted via <see cref="Pause"/>. If false, the game should generally exit if a user pause
|
||||||
@ -684,11 +694,9 @@ namespace osu.Game.Screens.Play
|
|||||||
LoadedBeatmapSuccessfully && Configuration.AllowPause && ValidForResume
|
LoadedBeatmapSuccessfully && Configuration.AllowPause && ValidForResume
|
||||||
// replays cannot be paused and exit immediately
|
// replays cannot be paused and exit immediately
|
||||||
&& !DrawableRuleset.HasReplayLoaded.Value
|
&& !DrawableRuleset.HasReplayLoaded.Value
|
||||||
|
// cannot pause if we are already in a fail state
|
||||||
&& !HasFailed;
|
&& !HasFailed;
|
||||||
|
|
||||||
private bool pauseCooldownActive =>
|
|
||||||
lastPauseActionTime.HasValue && GameplayClockContainer.GameplayClock.CurrentTime < lastPauseActionTime + pause_cooldown;
|
|
||||||
|
|
||||||
private bool canResume =>
|
private bool canResume =>
|
||||||
// cannot resume from a non-paused state
|
// cannot resume from a non-paused state
|
||||||
GameplayClockContainer.IsPaused.Value
|
GameplayClockContainer.IsPaused.Value
|
||||||
@ -697,12 +705,12 @@ namespace osu.Game.Screens.Play
|
|||||||
// already resuming
|
// already resuming
|
||||||
&& !IsResuming;
|
&& !IsResuming;
|
||||||
|
|
||||||
public void Pause()
|
public bool Pause()
|
||||||
{
|
{
|
||||||
if (!pausingSupportedByCurrentState) return;
|
if (!pausingSupportedByCurrentState) return false;
|
||||||
|
|
||||||
if (!IsResuming && pauseCooldownActive)
|
if (!IsResuming && PauseCooldownActive)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (IsResuming)
|
if (IsResuming)
|
||||||
{
|
{
|
||||||
@ -713,6 +721,7 @@ namespace osu.Game.Screens.Play
|
|||||||
GameplayClockContainer.Stop();
|
GameplayClockContainer.Stop();
|
||||||
PauseOverlay.Show();
|
PauseOverlay.Show();
|
||||||
lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime;
|
lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Resume()
|
public void Resume()
|
||||||
|
@ -34,6 +34,8 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
public new HealthProcessor HealthProcessor => base.HealthProcessor;
|
public new HealthProcessor HealthProcessor => base.HealthProcessor;
|
||||||
|
|
||||||
|
public new bool PauseCooldownActive => base.PauseCooldownActive;
|
||||||
|
|
||||||
public readonly List<JudgementResult> Results = new List<JudgementResult>();
|
public readonly List<JudgementResult> Results = new List<JudgementResult>();
|
||||||
|
|
||||||
public TestPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false)
|
public TestPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false)
|
||||||
|
Loading…
Reference in New Issue
Block a user