Merge branch 'master' into fix-storyboard-sample-pausing

This commit is contained in:
Dean Herbert
2020-09-30 22:42:00 +09:00
35 changed files with 380 additions and 145 deletions

View File

@ -1,6 +1,8 @@
// 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.
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Timing;
@ -20,6 +22,11 @@ namespace osu.Game.Screens.Play
public readonly BindableBool IsPaused = new BindableBool();
/// <summary>
/// All adjustments applied to this clock which don't come from gameplay or mods.
/// </summary>
public virtual IEnumerable<Bindable<double>> NonGameplayAdjustments => Enumerable.Empty<Bindable<double>>();
public GameplayClock(IFrameBasedClock underlyingClock)
{
this.underlyingClock = underlyingClock;
@ -29,6 +36,23 @@ namespace osu.Game.Screens.Play
public double Rate => underlyingClock.Rate;
/// <summary>
/// The rate of gameplay when playback is at 100%.
/// This excludes any seeking / user adjustments.
/// </summary>
public double TrueGameplayRate
{
get
{
double baseRate = Rate;
foreach (var adjustment in NonGameplayAdjustments)
baseRate /= adjustment.Value;
return baseRate;
}
}
public bool IsRunning => underlyingClock.IsRunning;
/// <summary>

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
@ -50,9 +51,11 @@ namespace osu.Game.Screens.Play
/// <summary>
/// The final clock which is exposed to underlying components.
/// </summary>
[Cached]
public GameplayClock GameplayClock => localGameplayClock;
[Cached(typeof(GameplayClock))]
[Cached(typeof(ISamplePlaybackDisabler))]
public readonly GameplayClock GameplayClock;
private readonly LocalGameplayClock localGameplayClock;
private Bindable<double> userAudioOffset;
@ -80,7 +83,7 @@ namespace osu.Game.Screens.Play
userOffsetClock = new HardwareCorrectionOffsetClock(platformOffsetClock);
// the clock to be exposed via DI to children.
GameplayClock = new GameplayClock(userOffsetClock);
localGameplayClock = new LocalGameplayClock(userOffsetClock);
GameplayClock.IsPaused.BindTo(IsPaused);
}
@ -201,7 +204,9 @@ namespace osu.Game.Screens.Play
protected override void Update()
{
if (!IsPaused.Value)
{
userOffsetClock.ProcessFrame();
}
base.Update();
}
@ -216,6 +221,9 @@ namespace osu.Game.Screens.Play
track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate);
localGameplayClock.MutableNonGameplayAdjustments.Add(pauseFreqAdjust);
localGameplayClock.MutableNonGameplayAdjustments.Add(UserPlaybackRate);
speedAdjustmentsApplied = true;
}
@ -232,9 +240,24 @@ namespace osu.Game.Screens.Play
track.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
track.RemoveAdjustment(AdjustableProperty.Tempo, UserPlaybackRate);
localGameplayClock.MutableNonGameplayAdjustments.Remove(pauseFreqAdjust);
localGameplayClock.MutableNonGameplayAdjustments.Remove(UserPlaybackRate);
speedAdjustmentsApplied = false;
}
private class LocalGameplayClock : GameplayClock
{
public readonly List<Bindable<double>> MutableNonGameplayAdjustments = new List<Bindable<double>>();
public override IEnumerable<Bindable<double>> NonGameplayAdjustments => MutableNonGameplayAdjustments;
public LocalGameplayClock(FramedOffsetClock underlyingClock)
: base(underlyingClock)
{
}
}
private class HardwareCorrectionOffsetClock : FramedOffsetClock
{
// we always want to apply the same real-time offset, so it should be adjusted by the difference in playback rate (from realtime) to achieve this.

View File

@ -8,7 +8,7 @@ namespace osu.Game.Screens.Play
{
/// <summary>
/// Allows a component to disable sample playback dynamically as required.
/// Handled by <see cref="SkinnableSound"/>.
/// Handled by <see cref="PausableSkinnableSound"/>.
/// </summary>
public interface ISamplePlaybackDisabler
{

View File

@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play
AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke());
AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke());
AddInternal(pauseLoop = new UnpausableSkinnableSound(new SampleInfo("pause-loop"))
AddInternal(pauseLoop = new SkinnableSound(new SampleInfo("pause-loop"))
{
Looping = true,
Volume = { Value = 0 }
@ -54,15 +54,5 @@ namespace osu.Game.Screens.Play
pauseLoop.VolumeTo(0, TRANSITION_DURATION, Easing.OutQuad).Finally(_ => pauseLoop.Stop());
}
private class UnpausableSkinnableSound : SkinnableSound
{
protected override bool PlayWhenPaused => true;
public UnpausableSkinnableSound(SampleInfo sampleInfo)
: base(sampleInfo)
{
}
}
}
}