mirror of
https://github.com/ppy/osu
synced 2025-02-05 12:52:04 +00:00
Use existing bindable flow instead
This commit is contained in:
parent
585b857a0c
commit
d6f3beffb6
@ -112,10 +112,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
|
||||
{
|
||||
// note that samples will not start playing if exiting a seek operation in the middle of a slider.
|
||||
// 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)
|
||||
if (tracking.NewValue)
|
||||
slidingSample?.Play();
|
||||
else
|
||||
slidingSample?.Stop();
|
||||
|
@ -113,10 +113,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
private void updateSpinningSample(ValueChangedEvent<bool> tracking)
|
||||
{
|
||||
// note that samples will not start playing if exiting a seek operation in the middle of a spinner.
|
||||
// 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)
|
||||
if (tracking.NewValue)
|
||||
{
|
||||
spinningSample?.Play();
|
||||
spinningSample?.VolumeTo(1, 200);
|
||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneSkinnableSound : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
[Cached(typeof(ISamplePlaybackDisabler))]
|
||||
private GameplayClock gameplayClock = new GameplayClock(new FramedClock());
|
||||
|
||||
private TestSkinSourceContainer skinSource;
|
||||
|
@ -360,7 +360,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
}
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private ISeekableClock seekableClock { get; set; }
|
||||
private ISamplePlaybackDisabler samplePlaybackDisabler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the position to be used for sample playback at a specified X position (0..1).
|
||||
@ -374,18 +374,13 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
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 => seekableClock?.IsSeeking != true;
|
||||
|
||||
/// <summary>
|
||||
/// Plays all the hit sounds for this <see cref="DrawableHitObject"/>.
|
||||
/// This is invoked automatically when this <see cref="DrawableHitObject"/> is hit.
|
||||
/// </summary>
|
||||
public virtual void PlaySamples()
|
||||
{
|
||||
if (Samples != null && ShouldPlaySamples)
|
||||
if (Samples != null)
|
||||
{
|
||||
Samples.Balance.Value = CalculateSamplePlaybackBalance(SamplePlaybackPosition);
|
||||
Samples.Play();
|
||||
|
@ -107,7 +107,7 @@ namespace osu.Game.Screens.Edit
|
||||
UpdateClockSource();
|
||||
|
||||
dependencies.CacheAs(clock);
|
||||
dependencies.CacheAs<ISeekableClock>(clock);
|
||||
dependencies.CacheAs<ISamplePlaybackDisabler>(clock);
|
||||
AddInternal(clock);
|
||||
|
||||
// todo: remove caching of this and consume via editorBeatmap?
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Screens.Edit
|
||||
/// <summary>
|
||||
/// A decoupled clock which adds editor-specific functionality, such as snapping to a user-defined beat divisor.
|
||||
/// </summary>
|
||||
public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock, ISeekableClock
|
||||
public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock, ISamplePlaybackDisabler
|
||||
{
|
||||
public IBindable<Track> Track => track;
|
||||
|
||||
@ -32,6 +32,10 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
private readonly DecoupleableInterpolatingFramedClock underlyingClock;
|
||||
|
||||
public IBindable<bool> SamplePlaybackDisabled => samplePlaybackDisabled;
|
||||
|
||||
private readonly Bindable<bool> samplePlaybackDisabled = new Bindable<bool>();
|
||||
|
||||
public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor)
|
||||
: this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor)
|
||||
{
|
||||
@ -167,11 +171,14 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
samplePlaybackDisabled.Value = true;
|
||||
underlyingClock.Stop();
|
||||
}
|
||||
|
||||
public bool Seek(double position)
|
||||
{
|
||||
samplePlaybackDisabled.Value = true;
|
||||
|
||||
ClearTransforms();
|
||||
return underlyingClock.Seek(position);
|
||||
}
|
||||
@ -212,26 +219,34 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
private const double transform_time = 300;
|
||||
|
||||
public bool IsSeeking { get; private set; }
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (IsSeeking)
|
||||
updateSeekingState();
|
||||
}
|
||||
|
||||
private void updateSeekingState()
|
||||
{
|
||||
if (samplePlaybackDisabled.Value)
|
||||
{
|
||||
bool isPaused = track.Value?.IsRunning != true;
|
||||
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.
|
||||
IsSeeking = isPaused || Transforms.Any();
|
||||
samplePlaybackDisabled.Value = Transforms.Any();
|
||||
}
|
||||
}
|
||||
|
||||
public void SeekTo(double seekDestination)
|
||||
{
|
||||
IsSeeking = true;
|
||||
samplePlaybackDisabled.Value = true;
|
||||
|
||||
if (IsRunning)
|
||||
Seek(seekDestination);
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Screens.Play
|
||||
/// <see cref="IFrameBasedClock"/>, as this should only be done once to ensure accuracy.
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
public class GameplayClock : IFrameBasedClock, ISeekableClock
|
||||
public class GameplayClock : IFrameBasedClock, ISamplePlaybackDisabler
|
||||
{
|
||||
private readonly IFrameBasedClock underlyingClock;
|
||||
|
||||
@ -48,5 +48,7 @@ namespace osu.Game.Screens.Play
|
||||
public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo;
|
||||
|
||||
public IClock Source => underlyingClock;
|
||||
|
||||
public IBindable<bool> SamplePlaybackDisabled => IsPaused;
|
||||
}
|
||||
}
|
||||
|
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="SkinnableSound"/>.
|
||||
/// </summary>
|
||||
public interface ISamplePlaybackDisabler
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether sample playback should be disabled (or paused for looping samples).
|
||||
/// </summary>
|
||||
IBindable<bool> SamplePlaybackDisabled { get; }
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public interface ISeekableClock
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether an ongoing seek operation is active.
|
||||
/// </summary>
|
||||
bool IsSeeking { get; }
|
||||
}
|
||||
}
|
@ -50,25 +50,28 @@ namespace osu.Game.Skinning
|
||||
InternalChild = samplesContainer = new AudioContainer<DrawableSample>();
|
||||
}
|
||||
|
||||
private Bindable<bool> gameplayClockPaused;
|
||||
private readonly IBindable<bool> samplePlaybackDisabled = new Bindable<bool>();
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(GameplayClock gameplayClock)
|
||||
private void load(ISamplePlaybackDisabler samplePlaybackDisabler)
|
||||
{
|
||||
// if in a gameplay context, pause sample playback when gameplay is paused.
|
||||
gameplayClockPaused = gameplayClock?.IsPaused.GetBoundCopy();
|
||||
gameplayClockPaused?.BindValueChanged(paused =>
|
||||
if (samplePlaybackDisabler != null)
|
||||
{
|
||||
if (requestedPlaying)
|
||||
samplePlaybackDisabled.BindTo(samplePlaybackDisabler.SamplePlaybackDisabled);
|
||||
samplePlaybackDisabled.BindValueChanged(disabled =>
|
||||
{
|
||||
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();
|
||||
}
|
||||
});
|
||||
if (requestedPlaying)
|
||||
{
|
||||
if (disabled.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;
|
||||
@ -94,6 +97,9 @@ namespace osu.Game.Skinning
|
||||
|
||||
private void play()
|
||||
{
|
||||
if (samplePlaybackDisabled.Value)
|
||||
return;
|
||||
|
||||
samplesContainer.ForEach(c =>
|
||||
{
|
||||
if (PlayWhenZeroVolume || c.AggregateVolume.Value > 0)
|
||||
|
Loading…
Reference in New Issue
Block a user