1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-21 13:42:55 +08:00

Merge pull request #10505 from peppy/skin-disabler-refactor

Move ISampleDisabler implementation to Player and FrameStabilityContainer
This commit is contained in:
Dan Balasescu 2020-10-15 19:14:52 +09:00 committed by GitHub
commit 93dfbd5d9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 39 deletions

View File

@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddStep("get variables", () => AddStep("get variables", () =>
{ {
gameplayClock = Player.ChildrenOfType<FrameStabilityContainer>().First().GameplayClock; gameplayClock = Player.ChildrenOfType<FrameStabilityContainer>().First();
slider = Player.ChildrenOfType<DrawableSlider>().OrderBy(s => s.HitObject.StartTime).First(); slider = Player.ChildrenOfType<DrawableSlider>().OrderBy(s => s.HitObject.StartTime).First();
samples = slider.ChildrenOfType<DrawableSample>().ToArray(); samples = slider.ChildrenOfType<DrawableSample>().ToArray();
}); });

View File

@ -13,7 +13,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.OpenGL.Textures;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osu.Game.Skinning; using osu.Game.Skinning;
@ -22,27 +21,24 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
public class TestSceneSkinnableSound : OsuTestScene public class TestSceneSkinnableSound : OsuTestScene
{ {
[Cached(typeof(ISamplePlaybackDisabler))]
private GameplayClock gameplayClock = new GameplayClock(new FramedClock());
private TestSkinSourceContainer skinSource; private TestSkinSourceContainer skinSource;
private PausableSkinnableSound skinnableSound; private PausableSkinnableSound skinnableSound;
[SetUp] [SetUp]
public void SetUp() => Schedule(() => public void SetUpSteps()
{
AddStep("setup hierarchy", () =>
{ {
gameplayClock.IsPaused.Value = false;
Children = new Drawable[] Children = new Drawable[]
{ {
skinSource = new TestSkinSourceContainer skinSource = new TestSkinSourceContainer
{ {
Clock = gameplayClock,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Child = skinnableSound = new PausableSkinnableSound(new SampleInfo("normal-sliderslide")) Child = skinnableSound = new PausableSkinnableSound(new SampleInfo("normal-sliderslide"))
}, },
}; };
}); });
}
[Test] [Test]
public void TestStoppedSoundDoesntResumeAfterPause() public void TestStoppedSoundDoesntResumeAfterPause()
@ -62,8 +58,9 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("wait for sample to stop playing", () => !sample.Playing); AddUntilStep("wait for sample to stop playing", () => !sample.Playing);
AddStep("pause gameplay clock", () => gameplayClock.IsPaused.Value = true); AddStep("disable sample playback", () => skinSource.SamplePlaybackDisabled.Value = true);
AddStep("resume gameplay clock", () => gameplayClock.IsPaused.Value = false);
AddStep("enable sample playback", () => skinSource.SamplePlaybackDisabled.Value = false);
AddWaitStep("wait a bit", 5); AddWaitStep("wait a bit", 5);
AddAssert("sample not playing", () => !sample.Playing); AddAssert("sample not playing", () => !sample.Playing);
@ -82,8 +79,11 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("wait for sample to start playing", () => sample.Playing); AddUntilStep("wait for sample to start playing", () => sample.Playing);
AddStep("pause gameplay clock", () => gameplayClock.IsPaused.Value = true); AddStep("disable sample playback", () => skinSource.SamplePlaybackDisabled.Value = true);
AddUntilStep("wait for sample to stop playing", () => !sample.Playing); AddUntilStep("wait for sample to stop playing", () => !sample.Playing);
AddStep("enable sample playback", () => skinSource.SamplePlaybackDisabled.Value = false);
AddUntilStep("wait for sample to start playing", () => sample.Playing);
} }
[Test] [Test]
@ -98,10 +98,11 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("sample playing", () => sample.Playing); AddAssert("sample playing", () => sample.Playing);
AddStep("pause gameplay clock", () => gameplayClock.IsPaused.Value = true); AddStep("disable sample playback", () => skinSource.SamplePlaybackDisabled.Value = true);
AddUntilStep("wait for sample to stop playing", () => !sample.Playing);
AddStep("resume gameplay clock", () => gameplayClock.IsPaused.Value = false); AddUntilStep("sample not playing", () => !sample.Playing);
AddStep("enable sample playback", () => skinSource.SamplePlaybackDisabled.Value = false);
AddAssert("sample not playing", () => !sample.Playing); AddAssert("sample not playing", () => !sample.Playing);
AddAssert("sample not playing", () => !sample.Playing); AddAssert("sample not playing", () => !sample.Playing);
@ -120,7 +121,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("sample playing", () => sample.Playing); AddAssert("sample playing", () => sample.Playing);
AddStep("pause gameplay clock", () => gameplayClock.IsPaused.Value = true); AddStep("disable sample playback", () => skinSource.SamplePlaybackDisabled.Value = true);
AddUntilStep("wait for sample to stop playing", () => !sample.Playing); AddUntilStep("wait for sample to stop playing", () => !sample.Playing);
AddStep("trigger skin change", () => skinSource.TriggerSourceChanged()); AddStep("trigger skin change", () => skinSource.TriggerSourceChanged());
@ -133,20 +134,25 @@ namespace osu.Game.Tests.Visual.Gameplay
}); });
AddAssert("new sample stopped", () => !sample.Playing); AddAssert("new sample stopped", () => !sample.Playing);
AddStep("resume gameplay clock", () => gameplayClock.IsPaused.Value = false); AddStep("enable sample playback", () => skinSource.SamplePlaybackDisabled.Value = false);
AddWaitStep("wait a bit", 5); AddWaitStep("wait a bit", 5);
AddAssert("new sample not played", () => !sample.Playing); AddAssert("new sample not played", () => !sample.Playing);
} }
[Cached(typeof(ISkinSource))] [Cached(typeof(ISkinSource))]
private class TestSkinSourceContainer : Container, ISkinSource [Cached(typeof(ISamplePlaybackDisabler))]
private class TestSkinSourceContainer : Container, ISkinSource, ISamplePlaybackDisabler
{ {
[Resolved] [Resolved]
private ISkinSource source { get; set; } private ISkinSource source { get; set; }
public event Action SourceChanged; public event Action SourceChanged;
public Bindable<bool> SamplePlaybackDisabled { get; } = new Bindable<bool>();
IBindable<bool> ISamplePlaybackDisabler.SamplePlaybackDisabled => SamplePlaybackDisabled;
public Drawable GetDrawableComponent(ISkinComponent component) => source?.GetDrawableComponent(component); public Drawable GetDrawableComponent(ISkinComponent component) => source?.GetDrawableComponent(component);
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => source?.GetTexture(componentName, wrapModeS, wrapModeT); public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => source?.GetTexture(componentName, wrapModeS, wrapModeT);
public SampleChannel GetSample(ISampleInfo sampleInfo) => source?.GetSample(sampleInfo); public SampleChannel GetSample(ISampleInfo sampleInfo) => source?.GetSample(sampleInfo);

View File

@ -18,8 +18,11 @@ namespace osu.Game.Rulesets.UI
/// A container which consumes a parent gameplay clock and standardises frame counts for children. /// A container which consumes a parent gameplay clock and standardises frame counts for children.
/// Will ensure a minimum of 50 frames per clock second is maintained, regardless of any system lag or seeks. /// Will ensure a minimum of 50 frames per clock second is maintained, regardless of any system lag or seeks.
/// </summary> /// </summary>
public class FrameStabilityContainer : Container, IHasReplayHandler [Cached(typeof(ISamplePlaybackDisabler))]
public class FrameStabilityContainer : Container, IHasReplayHandler, ISamplePlaybackDisabler
{ {
private readonly Bindable<bool> samplePlaybackDisabled = new Bindable<bool>();
private readonly double gameplayStartTime; private readonly double gameplayStartTime;
/// <summary> /// <summary>
@ -35,7 +38,6 @@ namespace osu.Game.Rulesets.UI
public GameplayClock GameplayClock => stabilityGameplayClock; public GameplayClock GameplayClock => stabilityGameplayClock;
[Cached(typeof(GameplayClock))] [Cached(typeof(GameplayClock))]
[Cached(typeof(ISamplePlaybackDisabler))]
private readonly StabilityGameplayClock stabilityGameplayClock; private readonly StabilityGameplayClock stabilityGameplayClock;
public FrameStabilityContainer(double gameplayStartTime = double.MinValue) public FrameStabilityContainer(double gameplayStartTime = double.MinValue)
@ -102,6 +104,8 @@ namespace osu.Game.Rulesets.UI
requireMoreUpdateLoops = true; requireMoreUpdateLoops = true;
validState = !GameplayClock.IsPaused.Value; validState = !GameplayClock.IsPaused.Value;
samplePlaybackDisabled.Value = stabilityGameplayClock.ShouldDisableSamplePlayback;
int loops = 0; int loops = 0;
while (validState && requireMoreUpdateLoops && loops++ < MaxCatchUpFrames) while (validState && requireMoreUpdateLoops && loops++ < MaxCatchUpFrames)
@ -224,6 +228,8 @@ namespace osu.Game.Rulesets.UI
public ReplayInputHandler ReplayInputHandler { get; set; } public ReplayInputHandler ReplayInputHandler { get; set; }
IBindable<bool> ISamplePlaybackDisabler.SamplePlaybackDisabled => samplePlaybackDisabled;
private class StabilityGameplayClock : GameplayClock private class StabilityGameplayClock : GameplayClock
{ {
public GameplayClock ParentGameplayClock; public GameplayClock ParentGameplayClock;
@ -237,7 +243,7 @@ namespace osu.Game.Rulesets.UI
{ {
} }
protected override bool ShouldDisableSamplePlayback => public override bool ShouldDisableSamplePlayback =>
// handle the case where playback is catching up to real-time. // handle the case where playback is catching up to real-time.
base.ShouldDisableSamplePlayback base.ShouldDisableSamplePlayback
|| ParentSampleDisabler?.SamplePlaybackDisabled.Value == true || ParentSampleDisabler?.SamplePlaybackDisabled.Value == true

View File

@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play
/// <see cref="IFrameBasedClock"/>, as this should only be done once to ensure accuracy. /// <see cref="IFrameBasedClock"/>, as this should only be done once to ensure accuracy.
/// </remarks> /// </remarks>
/// </summary> /// </summary>
public class GameplayClock : IFrameBasedClock, ISamplePlaybackDisabler public class GameplayClock : IFrameBasedClock
{ {
private readonly IFrameBasedClock underlyingClock; private readonly IFrameBasedClock underlyingClock;
@ -28,8 +28,6 @@ namespace osu.Game.Screens.Play
/// </summary> /// </summary>
public virtual IEnumerable<Bindable<double>> NonGameplayAdjustments => Enumerable.Empty<Bindable<double>>(); public virtual IEnumerable<Bindable<double>> NonGameplayAdjustments => Enumerable.Empty<Bindable<double>>();
private readonly Bindable<bool> samplePlaybackDisabled = new Bindable<bool>();
public GameplayClock(IFrameBasedClock underlyingClock) public GameplayClock(IFrameBasedClock underlyingClock)
{ {
this.underlyingClock = underlyingClock; this.underlyingClock = underlyingClock;
@ -66,13 +64,11 @@ namespace osu.Game.Screens.Play
/// <summary> /// <summary>
/// Whether nested samples supporting the <see cref="ISamplePlaybackDisabler"/> interface should be paused. /// Whether nested samples supporting the <see cref="ISamplePlaybackDisabler"/> interface should be paused.
/// </summary> /// </summary>
protected virtual bool ShouldDisableSamplePlayback => IsPaused.Value; public virtual bool ShouldDisableSamplePlayback => IsPaused.Value;
public void ProcessFrame() public void ProcessFrame()
{ {
// intentionally not updating the underlying clock (handled externally). // intentionally not updating the underlying clock (handled externally).
samplePlaybackDisabled.Value = ShouldDisableSamplePlayback;
} }
public double ElapsedFrameTime => underlyingClock.ElapsedFrameTime; public double ElapsedFrameTime => underlyingClock.ElapsedFrameTime;
@ -82,7 +78,5 @@ namespace osu.Game.Screens.Play
public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo; public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo;
public IClock Source => underlyingClock; public IClock Source => underlyingClock;
IBindable<bool> ISamplePlaybackDisabler.SamplePlaybackDisabled => samplePlaybackDisabled;
} }
} }

View File

@ -54,7 +54,6 @@ namespace osu.Game.Screens.Play
public GameplayClock GameplayClock => localGameplayClock; public GameplayClock GameplayClock => localGameplayClock;
[Cached(typeof(GameplayClock))] [Cached(typeof(GameplayClock))]
[Cached(typeof(ISamplePlaybackDisabler))]
private readonly LocalGameplayClock localGameplayClock; private readonly LocalGameplayClock localGameplayClock;
private Bindable<double> userAudioOffset; private Bindable<double> userAudioOffset;

View File

@ -35,7 +35,8 @@ using osu.Game.Users;
namespace osu.Game.Screens.Play namespace osu.Game.Screens.Play
{ {
[Cached] [Cached]
public class Player : ScreenWithBeatmapBackground [Cached(typeof(ISamplePlaybackDisabler))]
public class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler
{ {
/// <summary> /// <summary>
/// The delay upon completion of the beatmap before displaying the results screen. /// The delay upon completion of the beatmap before displaying the results screen.
@ -55,6 +56,8 @@ namespace osu.Game.Screens.Play
// We are managing our own adjustments (see OnEntering/OnExiting). // We are managing our own adjustments (see OnEntering/OnExiting).
public override bool AllowRateAdjustments => false; public override bool AllowRateAdjustments => false;
private readonly Bindable<bool> samplePlaybackDisabled = new Bindable<bool>();
/// <summary> /// <summary>
/// Whether gameplay should pause when the game window focus is lost. /// Whether gameplay should pause when the game window focus is lost.
/// </summary> /// </summary>
@ -229,7 +232,11 @@ namespace osu.Game.Screens.Play
skipOverlay.Hide(); skipOverlay.Hide();
} }
DrawableRuleset.IsPaused.BindValueChanged(_ => updateGameplayState()); DrawableRuleset.IsPaused.BindValueChanged(paused =>
{
updateGameplayState();
samplePlaybackDisabled.Value = paused.NewValue;
});
DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState());
DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true);
@ -752,5 +759,7 @@ namespace osu.Game.Screens.Play
} }
#endregion #endregion
IBindable<bool> ISamplePlaybackDisabler.SamplePlaybackDisabled => samplePlaybackDisabled;
} }
} }