diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 3da28f3560..e84f34e0d5 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -29,6 +29,11 @@ namespace osu.Game.Screens.Play /// protected readonly DecoupleableInterpolatingFramedClock AdjustableSource; + /// + /// The offset at which to start playing. Affects the time which the clock is reset to via . + /// + protected virtual double StartOffset => 0; + /// /// The source clock. /// @@ -93,9 +98,12 @@ namespace osu.Game.Screens.Play { ChangeSource(SourceClock); - AdjustableSource.Seek(0); + AdjustableSource.Seek(StartOffset); AdjustableSource.Stop(); + // Make sure the gameplay clock takes on the new time, otherwise the adjustable source will be seeked to the gameplay clock time in Start(). + GameplayClock.UnderlyingClock.ProcessFrame(); + if (!IsPaused.Value) Start(); } diff --git a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs index f019e50b60..05d34fb8d4 100644 --- a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs +++ b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs @@ -47,6 +47,9 @@ namespace osu.Game.Screens.Play private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); + protected override double StartOffset => startOffset; + private double startOffset; + private readonly WorkingBeatmap beatmap; private readonly double gameplayStartTime; private readonly bool startAtGameplayStart; @@ -74,27 +77,23 @@ namespace osu.Game.Screens.Play userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); // sane default provided by ruleset. - double startTime = gameplayStartTime; + startOffset = gameplayStartTime; if (!startAtGameplayStart) { - startTime = Math.Min(0, startTime); + startOffset = Math.Min(0, startOffset); // if a storyboard is present, it may dictate the appropriate start time by having events in negative time space. // this is commonly used to display an intro before the audio track start. double? firstStoryboardEvent = beatmap.Storyboard.EarliestEventTime; if (firstStoryboardEvent != null) - startTime = Math.Min(startTime, firstStoryboardEvent.Value); + startOffset = Math.Min(startOffset, firstStoryboardEvent.Value); // some beatmaps specify a current lead-in time which should be used instead of the ruleset-provided value when available. // this is not available as an option in the live editor but can still be applied via .osu editing. if (beatmap.BeatmapInfo.AudioLeadIn > 0) - startTime = Math.Min(startTime, firstHitObjectTime - beatmap.BeatmapInfo.AudioLeadIn); + startOffset = Math.Min(startOffset, firstHitObjectTime - beatmap.BeatmapInfo.AudioLeadIn); } - - Seek(startTime); - - AdjustableSource.ProcessFrame(); } protected override void OnIsPausedChanged(ValueChangedEvent isPaused)