From 414c40d29849932734343123a8b89bf0725381c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 15:45:14 +0900 Subject: [PATCH] Reverse inheritance order of SkinnableSound's pause logic --- .../Objects/Drawables/DrawableSlider.cs | 4 +- .../Objects/Drawables/DrawableSpinner.cs | 4 +- .../Audio/DrumSampleContainer.cs | 8 +-- .../Gameplay/TestSceneSkinnableSound.cs | 4 +- osu.Game/Rulesets/Mods/ModNightcore.cs | 16 ++--- .../Objects/Drawables/DrawableHitObject.cs | 4 +- .../Screens/Play/ISamplePlaybackDisabler.cs | 2 +- osu.Game/Screens/Play/PauseOverlay.cs | 12 +--- osu.Game/Skinning/PausableSkinnableSound.cs | 66 +++++++++++++++++++ osu.Game/Skinning/SkinnableSound.cs | 50 +------------- 10 files changed, 91 insertions(+), 79 deletions(-) create mode 100644 osu.Game/Skinning/PausableSkinnableSound.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 68f203db47..b73ae5eeb9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Tracking.BindValueChanged(updateSlidingSample); } - private SkinnableSound slidingSample; + private PausableSkinnableSound slidingSample; protected override void LoadSamples() { @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables var clone = HitObject.SampleControlPoint.ApplyTo(firstSample); clone.Name = "sliderslide"; - AddInternal(slidingSample = new SkinnableSound(clone) + AddInternal(slidingSample = new PausableSkinnableSound(clone) { Looping = true }); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index b2a706833c..6488c60acf 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables isSpinning.BindValueChanged(updateSpinningSample); } - private SkinnableSound spinningSample; + private PausableSkinnableSound spinningSample; private const float spinning_sample_initial_frequency = 1.0f; private const float spinning_sample_modulated_base_frequency = 0.5f; @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables var clone = HitObject.SampleControlPoint.ApplyTo(firstSample); clone.Name = "spinnerspin"; - AddInternal(spinningSample = new SkinnableSound(clone) + AddInternal(spinningSample = new PausableSkinnableSound(clone) { Volume = { Value = 0 }, Looping = true, diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleContainer.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleContainer.cs index 7c39c040b1..fcf7c529f5 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleContainer.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleContainer.cs @@ -42,9 +42,9 @@ namespace osu.Game.Rulesets.Taiko.Audio } } - private SkinnableSound addSound(HitSampleInfo hitSampleInfo, double lifetimeStart, double lifetimeEnd) + private PausableSkinnableSound addSound(HitSampleInfo hitSampleInfo, double lifetimeStart, double lifetimeEnd) { - var drawable = new SkinnableSound(hitSampleInfo) + var drawable = new PausableSkinnableSound(hitSampleInfo) { LifetimeStart = lifetimeStart, LifetimeEnd = lifetimeEnd @@ -57,8 +57,8 @@ namespace osu.Game.Rulesets.Taiko.Audio public class DrumSample { - public SkinnableSound Centre; - public SkinnableSound Rim; + public PausableSkinnableSound Centre; + public PausableSkinnableSound Rim; } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs index 8b37cbd06f..8f2011e5dd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Gameplay private GameplayClock gameplayClock = new GameplayClock(new FramedClock()); private TestSkinSourceContainer skinSource; - private SkinnableSound skinnableSound; + private PausableSkinnableSound skinnableSound; [SetUp] public void SetUp() => Schedule(() => @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay { Clock = gameplayClock, RelativeSizeAxes = Axes.Both, - Child = skinnableSound = new SkinnableSound(new SampleInfo("normal-sliderslide")) + Child = skinnableSound = new PausableSkinnableSound(new SampleInfo("normal-sliderslide")) }, }; }); diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 4004953cd1..282de3a8e1 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -52,10 +52,10 @@ namespace osu.Game.Rulesets.Mods public class NightcoreBeatContainer : BeatSyncedContainer { - private SkinnableSound hatSample; - private SkinnableSound clapSample; - private SkinnableSound kickSample; - private SkinnableSound finishSample; + private PausableSkinnableSound hatSample; + private PausableSkinnableSound clapSample; + private PausableSkinnableSound kickSample; + private PausableSkinnableSound finishSample; private int? firstBeat; @@ -69,10 +69,10 @@ namespace osu.Game.Rulesets.Mods { InternalChildren = new Drawable[] { - hatSample = new SkinnableSound(new SampleInfo("nightcore-hat")), - clapSample = new SkinnableSound(new SampleInfo("nightcore-clap")), - kickSample = new SkinnableSound(new SampleInfo("nightcore-kick")), - finishSample = new SkinnableSound(new SampleInfo("nightcore-finish")), + hatSample = new PausableSkinnableSound(new SampleInfo("nightcore-hat")), + clapSample = new PausableSkinnableSound(new SampleInfo("nightcore-clap")), + kickSample = new PausableSkinnableSound(new SampleInfo("nightcore-kick")), + finishSample = new PausableSkinnableSound(new SampleInfo("nightcore-finish")), }; } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 796b8f7aae..59a3381b8b 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public readonly Bindable AccentColour = new Bindable(Color4.Gray); - protected SkinnableSound Samples { get; private set; } + protected PausableSkinnableSound Samples { get; private set; } public virtual IEnumerable GetSamples() => HitObject.Samples; @@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Objects.Drawables + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); } - Samples = new SkinnableSound(samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s))); + Samples = new PausableSkinnableSound(samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s))); AddInternal(Samples); } diff --git a/osu.Game/Screens/Play/ISamplePlaybackDisabler.cs b/osu.Game/Screens/Play/ISamplePlaybackDisabler.cs index 83e89d654b..6b37021fe6 100644 --- a/osu.Game/Screens/Play/ISamplePlaybackDisabler.cs +++ b/osu.Game/Screens/Play/ISamplePlaybackDisabler.cs @@ -8,7 +8,7 @@ namespace osu.Game.Screens.Play { /// /// Allows a component to disable sample playback dynamically as required. - /// Handled by . + /// Handled by . /// public interface ISamplePlaybackDisabler { diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index 9494971f8a..65f34aba3e 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -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) - { - } - } } } diff --git a/osu.Game/Skinning/PausableSkinnableSound.cs b/osu.Game/Skinning/PausableSkinnableSound.cs new file mode 100644 index 0000000000..991278fb98 --- /dev/null +++ b/osu.Game/Skinning/PausableSkinnableSound.cs @@ -0,0 +1,66 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Audio; +using osu.Game.Screens.Play; + +namespace osu.Game.Skinning +{ + public class PausableSkinnableSound : SkinnableSound + { + protected bool RequestedPlaying { get; private set; } + + public PausableSkinnableSound(ISampleInfo hitSamples) + : base(hitSamples) + { + } + + public PausableSkinnableSound(IEnumerable hitSamples) + : base(hitSamples) + { + } + + private readonly IBindable samplePlaybackDisabled = new Bindable(); + + [BackgroundDependencyLoader(true)] + private void load(ISamplePlaybackDisabler samplePlaybackDisabler) + { + // if in a gameplay context, pause sample playback when gameplay is paused. + if (samplePlaybackDisabler != null) + { + samplePlaybackDisabled.BindTo(samplePlaybackDisabler.SamplePlaybackDisabled); + samplePlaybackDisabled.BindValueChanged(disabled => + { + if (RequestedPlaying) + { + if (disabled.NewValue) + base.Stop(); + // it's not easy to know if a sample has finished playing (to end). + // to keep things simple only resume playing looping samples. + else if (Looping) + base.Play(); + } + }); + } + } + + public override void Play() + { + RequestedPlaying = true; + + if (samplePlaybackDisabled.Value) + return; + + base.Play(); + } + + public override void Stop() + { + RequestedPlaying = false; + base.Stop(); + } + } +} diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index f3ab8b86bc..91bdcd7444 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -11,7 +11,6 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; using osu.Game.Audio; -using osu.Game.Screens.Play; namespace osu.Game.Skinning { @@ -22,8 +21,6 @@ namespace osu.Game.Skinning [Resolved] private ISampleStore samples { get; set; } - private bool requestedPlaying; - public override bool RemoveWhenNotAlive => false; public override bool RemoveCompletedTransforms => false; @@ -37,8 +34,6 @@ namespace osu.Game.Skinning /// protected bool PlayWhenZeroVolume => Looping; - protected virtual bool PlayWhenPaused => false; - private readonly AudioContainer samplesContainer; public SkinnableSound(ISampleInfo hitSamples) @@ -52,30 +47,6 @@ namespace osu.Game.Skinning InternalChild = samplesContainer = new AudioContainer(); } - private readonly IBindable samplePlaybackDisabled = new Bindable(); - - [BackgroundDependencyLoader(true)] - private void load(ISamplePlaybackDisabler samplePlaybackDisabler) - { - // if in a gameplay context, pause sample playback when gameplay is paused. - if (samplePlaybackDisabler != null) - { - samplePlaybackDisabled.BindTo(samplePlaybackDisabler.SamplePlaybackDisabled); - samplePlaybackDisabled.BindValueChanged(disabled => - { - if (requestedPlaying) - { - if (disabled.NewValue && !PlayWhenPaused) - stop(); - // it's not easy to know if a sample has finished playing (to end). - // to keep things simple only resume playing looping samples. - else if (Looping) - play(); - } - }); - } - } - private bool looping; public bool Looping @@ -91,17 +62,8 @@ namespace osu.Game.Skinning } } - public void Play() + public virtual void Play() { - requestedPlaying = true; - play(); - } - - private void play() - { - if (samplePlaybackDisabled.Value && !PlayWhenPaused) - return; - samplesContainer.ForEach(c => { if (PlayWhenZeroVolume || c.AggregateVolume.Value > 0) @@ -109,13 +71,7 @@ namespace osu.Game.Skinning }); } - public void Stop() - { - requestedPlaying = false; - stop(); - } - - private void stop() + public virtual void Stop() { samplesContainer.ForEach(c => c.Stop()); } @@ -150,7 +106,7 @@ namespace osu.Game.Skinning // Start playback internally for the new samples if the previous ones were playing beforehand. if (wasPlaying) - play(); + Play(); } #region Re-expose AudioContainer