diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs
index 1ae393d06a..ff82fb96ec 100644
--- a/osu.Game/Screens/Play/GameplayClockContainer.cs
+++ b/osu.Game/Screens/Play/GameplayClockContainer.cs
@@ -88,9 +88,7 @@ namespace osu.Game.Screens.Play
ensureSourceClockSet();
- // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time
- // This accounts for the clock source potentially taking time to enter a completely stopped state
- Seek(GameplayClock.CurrentTime);
+ PrepareStart();
// The case which caused this to be added is FrameStabilityContainer, which manages its own current and elapsed time.
// Because we generally update our own current time quicker than children can query it (via Start/Seek/Update),
@@ -111,11 +109,22 @@ namespace osu.Game.Screens.Play
});
}
+ ///
+ /// When is called, this will be run to give an opportunity to prepare the clock at the correct
+ /// start location.
+ ///
+ protected virtual void PrepareStart()
+ {
+ // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time
+ // This accounts for the clock source potentially taking time to enter a completely stopped state
+ Seek(GameplayClock.CurrentTime);
+ }
+
///
/// Seek to a specific time in gameplay.
///
/// The destination time to seek to.
- public void Seek(double time)
+ public virtual void Seek(double time)
{
Logger.Log($"{nameof(GameplayClockContainer)} seeking to {time}");
diff --git a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs
index 238817ad05..f0f5daf64d 100644
--- a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs
+++ b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs
@@ -8,6 +8,7 @@ using osu.Framework.Audio;
using osu.Framework.Audio.Track;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
+using osu.Framework.Logging;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
@@ -45,6 +46,17 @@ namespace osu.Game.Screens.Play
private readonly List> nonGameplayAdjustments = new List>();
+ ///
+ /// Stores the time at which the last call was triggered.
+ /// This is used to ensure we resume from that precise point in time, ignoring the proceeding frequency ramp.
+ ///
+ /// Optimally, we'd have gameplay ramp down with the frequency, but I believe this was intentionally disabled
+ /// to avoid fails occurring after the pause screen has been shown.
+ ///
+ /// In the future I want to change this.
+ ///
+ private double? actualStopTime;
+
public override IEnumerable NonGameplayAdjustments => nonGameplayAdjustments.Select(b => b.Value);
///
@@ -86,10 +98,12 @@ namespace osu.Game.Screens.Play
protected override void StopGameplayClock()
{
+ actualStopTime = GameplayClock.CurrentTime;
+
if (IsLoaded)
{
// During normal operation, the source is stopped after performing a frequency ramp.
- this.TransformBindableTo(GameplayClock.ExternalPauseFrequencyAdjust, 0, 200, Easing.Out).OnComplete(_ =>
+ this.TransformBindableTo(GameplayClock.ExternalPauseFrequencyAdjust, 0, 2000, Easing.Out).OnComplete(_ =>
{
if (IsPaused.Value)
base.StopGameplayClock();
@@ -108,6 +122,25 @@ namespace osu.Game.Screens.Play
}
}
+ public override void Seek(double time)
+ {
+ // Safety in case the clock is seeked while stopped.
+ actualStopTime = null;
+
+ base.Seek(time);
+ }
+
+ protected override void PrepareStart()
+ {
+ if (actualStopTime != null)
+ {
+ Seek(actualStopTime.Value);
+ actualStopTime = null;
+ }
+ else
+ base.PrepareStart();
+ }
+
protected override void StartGameplayClock()
{
addSourceClockAdjustments();
@@ -116,7 +149,7 @@ namespace osu.Game.Screens.Play
if (IsLoaded)
{
- this.TransformBindableTo(GameplayClock.ExternalPauseFrequencyAdjust, 1, 200, Easing.In);
+ this.TransformBindableTo(GameplayClock.ExternalPauseFrequencyAdjust, 1, 2000, Easing.In);
}
else
{
@@ -158,6 +191,14 @@ namespace osu.Game.Screens.Play
private bool speedAdjustmentsApplied;
+ protected override void Update()
+ {
+ base.Update();
+
+ if (GameplayClock.ExternalPauseFrequencyAdjust.Value < 1)
+ Logger.Log($"{GameplayClock.CurrentTime}");
+ }
+
private void addSourceClockAdjustments()
{
if (speedAdjustmentsApplied)