mirror of
https://github.com/ppy/osu.git
synced 2024-09-23 02:07:24 +08:00
Merge pull request #10282 from peppy/fix-editor-silence-on-seek
Fix hit samples playing while paused / seeking in the editor
This commit is contained in:
commit
db78a0edf4
@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
Tracking.BindValueChanged(updateSlidingSample);
|
Tracking.BindValueChanged(updateSlidingSample);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SkinnableSound slidingSample;
|
private PausableSkinnableSound slidingSample;
|
||||||
|
|
||||||
protected override void LoadSamples()
|
protected override void LoadSamples()
|
||||||
{
|
{
|
||||||
@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
var clone = HitObject.SampleControlPoint.ApplyTo(firstSample);
|
var clone = HitObject.SampleControlPoint.ApplyTo(firstSample);
|
||||||
clone.Name = "sliderslide";
|
clone.Name = "sliderslide";
|
||||||
|
|
||||||
AddInternal(slidingSample = new SkinnableSound(clone)
|
AddInternal(slidingSample = new PausableSkinnableSound(clone)
|
||||||
{
|
{
|
||||||
Looping = true
|
Looping = true
|
||||||
});
|
});
|
||||||
@ -112,10 +112,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
|
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
|
||||||
{
|
{
|
||||||
// note that samples will not start playing if exiting a seek operation in the middle of a slider.
|
if (tracking.NewValue)
|
||||||
// may be something we want to address at a later point, but not so easy to make happen right now
|
|
||||||
// (SkinnableSound would need to expose whether the sample is already playing and this logic would need to run in Update).
|
|
||||||
if (tracking.NewValue && ShouldPlaySamples)
|
|
||||||
slidingSample?.Play();
|
slidingSample?.Play();
|
||||||
else
|
else
|
||||||
slidingSample?.Stop();
|
slidingSample?.Stop();
|
||||||
|
@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
isSpinning.BindValueChanged(updateSpinningSample);
|
isSpinning.BindValueChanged(updateSpinningSample);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SkinnableSound spinningSample;
|
private PausableSkinnableSound spinningSample;
|
||||||
private const float spinning_sample_initial_frequency = 1.0f;
|
private const float spinning_sample_initial_frequency = 1.0f;
|
||||||
private const float spinning_sample_modulated_base_frequency = 0.5f;
|
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);
|
var clone = HitObject.SampleControlPoint.ApplyTo(firstSample);
|
||||||
clone.Name = "spinnerspin";
|
clone.Name = "spinnerspin";
|
||||||
|
|
||||||
AddInternal(spinningSample = new SkinnableSound(clone)
|
AddInternal(spinningSample = new PausableSkinnableSound(clone)
|
||||||
{
|
{
|
||||||
Volume = { Value = 0 },
|
Volume = { Value = 0 },
|
||||||
Looping = true,
|
Looping = true,
|
||||||
@ -113,10 +113,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
private void updateSpinningSample(ValueChangedEvent<bool> tracking)
|
private void updateSpinningSample(ValueChangedEvent<bool> tracking)
|
||||||
{
|
{
|
||||||
// note that samples will not start playing if exiting a seek operation in the middle of a spinner.
|
if (tracking.NewValue)
|
||||||
// may be something we want to address at a later point, but not so easy to make happen right now
|
|
||||||
// (SkinnableSound would need to expose whether the sample is already playing and this logic would need to run in Update).
|
|
||||||
if (tracking.NewValue && ShouldPlaySamples)
|
|
||||||
{
|
{
|
||||||
spinningSample?.Play();
|
spinningSample?.Play();
|
||||||
spinningSample?.VolumeTo(1, 200);
|
spinningSample?.VolumeTo(1, 200);
|
||||||
|
@ -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,
|
LifetimeStart = lifetimeStart,
|
||||||
LifetimeEnd = lifetimeEnd
|
LifetimeEnd = lifetimeEnd
|
||||||
@ -57,8 +57,8 @@ namespace osu.Game.Rulesets.Taiko.Audio
|
|||||||
|
|
||||||
public class DrumSample
|
public class DrumSample
|
||||||
{
|
{
|
||||||
public SkinnableSound Centre;
|
public PausableSkinnableSound Centre;
|
||||||
public SkinnableSound Rim;
|
public PausableSkinnableSound Rim;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,11 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
public class TestSceneSkinnableSound : OsuTestScene
|
public class TestSceneSkinnableSound : OsuTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached(typeof(ISamplePlaybackDisabler))]
|
||||||
private GameplayClock gameplayClock = new GameplayClock(new FramedClock());
|
private GameplayClock gameplayClock = new GameplayClock(new FramedClock());
|
||||||
|
|
||||||
private TestSkinSourceContainer skinSource;
|
private TestSkinSourceContainer skinSource;
|
||||||
private SkinnableSound skinnableSound;
|
private PausableSkinnableSound skinnableSound;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
Clock = gameplayClock,
|
Clock = gameplayClock,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = skinnableSound = new SkinnableSound(new SampleInfo("normal-sliderslide"))
|
Child = skinnableSound = new PausableSkinnableSound(new SampleInfo("normal-sliderslide"))
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -52,10 +52,10 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
|
|
||||||
public class NightcoreBeatContainer : BeatSyncedContainer
|
public class NightcoreBeatContainer : BeatSyncedContainer
|
||||||
{
|
{
|
||||||
private SkinnableSound hatSample;
|
private PausableSkinnableSound hatSample;
|
||||||
private SkinnableSound clapSample;
|
private PausableSkinnableSound clapSample;
|
||||||
private SkinnableSound kickSample;
|
private PausableSkinnableSound kickSample;
|
||||||
private SkinnableSound finishSample;
|
private PausableSkinnableSound finishSample;
|
||||||
|
|
||||||
private int? firstBeat;
|
private int? firstBeat;
|
||||||
|
|
||||||
@ -69,10 +69,10 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
{
|
{
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
hatSample = new SkinnableSound(new SampleInfo("nightcore-hat")),
|
hatSample = new PausableSkinnableSound(new SampleInfo("nightcore-hat")),
|
||||||
clapSample = new SkinnableSound(new SampleInfo("nightcore-clap")),
|
clapSample = new PausableSkinnableSound(new SampleInfo("nightcore-clap")),
|
||||||
kickSample = new SkinnableSound(new SampleInfo("nightcore-kick")),
|
kickSample = new PausableSkinnableSound(new SampleInfo("nightcore-kick")),
|
||||||
finishSample = new SkinnableSound(new SampleInfo("nightcore-finish")),
|
finishSample = new PausableSkinnableSound(new SampleInfo("nightcore-finish")),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ using osu.Game.Rulesets.Objects.Types;
|
|||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Objects.Drawables
|
namespace osu.Game.Rulesets.Objects.Drawables
|
||||||
@ -34,7 +33,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly Bindable<Color4> AccentColour = new Bindable<Color4>(Color4.Gray);
|
public readonly Bindable<Color4> AccentColour = new Bindable<Color4>(Color4.Gray);
|
||||||
|
|
||||||
protected SkinnableSound Samples { get; private set; }
|
protected PausableSkinnableSound Samples { get; private set; }
|
||||||
|
|
||||||
public virtual IEnumerable<HitSampleInfo> GetSamples() => HitObject.Samples;
|
public virtual IEnumerable<HitSampleInfo> GetSamples() => HitObject.Samples;
|
||||||
|
|
||||||
@ -179,7 +178,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
+ $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}.");
|
+ $" 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);
|
AddInternal(Samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,9 +358,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
|
||||||
private GameplayClock gameplayClock { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculate the position to be used for sample playback at a specified X position (0..1).
|
/// Calculate the position to be used for sample playback at a specified X position (0..1).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -374,18 +370,13 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
return balance_adjust_amount * (userPositionalHitSounds.Value ? position - 0.5f : 0);
|
return balance_adjust_amount * (userPositionalHitSounds.Value ? position - 0.5f : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether samples should currently be playing. Will be false during seek operations.
|
|
||||||
/// </summary>
|
|
||||||
protected bool ShouldPlaySamples => gameplayClock?.IsSeeking != true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Plays all the hit sounds for this <see cref="DrawableHitObject"/>.
|
/// Plays all the hit sounds for this <see cref="DrawableHitObject"/>.
|
||||||
/// This is invoked automatically when this <see cref="DrawableHitObject"/> is hit.
|
/// This is invoked automatically when this <see cref="DrawableHitObject"/> is hit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void PlaySamples()
|
public virtual void PlaySamples()
|
||||||
{
|
{
|
||||||
if (Samples != null && ShouldPlaySamples)
|
if (Samples != null)
|
||||||
{
|
{
|
||||||
Samples.Balance.Value = CalculateSamplePlaybackBalance(SamplePlaybackPosition);
|
Samples.Balance.Value = CalculateSamplePlaybackBalance(SamplePlaybackPosition);
|
||||||
Samples.Play();
|
Samples.Play();
|
||||||
|
@ -107,6 +107,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
UpdateClockSource();
|
UpdateClockSource();
|
||||||
|
|
||||||
dependencies.CacheAs(clock);
|
dependencies.CacheAs(clock);
|
||||||
|
dependencies.CacheAs<ISamplePlaybackDisabler>(clock);
|
||||||
AddInternal(clock);
|
AddInternal(clock);
|
||||||
|
|
||||||
// todo: remove caching of this and consume via editorBeatmap?
|
// todo: remove caching of this and consume via editorBeatmap?
|
||||||
|
@ -7,17 +7,18 @@ using osu.Framework.Audio.Track;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Transforms;
|
using osu.Framework.Graphics.Transforms;
|
||||||
using osu.Framework.Utils;
|
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit
|
namespace osu.Game.Screens.Edit
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A decoupled clock which adds editor-specific functionality, such as snapping to a user-defined beat divisor.
|
/// A decoupled clock which adds editor-specific functionality, such as snapping to a user-defined beat divisor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock
|
public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock, ISamplePlaybackDisabler
|
||||||
{
|
{
|
||||||
public IBindable<Track> Track => track;
|
public IBindable<Track> Track => track;
|
||||||
|
|
||||||
@ -31,6 +32,10 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
private readonly DecoupleableInterpolatingFramedClock underlyingClock;
|
private readonly DecoupleableInterpolatingFramedClock underlyingClock;
|
||||||
|
|
||||||
|
public IBindable<bool> SamplePlaybackDisabled => samplePlaybackDisabled;
|
||||||
|
|
||||||
|
private readonly Bindable<bool> samplePlaybackDisabled = new Bindable<bool>();
|
||||||
|
|
||||||
public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor)
|
public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor)
|
||||||
: this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor)
|
: this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor)
|
||||||
{
|
{
|
||||||
@ -166,11 +171,14 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
|
samplePlaybackDisabled.Value = true;
|
||||||
underlyingClock.Stop();
|
underlyingClock.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Seek(double position)
|
public bool Seek(double position)
|
||||||
{
|
{
|
||||||
|
samplePlaybackDisabled.Value = true;
|
||||||
|
|
||||||
ClearTransforms();
|
ClearTransforms();
|
||||||
return underlyingClock.Seek(position);
|
return underlyingClock.Seek(position);
|
||||||
}
|
}
|
||||||
@ -211,8 +219,35 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
private const double transform_time = 300;
|
private const double transform_time = 300;
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
updateSeekingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSeekingState()
|
||||||
|
{
|
||||||
|
if (samplePlaybackDisabled.Value)
|
||||||
|
{
|
||||||
|
if (track.Value?.IsRunning != true)
|
||||||
|
{
|
||||||
|
// seeking in the editor can happen while the track isn't running.
|
||||||
|
// in this case we always want to expose ourselves as seeking (to avoid sample playback).
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we are either running a seek tween or doing an immediate seek.
|
||||||
|
// in the case of an immediate seek the seeking bool will be set to false after one update.
|
||||||
|
// this allows for silencing hit sounds and the likes.
|
||||||
|
samplePlaybackDisabled.Value = Transforms.Any();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SeekTo(double seekDestination)
|
public void SeekTo(double seekDestination)
|
||||||
{
|
{
|
||||||
|
samplePlaybackDisabled.Value = true;
|
||||||
|
|
||||||
if (IsRunning)
|
if (IsRunning)
|
||||||
Seek(seekDestination);
|
Seek(seekDestination);
|
||||||
else
|
else
|
||||||
|
@ -16,7 +16,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
|
public class GameplayClock : IFrameBasedClock, ISamplePlaybackDisabler
|
||||||
{
|
{
|
||||||
private readonly IFrameBasedClock underlyingClock;
|
private readonly IFrameBasedClock underlyingClock;
|
||||||
|
|
||||||
@ -72,5 +72,7 @@ namespace osu.Game.Screens.Play
|
|||||||
public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo;
|
public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo;
|
||||||
|
|
||||||
public IClock Source => underlyingClock;
|
public IClock Source => underlyingClock;
|
||||||
|
|
||||||
|
public IBindable<bool> SamplePlaybackDisabled => IsPaused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ 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;
|
||||||
|
20
osu.Game/Screens/Play/ISamplePlaybackDisabler.cs
Normal file
20
osu.Game/Screens/Play/ISamplePlaybackDisabler.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// 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 osu.Framework.Bindables;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Allows a component to disable sample playback dynamically as required.
|
||||||
|
/// Handled by <see cref="PausableSkinnableSound"/>.
|
||||||
|
/// </summary>
|
||||||
|
public interface ISamplePlaybackDisabler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether sample playback should be disabled (or paused for looping samples).
|
||||||
|
/// </summary>
|
||||||
|
IBindable<bool> SamplePlaybackDisabled { get; }
|
||||||
|
}
|
||||||
|
}
|
66
osu.Game/Skinning/PausableSkinnableSound.cs
Normal file
66
osu.Game/Skinning/PausableSkinnableSound.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// 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 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<ISampleInfo> hitSamples)
|
||||||
|
: base(hitSamples)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IBindable<bool> samplePlaybackDisabled = new Bindable<bool>();
|
||||||
|
|
||||||
|
[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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,6 @@ using osu.Framework.Extensions.IEnumerableExtensions;
|
|||||||
using osu.Framework.Graphics.Audio;
|
using osu.Framework.Graphics.Audio;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
@ -22,8 +21,6 @@ namespace osu.Game.Skinning
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private ISampleStore samples { get; set; }
|
private ISampleStore samples { get; set; }
|
||||||
|
|
||||||
private bool requestedPlaying;
|
|
||||||
|
|
||||||
public override bool RemoveWhenNotAlive => false;
|
public override bool RemoveWhenNotAlive => false;
|
||||||
public override bool RemoveCompletedTransforms => false;
|
public override bool RemoveCompletedTransforms => false;
|
||||||
|
|
||||||
@ -50,27 +47,6 @@ namespace osu.Game.Skinning
|
|||||||
InternalChild = samplesContainer = new AudioContainer<DrawableSample>();
|
InternalChild = samplesContainer = new AudioContainer<DrawableSample>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bindable<bool> gameplayClockPaused;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
|
||||||
private void load(GameplayClock gameplayClock)
|
|
||||||
{
|
|
||||||
// if in a gameplay context, pause sample playback when gameplay is paused.
|
|
||||||
gameplayClockPaused = gameplayClock?.IsPaused.GetBoundCopy();
|
|
||||||
gameplayClockPaused?.BindValueChanged(paused =>
|
|
||||||
{
|
|
||||||
if (requestedPlaying)
|
|
||||||
{
|
|
||||||
if (paused.NewValue)
|
|
||||||
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;
|
private bool looping;
|
||||||
|
|
||||||
public bool Looping
|
public bool Looping
|
||||||
@ -86,13 +62,7 @@ namespace osu.Game.Skinning
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Play()
|
public virtual void Play()
|
||||||
{
|
|
||||||
requestedPlaying = true;
|
|
||||||
play();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void play()
|
|
||||||
{
|
{
|
||||||
samplesContainer.ForEach(c =>
|
samplesContainer.ForEach(c =>
|
||||||
{
|
{
|
||||||
@ -101,13 +71,7 @@ namespace osu.Game.Skinning
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public virtual void Stop()
|
||||||
{
|
|
||||||
requestedPlaying = false;
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stop()
|
|
||||||
{
|
{
|
||||||
samplesContainer.ForEach(c => c.Stop());
|
samplesContainer.ForEach(c => c.Stop());
|
||||||
}
|
}
|
||||||
@ -142,7 +106,7 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
// Start playback internally for the new samples if the previous ones were playing beforehand.
|
// Start playback internally for the new samples if the previous ones were playing beforehand.
|
||||||
if (wasPlaying)
|
if (wasPlaying)
|
||||||
play();
|
Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Re-expose AudioContainer
|
#region Re-expose AudioContainer
|
||||||
|
Loading…
Reference in New Issue
Block a user