From 4f0c0ea5f9bb4d3dc7b671af349cf6ab87d15313 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Sep 2020 18:16:19 +0900 Subject: [PATCH 01/15] Fix hit samples playing while paused / seeking in the editor --- .../Objects/Drawables/DrawableHitObject.cs | 4 ++-- osu.Game/Screens/Edit/Editor.cs | 1 + osu.Game/Screens/Edit/EditorClock.cs | 22 +++++++++++++++++-- osu.Game/Screens/Play/GameplayClock.cs | 2 +- osu.Game/Screens/Play/ISeekableClock.cs | 13 +++++++++++ 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Screens/Play/ISeekableClock.cs diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 7c05bc9aa7..5b26607bf7 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -360,7 +360,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } [Resolved(canBeNull: true)] - private GameplayClock gameplayClock { get; set; } + private ISeekableClock seekableClock { get; set; } /// /// Calculate the position to be used for sample playback at a specified X position (0..1). @@ -377,7 +377,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether samples should currently be playing. Will be false during seek operations. /// - protected bool ShouldPlaySamples => gameplayClock?.IsSeeking != true; + protected bool ShouldPlaySamples => seekableClock?.IsSeeking != true; /// /// Plays all the hit sounds for this . diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index fd090e0959..1f5e261588 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -107,6 +107,7 @@ namespace osu.Game.Screens.Edit UpdateClockSource(); dependencies.CacheAs(clock); + dependencies.CacheAs(clock); AddInternal(clock); // todo: remove caching of this and consume via editorBeatmap? diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index ec203df064..ebc73c2bb8 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -7,17 +7,18 @@ using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; -using osu.Framework.Utils; using osu.Framework.Timing; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Screens.Play; namespace osu.Game.Screens.Edit { /// /// A decoupled clock which adds editor-specific functionality, such as snapping to a user-defined beat divisor. /// - public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock + public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock, ISeekableClock { public IBindable Track => track; @@ -211,8 +212,25 @@ 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) + { + // 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 = Transforms.Any(); + } + } + public void SeekTo(double seekDestination) { + IsSeeking = true; + if (IsRunning) Seek(seekDestination); else diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index 4f2cf5005c..b10e50882c 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Play /// , as this should only be done once to ensure accuracy. /// /// - public class GameplayClock : IFrameBasedClock + public class GameplayClock : IFrameBasedClock, ISeekableClock { private readonly IFrameBasedClock underlyingClock; diff --git a/osu.Game/Screens/Play/ISeekableClock.cs b/osu.Game/Screens/Play/ISeekableClock.cs new file mode 100644 index 0000000000..9d992a45fd --- /dev/null +++ b/osu.Game/Screens/Play/ISeekableClock.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . 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 + { + /// + /// Whether an ongoing seek operation is active. + /// + bool IsSeeking { get; } + } +} From 585b857a0c7f417a5fdfeb877d032324b4879f13 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 12:17:38 +0900 Subject: [PATCH 02/15] Handle paused state correctly --- osu.Game/Screens/Edit/EditorClock.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index ebc73c2bb8..99e5044b1f 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -220,10 +220,12 @@ namespace osu.Game.Screens.Edit if (IsSeeking) { + bool isPaused = track.Value?.IsRunning != true; + // 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 = Transforms.Any(); + IsSeeking = isPaused || Transforms.Any(); } } From d6f3beffb648f1a0e059a5d641984522c799b77b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 12:45:20 +0900 Subject: [PATCH 03/15] Use existing bindable flow instead --- .../Objects/Drawables/DrawableSlider.cs | 5 +-- .../Objects/Drawables/DrawableSpinner.cs | 5 +-- .../Gameplay/TestSceneSkinnableSound.cs | 2 +- .../Objects/Drawables/DrawableHitObject.cs | 9 ++---- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 29 +++++++++++++---- osu.Game/Screens/Play/GameplayClock.cs | 4 ++- .../Screens/Play/ISamplePlaybackDisabler.cs | 20 ++++++++++++ osu.Game/Screens/Play/ISeekableClock.cs | 13 -------- osu.Game/Skinning/SkinnableSound.cs | 32 +++++++++++-------- 10 files changed, 70 insertions(+), 51 deletions(-) create mode 100644 osu.Game/Screens/Play/ISamplePlaybackDisabler.cs delete mode 100644 osu.Game/Screens/Play/ISeekableClock.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 07f40f763b..68f203db47 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -112,10 +112,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private void updateSlidingSample(ValueChangedEvent 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(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index a57bb466c7..b2a706833c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -113,10 +113,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private void updateSpinningSample(ValueChangedEvent 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); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs index ed75d83151..8b37cbd06f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs @@ -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; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 5b26607bf7..796b8f7aae 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -360,7 +360,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } [Resolved(canBeNull: true)] - private ISeekableClock seekableClock { get; set; } + private ISamplePlaybackDisabler samplePlaybackDisabler { get; set; } /// /// 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); } - /// - /// Whether samples should currently be playing. Will be false during seek operations. - /// - protected bool ShouldPlaySamples => seekableClock?.IsSeeking != true; - /// /// Plays all the hit sounds for this . /// This is invoked automatically when this is hit. /// public virtual void PlaySamples() { - if (Samples != null && ShouldPlaySamples) + if (Samples != null) { Samples.Balance.Value = CalculateSamplePlaybackBalance(SamplePlaybackPosition); Samples.Play(); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 1f5e261588..a0692d94e6 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Edit UpdateClockSource(); dependencies.CacheAs(clock); - dependencies.CacheAs(clock); + dependencies.CacheAs(clock); AddInternal(clock); // todo: remove caching of this and consume via editorBeatmap? diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 99e5044b1f..4b7cd82637 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Edit /// /// A decoupled clock which adds editor-specific functionality, such as snapping to a user-defined beat divisor. /// - public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock, ISeekableClock + public class EditorClock : Component, IFrameBasedClock, IAdjustableClock, ISourceChangeableClock, ISamplePlaybackDisabler { public IBindable Track => track; @@ -32,6 +32,10 @@ namespace osu.Game.Screens.Edit private readonly DecoupleableInterpolatingFramedClock underlyingClock; + public IBindable SamplePlaybackDisabled => samplePlaybackDisabled; + + private readonly Bindable samplePlaybackDisabled = new Bindable(); + 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); diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index b10e50882c..da4648fd2b 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Play /// , as this should only be done once to ensure accuracy. /// /// - 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 SamplePlaybackDisabled => IsPaused; } } diff --git a/osu.Game/Screens/Play/ISamplePlaybackDisabler.cs b/osu.Game/Screens/Play/ISamplePlaybackDisabler.cs new file mode 100644 index 0000000000..83e89d654b --- /dev/null +++ b/osu.Game/Screens/Play/ISamplePlaybackDisabler.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . 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 +{ + /// + /// Allows a component to disable sample playback dynamically as required. + /// Handled by . + /// + public interface ISamplePlaybackDisabler + { + /// + /// Whether sample playback should be disabled (or paused for looping samples). + /// + IBindable SamplePlaybackDisabled { get; } + } +} diff --git a/osu.Game/Screens/Play/ISeekableClock.cs b/osu.Game/Screens/Play/ISeekableClock.cs deleted file mode 100644 index 9d992a45fd..0000000000 --- a/osu.Game/Screens/Play/ISeekableClock.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) ppy Pty Ltd . 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 - { - /// - /// Whether an ongoing seek operation is active. - /// - bool IsSeeking { get; } - } -} diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index ba14049b41..704ba099c1 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -50,25 +50,28 @@ namespace osu.Game.Skinning InternalChild = samplesContainer = new AudioContainer(); } - private Bindable gameplayClockPaused; + private readonly IBindable samplePlaybackDisabled = new Bindable(); [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) From c5f6b77bbaa03be219cf5978391852ff5019287a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 13:42:17 +0900 Subject: [PATCH 04/15] Add missing cached type --- osu.Game/Screens/Play/GameplayClockContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 7a9cb3dddd..cc25a733f1 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -51,6 +51,7 @@ namespace osu.Game.Screens.Play /// The final clock which is exposed to underlying components. /// [Cached] + [Cached(typeof(ISamplePlaybackDisabler))] public readonly GameplayClock GameplayClock; private Bindable userAudioOffset; From 74e74e1c31acdd58bfb258ca6a3dc0b291c548e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 14:20:41 +0900 Subject: [PATCH 05/15] Fix pause loop sound not working because paused --- osu.Game/Screens/Play/PauseOverlay.cs | 12 +++++++++++- osu.Game/Skinning/SkinnableSound.cs | 6 ++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index 65f34aba3e..9494971f8a 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 SkinnableSound(new SampleInfo("pause-loop")) + AddInternal(pauseLoop = new UnpausableSkinnableSound(new SampleInfo("pause-loop")) { Looping = true, Volume = { Value = 0 } @@ -54,5 +54,15 @@ 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/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 704ba099c1..f3ab8b86bc 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -37,6 +37,8 @@ namespace osu.Game.Skinning /// protected bool PlayWhenZeroVolume => Looping; + protected virtual bool PlayWhenPaused => false; + private readonly AudioContainer samplesContainer; public SkinnableSound(ISampleInfo hitSamples) @@ -63,7 +65,7 @@ namespace osu.Game.Skinning { if (requestedPlaying) { - if (disabled.NewValue) + 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. @@ -97,7 +99,7 @@ namespace osu.Game.Skinning private void play() { - if (samplePlaybackDisabled.Value) + if (samplePlaybackDisabled.Value && !PlayWhenPaused) return; samplesContainer.ForEach(c => From 53b3d238427d456be3e5acbd79d221b7d1937136 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 17:26:49 +0900 Subject: [PATCH 06/15] Expose HitObjectComposer for other components in the Compose csreen to use --- .../Screens/Edit/Compose/ComposeScreen.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index d7a4661fa0..5282b4d998 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -1,8 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Skinning; @@ -18,11 +22,23 @@ namespace osu.Game.Screens.Edit.Compose { } - protected override Drawable CreateMainContent() + private Ruleset ruleset; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + ruleset = parent.Get>().Value.BeatmapInfo.Ruleset?.CreateInstance(); composer = ruleset?.CreateHitObjectComposer(); + // make the composer available to the timeline and other components in this screen. + dependencies.CacheAs(composer); + + return dependencies; + } + + protected override Drawable CreateMainContent() + { if (ruleset == null || composer == null) return new ScreenWhiteBox.UnderConstructionMessage(ruleset == null ? "This beatmap" : $"{ruleset.Description}'s composer"); From f16fc2907188da26ff64cb7743eb1e0a2319f444 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 16:42:54 +0900 Subject: [PATCH 07/15] Add combo colour display support --- .../Timeline/TimelineHitObjectBlueprint.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index b95b3842b3..7dfaf02af4 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -15,6 +16,7 @@ using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osuTK; using osuTK.Graphics; @@ -34,6 +36,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private readonly List shadowComponents = new List(); + private DrawableHitObject drawableHitObject; + + private Bindable comboColour; + private const float thickness = 5; private const float shadow_radius = 5; @@ -123,6 +129,30 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline updateShadows(); } + [BackgroundDependencyLoader(true)] + private void load(HitObjectComposer composer) + { + if (composer != null) + { + // best effort to get the drawable representation for grabbing colour and what not. + drawableHitObject = composer.HitObjects.FirstOrDefault(d => d.HitObject == HitObject); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (drawableHitObject != null) + { + comboColour = drawableHitObject.AccentColour.GetBoundCopy(); + comboColour.BindValueChanged(colour => + { + Colour = drawableHitObject.AccentColour.Value; + }, true); + } + } + protected override void Update() { base.Update(); From 8d8d45a0c068a9348e1ba37eecdf673900dae70d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 17:04:59 +0900 Subject: [PATCH 08/15] Add combo index display support --- .../Timeline/TimelineHitObjectBlueprint.cs | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 7dfaf02af4..9aa0fee96e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -13,6 +13,8 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; @@ -40,11 +42,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private Bindable comboColour; + private readonly Container mainComponents; + + private readonly OsuSpriteText comboIndexText; + + private Bindable comboIndex; + private const float thickness = 5; private const float shadow_radius = 5; - private const float circle_size = 16; + private const float circle_size = 24; public TimelineHitObjectBlueprint(HitObject hitObject) : base(hitObject) @@ -60,6 +68,23 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + AddRangeInternal(new Drawable[] + { + mainComponents = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + comboIndexText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + Font = OsuFont.Numeric.With(size: circle_size / 2, weight: FontWeight.Black), + }, + }); + circle = new Circle { Size = new Vector2(circle_size), @@ -83,7 +108,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline DragBar dragBarUnderlay; Container extensionBar; - AddRangeInternal(new Drawable[] + mainComponents.AddRange(new Drawable[] { extensionBar = new Container { @@ -123,7 +148,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } else { - AddInternal(circle); + mainComponents.Add(circle); } updateShadows(); @@ -143,12 +168,27 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { base.LoadComplete(); + if (HitObject is IHasComboInformation comboInfo) + { + comboIndex = comboInfo.IndexInCurrentComboBindable.GetBoundCopy(); + comboIndex.BindValueChanged(combo => + { + comboIndexText.Text = (combo.NewValue + 1).ToString(); + }, true); + } + if (drawableHitObject != null) { comboColour = drawableHitObject.AccentColour.GetBoundCopy(); comboColour.BindValueChanged(colour => { - Colour = drawableHitObject.AccentColour.Value; + mainComponents.Colour = drawableHitObject.AccentColour.Value; + + var col = mainComponents.Colour.AverageColour.Linear; + float brightness = col.R + col.G + col.B; + + // decide the combo index colour based on brightness? + comboIndexText.Colour = brightness > 0.5f ? Color4.Black : Color4.White; }, true); } } From c47652c97a22350e3d14269fc4d6936c2856e444 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 17:22:47 +0900 Subject: [PATCH 09/15] Add gradient to hide subtractive colour issues Good thing is looks better than without. --- .../Compose/Components/Timeline/TimelineHitObjectBlueprint.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 9aa0fee96e..11f44c59ac 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -8,6 +8,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Primitives; @@ -182,7 +183,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline comboColour = drawableHitObject.AccentColour.GetBoundCopy(); comboColour.BindValueChanged(colour => { - mainComponents.Colour = drawableHitObject.AccentColour.Value; + mainComponents.Colour = ColourInfo.GradientHorizontal(drawableHitObject.AccentColour.Value, Color4.White); var col = mainComponents.Colour.AverageColour.Linear; float brightness = col.R + col.G + col.B; From 6e1ea004436fcdc09da0b6599d37a75e778b5a18 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 17:34:50 +0900 Subject: [PATCH 10/15] Don't apply gradient to non-duration objects --- .../Components/Timeline/TimelineHitObjectBlueprint.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 11f44c59ac..455f1e17bd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -91,9 +91,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Size = new Vector2(circle_size), Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, - RelativePositionAxes = Axes.X, - AlwaysPresent = true, - Colour = Color4.White, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, @@ -183,7 +180,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline comboColour = drawableHitObject.AccentColour.GetBoundCopy(); comboColour.BindValueChanged(colour => { - mainComponents.Colour = ColourInfo.GradientHorizontal(drawableHitObject.AccentColour.Value, Color4.White); + if (HitObject is IHasDuration) + mainComponents.Colour = ColourInfo.GradientHorizontal(drawableHitObject.AccentColour.Value, Color4.White); + else + mainComponents.Colour = drawableHitObject.AccentColour.Value; var col = mainComponents.Colour.AverageColour.Linear; float brightness = col.R + col.G + col.B; From 414c40d29849932734343123a8b89bf0725381c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 15:45:14 +0900 Subject: [PATCH 11/15] 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 From 6cceb42ad5f21861b839fca68f358183ad1b3da6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 15:50:53 +0900 Subject: [PATCH 12/15] Remove unused DI resolution --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 59a3381b8b..eb12c1cdfc 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -17,7 +17,6 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using osu.Game.Configuration; -using osu.Game.Screens.Play; using osuTK.Graphics; namespace osu.Game.Rulesets.Objects.Drawables @@ -359,9 +358,6 @@ namespace osu.Game.Rulesets.Objects.Drawables { } - [Resolved(canBeNull: true)] - private ISamplePlaybackDisabler samplePlaybackDisabler { get; set; } - /// /// Calculate the position to be used for sample playback at a specified X position (0..1). /// From 3422db1bb291f7daf0b42887edb24a54ac3637b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 17:10:22 +0900 Subject: [PATCH 13/15] Use top-left colour for deciding the text colour (gradient was added in some cases) --- .../Compose/Components/Timeline/TimelineHitObjectBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 455f1e17bd..bc2ccfc605 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -185,7 +185,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline else mainComponents.Colour = drawableHitObject.AccentColour.Value; - var col = mainComponents.Colour.AverageColour.Linear; + var col = mainComponents.Colour.TopLeft.Linear; float brightness = col.R + col.G + col.B; // decide the combo index colour based on brightness? From b0f8e11bd46b54ab14ee678a10b576daa7ed4278 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 17:34:14 +0900 Subject: [PATCH 14/15] Fix incorrect caching --- osu.Game/Screens/Play/GameplayClockContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index e404d7ca42..9f8e55f577 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Play /// public GameplayClock GameplayClock => localGameplayClock; - [Cached] + [Cached(typeof(GameplayClock))] [Cached(typeof(ISamplePlaybackDisabler))] private readonly LocalGameplayClock localGameplayClock; From a11c74d60044d0ba9ee39e7a1e8e91674577b3cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 20:27:02 +0900 Subject: [PATCH 15/15] Update to consume framework fixes --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 4ab27ff1c0..0a0cfe193d 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -76,7 +76,7 @@ namespace osu.Game.Screens.Edit.Timing private OsuButton deleteButton; private ControlPointTable table; - private BindableList controlGroups; + private IBindableList controlGroups; [Resolved] private EditorClock clock { get; set; } @@ -141,8 +141,7 @@ namespace osu.Game.Screens.Edit.Timing selectedGroup.BindValueChanged(selected => { deleteButton.Enabled.Value = selected.NewValue != null; }, true); - // todo: remove cast after https://github.com/ppy/osu-framework/pull/3906 is merged - controlGroups = (BindableList)Beatmap.Value.Beatmap.ControlPointInfo.Groups.GetBoundCopy(); + controlGroups = Beatmap.Value.Beatmap.ControlPointInfo.Groups.GetBoundCopy(); controlGroups.BindCollectionChanged((sender, args) => {