From 0cecb2bba348e9d178704d911339ba6df7a1b26b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Sep 2020 19:33:19 +0900 Subject: [PATCH 01/29] Remove incorrect assumption from tests --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index f7909071ea..9e78185272 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -7,7 +7,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; using osu.Framework.Timing; @@ -194,13 +193,7 @@ namespace osu.Game.Rulesets.Osu.Tests addSeekStep(0); - AddStep("adjust track rate", () => MusicController.CurrentTrack.AddAdjustment(AdjustableProperty.Tempo, new BindableDouble(rate))); - // autoplay replay frames use track time; - // if a spin takes 1000ms in track time and we're playing with a 2x rate adjustment, the spin will take 500ms of *real* time. - // therefore we need to apply the rate adjustment to the replay itself to change from track time to real time, - // as real time is what we care about for spinners - // (so we're making the spin take 1000ms in real time *always*, regardless of the track clock's rate). - transformReplay(replay => applyRateAdjustment(replay, rate)); + AddStep("adjust track rate", () => Player.GameplayClockContainer.UserPlaybackRate.Value = rate); addSeekStep(1000); AddAssert("progress almost same", () => Precision.AlmostEquals(expectedProgress, drawableSpinner.Progress, 0.05)); From 3f788da06d0aa4379f8133ce319dcde18cabe1fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Sep 2020 19:39:54 +0900 Subject: [PATCH 02/29] Fix SPM changing incorrectly with playback rate changes --- .../Pieces/SpinnerRotationTracker.cs | 7 +++- .../Rulesets/UI/FrameStabilityContainer.cs | 8 +++- osu.Game/Screens/Play/GameplayClock.cs | 24 +++++++++++ .../Screens/Play/GameplayClockContainer.cs | 42 +++++++++++++++++-- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs index f1a782cbb5..e949017ccf 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs @@ -2,11 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Utils; +using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces @@ -77,6 +79,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private bool rotationTransferred; + [Resolved] + private GameplayClock gameplayClock { get; set; } + protected override void Update() { base.Update(); @@ -126,7 +131,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces currentRotation += angle; // rate has to be applied each frame, because it's not guaranteed to be constant throughout playback // (see: ModTimeRamp) - RateAdjustedRotation += (float)(Math.Abs(angle) * Clock.Rate); + RateAdjustedRotation += (float)(Math.Abs(angle) * gameplayClock.TrueGameplayRate); } } } diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index d574991fa0..b585a78f42 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; @@ -59,7 +61,7 @@ namespace osu.Game.Rulesets.UI { if (clock != null) { - stabilityGameplayClock.ParentGameplayClock = parentGameplayClock = clock; + parentGameplayClock = stabilityGameplayClock.ParentGameplayClock = clock; GameplayClock.IsPaused.BindTo(clock.IsPaused); } } @@ -191,7 +193,9 @@ namespace osu.Game.Rulesets.UI private class StabilityGameplayClock : GameplayClock { - public IFrameBasedClock ParentGameplayClock; + public GameplayClock ParentGameplayClock; + + public override IEnumerable> NonGameplayAdjustments => ParentGameplayClock.NonGameplayAdjustments; public StabilityGameplayClock(FramedClock underlyingClock) : base(underlyingClock) diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index 4f2cf5005c..45da8816d6 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -1,6 +1,8 @@ // 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 System.Linq; using osu.Framework.Bindables; using osu.Framework.Timing; @@ -20,6 +22,11 @@ namespace osu.Game.Screens.Play public readonly BindableBool IsPaused = new BindableBool(); + /// + /// All adjustments applied to this clock which don't come from gameplay or mods. + /// + public virtual IEnumerable> NonGameplayAdjustments => Enumerable.Empty>(); + public GameplayClock(IFrameBasedClock underlyingClock) { this.underlyingClock = underlyingClock; @@ -29,6 +36,23 @@ namespace osu.Game.Screens.Play public double Rate => underlyingClock.Rate; + /// + /// The rate of gameplay when playback is at 100%. + /// This excludes any seeking / user adjustments. + /// + public double TrueGameplayRate + { + get + { + double baseRate = Rate; + + foreach (var adjustment in NonGameplayAdjustments) + baseRate /= adjustment.Value; + + return baseRate; + } + } + public bool IsRunning => underlyingClock.IsRunning; /// diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 7a9cb3dddd..d5c3a7232f 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; @@ -50,8 +51,10 @@ namespace osu.Game.Screens.Play /// /// The final clock which is exposed to underlying components. /// - [Cached] - public readonly GameplayClock GameplayClock; + public GameplayClock GameplayClock => localGameplayClock; + + [Cached(typeof(GameplayClock))] + private readonly LocalGameplayClock localGameplayClock; private Bindable userAudioOffset; @@ -79,7 +82,7 @@ namespace osu.Game.Screens.Play userOffsetClock = new HardwareCorrectionOffsetClock(platformOffsetClock); // the clock to be exposed via DI to children. - GameplayClock = new GameplayClock(userOffsetClock); + localGameplayClock = new LocalGameplayClock(userOffsetClock); GameplayClock.IsPaused.BindTo(IsPaused); } @@ -200,11 +203,26 @@ namespace osu.Game.Screens.Play protected override void Update() { if (!IsPaused.Value) + { userOffsetClock.ProcessFrame(); + } base.Update(); } + private double getTrueGameplayRate() + { + double baseRate = track.Rate; + + if (speedAdjustmentsApplied) + { + baseRate /= UserPlaybackRate.Value; + baseRate /= pauseFreqAdjust.Value; + } + + return baseRate; + } + private bool speedAdjustmentsApplied; private void updateRate() @@ -215,6 +233,9 @@ namespace osu.Game.Screens.Play track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); + localGameplayClock.MutableNonGameplayAdjustments.Add(pauseFreqAdjust); + localGameplayClock.MutableNonGameplayAdjustments.Add(UserPlaybackRate); + speedAdjustmentsApplied = true; } @@ -231,9 +252,24 @@ namespace osu.Game.Screens.Play track.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); track.RemoveAdjustment(AdjustableProperty.Tempo, UserPlaybackRate); + localGameplayClock.MutableNonGameplayAdjustments.Remove(pauseFreqAdjust); + localGameplayClock.MutableNonGameplayAdjustments.Remove(UserPlaybackRate); + speedAdjustmentsApplied = false; } + public class LocalGameplayClock : GameplayClock + { + public readonly List> MutableNonGameplayAdjustments = new List>(); + + public override IEnumerable> NonGameplayAdjustments => MutableNonGameplayAdjustments; + + public LocalGameplayClock(FramedOffsetClock underlyingClock) + : base(underlyingClock) + { + } + } + private class HardwareCorrectionOffsetClock : FramedOffsetClock { // we always want to apply the same real-time offset, so it should be adjusted by the difference in playback rate (from realtime) to achieve this. From 508278505f71a7b72531787364f8ece28f07f9d7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Sep 2020 19:40:57 +0900 Subject: [PATCH 03/29] Make local clock private --- 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 d5c3a7232f..4094de1c4f 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -258,7 +258,7 @@ namespace osu.Game.Screens.Play speedAdjustmentsApplied = false; } - public class LocalGameplayClock : GameplayClock + private class LocalGameplayClock : GameplayClock { public readonly List> MutableNonGameplayAdjustments = new List>(); From 25bf160d942d8c1bdb6dac7951073a145fe57656 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Sep 2020 22:30:14 +0900 Subject: [PATCH 04/29] Fix missing GameplayClock in some tests --- .../Objects/Drawables/Pieces/SpinnerRotationTracker.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs index e949017ccf..05ed38d241 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerRotationTracker.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private bool rotationTransferred; - [Resolved] + [Resolved(canBeNull: true)] private GameplayClock gameplayClock { get; set; } protected override void Update() @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces currentRotation += angle; // rate has to be applied each frame, because it's not guaranteed to be constant throughout playback // (see: ModTimeRamp) - RateAdjustedRotation += (float)(Math.Abs(angle) * gameplayClock.TrueGameplayRate); + RateAdjustedRotation += (float)(Math.Abs(angle) * (gameplayClock?.TrueGameplayRate ?? Clock.Rate)); } } } From 892d440ed0f337ac47ed192f6db3fdebfbfa5b19 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Sep 2020 13:19:07 +0900 Subject: [PATCH 05/29] Add fallback path for potential null ParentGameplayClock --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index b585a78f42..6716f828ed 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -195,7 +196,7 @@ namespace osu.Game.Rulesets.UI { public GameplayClock ParentGameplayClock; - public override IEnumerable> NonGameplayAdjustments => ParentGameplayClock.NonGameplayAdjustments; + public override IEnumerable> NonGameplayAdjustments => ParentGameplayClock?.NonGameplayAdjustments ?? Enumerable.Empty>(); public StabilityGameplayClock(FramedClock underlyingClock) : base(underlyingClock) From 26ba7d3100ff77a91cf01ae4737f3c014b7fe5ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Sep 2020 13:20:19 +0900 Subject: [PATCH 06/29] Remove unused method (was moved to a more local location) --- osu.Game/Screens/Play/GameplayClockContainer.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 4094de1c4f..6679e56871 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -210,19 +210,6 @@ namespace osu.Game.Screens.Play base.Update(); } - private double getTrueGameplayRate() - { - double baseRate = track.Rate; - - if (speedAdjustmentsApplied) - { - baseRate /= UserPlaybackRate.Value; - baseRate /= pauseFreqAdjust.Value; - } - - return baseRate; - } - private bool speedAdjustmentsApplied; private void updateRate() From 8692c24dfc624f739d10209cafa173b125ff024d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Sep 2020 17:20:36 +0900 Subject: [PATCH 07/29] Fix extending spinners in editor causing them to disappear temporarily --- .../Objects/Drawables/Pieces/DefaultSpinnerDisc.cs | 9 ++++----- osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs | 5 ++--- osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs | 5 ++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs index 1476fe6010..e45ea9c6cc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -93,7 +92,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces base.LoadComplete(); drawableSpinner.RotationTracker.Complete.BindValueChanged(complete => updateComplete(complete.NewValue, 200)); - drawableSpinner.State.BindValueChanged(updateStateTransforms, true); + drawableSpinner.ApplyCustomUpdateState += updateStateTransforms; } protected override void Update() @@ -123,7 +122,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces mainContainer.Rotation = drawableSpinner.RotationTracker.Rotation; } - private void updateStateTransforms(ValueChangedEvent state) + private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state) { centre.ScaleTo(0); mainContainer.ScaleTo(0); @@ -144,11 +143,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } // transforms we have from completing the spinner will be rolled back, so reapply immediately. - updateComplete(state.NewValue == ArmedState.Hit, 0); + updateComplete(state == ArmedState.Hit, 0); using (BeginDelayedSequence(spinner.Duration, true)) { - switch (state.NewValue) + switch (state) { case ArmedState.Hit: this.ScaleTo(Scale * 1.2f, 320, Easing.Out); diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs index 739c87e037..734c66ce7d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs @@ -2,7 +2,6 @@ // 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.Framework.Graphics.Sprites; @@ -72,10 +71,10 @@ namespace osu.Game.Rulesets.Osu.Skinning base.LoadComplete(); this.FadeOut(); - drawableSpinner.State.BindValueChanged(updateStateTransforms, true); + drawableSpinner.ApplyCustomUpdateState += updateStateTransforms; } - private void updateStateTransforms(ValueChangedEvent state) + private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state) { var spinner = (Spinner)drawableSpinner.HitObject; diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs index e157842fd1..09f8894d53 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -86,10 +85,10 @@ namespace osu.Game.Rulesets.Osu.Skinning base.LoadComplete(); this.FadeOut(); - drawableSpinner.State.BindValueChanged(updateStateTransforms, true); + drawableSpinner.ApplyCustomUpdateState += updateStateTransforms; } - private void updateStateTransforms(ValueChangedEvent state) + private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state) { var spinner = drawableSpinner.HitObject; From 63b5b8b84187251bb51e72da4e295d00b7a8226d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Sep 2020 17:32:57 +0900 Subject: [PATCH 08/29] Fix sliders not dragging correctly after snaking has begun Closes #10278. --- .../Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs | 5 +++++ .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index 78f4c4d992..9349ef7a18 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -15,6 +15,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { private readonly ManualSliderBody body; + /// + /// Offset in absolute (local) coordinates from the start of the curve. + /// + public Vector2 PathStartLocation => body.PathOffset; + public SliderBodyPiece() { InternalChild = body = new ManualSliderBody diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 6633136673..94862eb205 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -190,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)), }; - public override Vector2 ScreenSpaceSelectionPoint => ((DrawableSlider)DrawableObject).HeadCircle.ScreenSpaceDrawQuad.Centre; + public override Vector2 ScreenSpaceSelectionPoint => BodyPiece.ToScreenSpace(BodyPiece.PathStartLocation); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BodyPiece.ReceivePositionalInputAt(screenSpacePos); From e60e47ff66b623c230cdfe832bc4b12d2688e479 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Sep 2020 17:41:10 +0900 Subject: [PATCH 09/29] Unbind events on disposal --- .../Objects/Drawables/Pieces/DefaultSpinnerDisc.cs | 6 ++++++ osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs | 6 ++++++ osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs index e45ea9c6cc..51d67c7f67 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs @@ -184,5 +184,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return true; } } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; + } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs index 734c66ce7d..8baa6a3dd3 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs @@ -94,5 +94,11 @@ namespace osu.Game.Rulesets.Osu.Skinning Scale = new Vector2(final_scale * (0.8f + (float)Interpolation.ApplyEasing(Easing.Out, drawableSpinner.Progress) * 0.2f)); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; + } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs index 09f8894d53..a895298ec3 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs @@ -126,5 +126,11 @@ namespace osu.Game.Rulesets.Osu.Skinning return (float)barCount / total_bars * final_metre_height; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; + } } } From b6bc829bd5a8ea160a26fd66f7f18362395d9bb5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 28 Sep 2020 17:46:22 +0900 Subject: [PATCH 10/29] Guard against nulls (load not run) --- .../Objects/Drawables/Pieces/DefaultSpinnerDisc.cs | 4 +++- osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs | 4 +++- osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs index 51d67c7f67..2862fe49bd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultSpinnerDisc.cs @@ -188,7 +188,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; + + if (drawableSpinner != null) + drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs index 8baa6a3dd3..bcb2af8e3e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyNewStyleSpinner.cs @@ -98,7 +98,9 @@ namespace osu.Game.Rulesets.Osu.Skinning protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; + + if (drawableSpinner != null) + drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs index a895298ec3..a45d91801d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyOldStyleSpinner.cs @@ -130,7 +130,9 @@ namespace osu.Game.Rulesets.Osu.Skinning protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; + + if (drawableSpinner != null) + drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; } } } From 53b3d238427d456be3e5acbd79d221b7d1937136 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Sep 2020 17:26:49 +0900 Subject: [PATCH 11/29] 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 12/29] 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 13/29] 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 14/29] 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 15/29] 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 1386c9fe668e13c89259c44d92e704503eff0e64 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 12:45:43 +0900 Subject: [PATCH 16/29] Standardise time display formats across the editor --- .../Extensions/EditorDisplayExtensions.cs | 26 +++++++++++++++++++ .../Edit/Components/TimeInfoContainer.cs | 6 ++--- .../Screens/Edit/Timing/ControlPointTable.cs | 3 ++- 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Extensions/EditorDisplayExtensions.cs diff --git a/osu.Game/Extensions/EditorDisplayExtensions.cs b/osu.Game/Extensions/EditorDisplayExtensions.cs new file mode 100644 index 0000000000..f749b88b46 --- /dev/null +++ b/osu.Game/Extensions/EditorDisplayExtensions.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Extensions +{ + public static class EditorDisplayExtensions + { + /// + /// Get an editor formatted string (mm:ss:mss) + /// + /// A time value in milliseconds. + /// An editor formatted display string. + public static string ToEditorFormattedString(this double milliseconds) => + ToEditorFormattedString(TimeSpan.FromMilliseconds(milliseconds)); + + /// + /// Get an editor formatted string (mm:ss:mss) + /// + /// A time value. + /// An editor formatted display string. + public static string ToEditorFormattedString(this TimeSpan timeSpan) => + $"{(timeSpan < TimeSpan.Zero ? "-" : string.Empty)}{timeSpan:mm\\:ss\\:fff}"; + } +} diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index c68eeeb4f9..0a8c339559 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -3,8 +3,8 @@ using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; -using System; using osu.Framework.Allocation; +using osu.Game.Extensions; using osu.Game.Graphics; namespace osu.Game.Screens.Edit.Components @@ -35,9 +35,7 @@ namespace osu.Game.Screens.Edit.Components protected override void Update() { base.Update(); - - var timespan = TimeSpan.FromMilliseconds(editorClock.CurrentTime); - trackTimer.Text = $"{(timespan < TimeSpan.Zero ? "-" : string.Empty)}{timespan:mm\\:ss\\:fff}"; + trackTimer.Text = editorClock.CurrentTime.ToEditorFormattedString(); } } } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index c0c0bcead2..87af4546f1 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -89,7 +90,7 @@ namespace osu.Game.Screens.Edit.Timing }, new OsuSpriteText { - Text = $"{group.Time:n0}ms", + Text = group.Time.ToEditorFormattedString(), Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, new ControlGroupAttributes(group), From 414c40d29849932734343123a8b89bf0725381c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 15:45:14 +0900 Subject: [PATCH 17/29] 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 18/29] 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 a40c2ea5ee54863c0991c5be9fdcfc5fa76cbc03 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 16:02:22 +0900 Subject: [PATCH 19/29] Simplify control point group binding/update logic --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index d7da29218f..1d550b7cc3 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Edit.Timing private OsuButton deleteButton; private ControlPointTable table; - private IBindableList controlGroups; + private BindableList controlGroups; [Resolved] private EditorClock clock { get; set; } @@ -128,12 +128,14 @@ namespace osu.Game.Screens.Edit.Timing selectedGroup.BindValueChanged(selected => { deleteButton.Enabled.Value = selected.NewValue != null; }, true); - controlGroups = Beatmap.Value.Beatmap.ControlPointInfo.Groups.GetBoundCopy(); - controlGroups.CollectionChanged += (sender, args) => createContent(); - createContent(); - } + // todo: remove cast after https://github.com/ppy/osu-framework/pull/3906 is merged + controlGroups = (BindableList)Beatmap.Value.Beatmap.ControlPointInfo.Groups.GetBoundCopy(); - private void createContent() => table.ControlGroups = controlGroups; + controlGroups.BindCollectionChanged((sender, args) => + { + table.ControlGroups = controlGroups; + }, true); + } private void delete() { From 2ef09a8730085609f3ecb5eeba827e5a15554f60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 16:06:58 +0900 Subject: [PATCH 20/29] Populate test scene with control points --- osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs index 09f5ac2224..cda4ade6e1 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Timing; @@ -19,7 +20,7 @@ namespace osu.Game.Tests.Visual.Editing public TestSceneTimingScreen() { - editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + editorBeatmap = new EditorBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); } [BackgroundDependencyLoader] From 1dd354120b1013759d210e49902e08393c6d18b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 16:16:14 +0900 Subject: [PATCH 21/29] Fix beatmap potentially changing in test scene --- osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs index cda4ade6e1..04cdfd7a67 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs @@ -5,7 +5,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu; -using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Timing; @@ -27,7 +26,15 @@ namespace osu.Game.Tests.Visual.Editing private void load() { Beatmap.Value = CreateWorkingBeatmap(editorBeatmap.PlayableBeatmap); + Beatmap.Disabled = true; + Child = new TimingScreen(); } + + protected override void Dispose(bool isDisposing) + { + Beatmap.Disabled = false; + base.Dispose(isDisposing); + } } } From e760ed8e01921c42c6adc6e8039b475f0b5758b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 16:39:02 +0900 Subject: [PATCH 22/29] Fix scroll wheel being handled by base test scene --- osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs | 2 ++ osu.Game/Tests/Visual/EditorClockTestScene.cs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs index 04cdfd7a67..b82e776164 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs @@ -17,6 +17,8 @@ namespace osu.Game.Tests.Visual.Editing [Cached(typeof(IBeatSnapProvider))] private readonly EditorBeatmap editorBeatmap; + protected override bool ScrollUsingMouseWheel => false; + public TestSceneTimingScreen() { editorBeatmap = new EditorBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index f0ec638fc9..693c9cb792 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -20,6 +20,8 @@ namespace osu.Game.Tests.Visual protected readonly BindableBeatDivisor BeatDivisor = new BindableBeatDivisor(); protected new readonly EditorClock Clock; + protected virtual bool ScrollUsingMouseWheel => true; + protected EditorClockTestScene() { Clock = new EditorClock(new ControlPointInfo(), 5000, BeatDivisor) { IsCoupled = false }; @@ -57,6 +59,9 @@ namespace osu.Game.Tests.Visual protected override bool OnScroll(ScrollEvent e) { + if (!ScrollUsingMouseWheel) + return false; + if (e.ScrollDelta.Y > 0) Clock.SeekBackward(true); else From 5b200a8ca41f44084a3c0cc3703b50042a76a3bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 16:39:27 +0900 Subject: [PATCH 23/29] Change default zoom of timing screen timeline to most zoomed out --- .../Edit/Compose/Components/Timeline/TimelineArea.cs | 10 +++++----- osu.Game/Screens/Edit/EditorScreenWithTimeline.cs | 10 +++++++++- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 7 +++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index b99a053859..d870eb5279 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -14,9 +14,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public class TimelineArea : Container { - private readonly Timeline timeline = new Timeline { RelativeSizeAxes = Axes.Both }; + public readonly Timeline Timeline = new Timeline { RelativeSizeAxes = Axes.Both }; - protected override Container Content => timeline; + protected override Container Content => Timeline; [BackgroundDependencyLoader] private void load() @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } }, - timeline + Timeline }, }, ColumnDimensions = new[] @@ -121,9 +121,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline waveformCheckbox.Current.Value = true; - timeline.WaveformVisible.BindTo(waveformCheckbox.Current); + Timeline.WaveformVisible.BindTo(waveformCheckbox.Current); } - private void changeZoom(float change) => timeline.Zoom += change; + private void changeZoom(float change) => Timeline.Zoom += change; } } diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 34eddbefad..d6d782e70c 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -115,10 +115,18 @@ namespace osu.Game.Screens.Edit new TimelineTickDisplay(), CreateTimelineContent(), } - }, timelineContainer.Add); + }, t => + { + timelineContainer.Add(t); + OnTimelineLoaded(t); + }); }); } + protected virtual void OnTimelineLoaded(TimelineArea timelineArea) + { + } + protected abstract Drawable CreateMainContent(); protected virtual Drawable CreateTimelineContent() => new Container(); diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 1d550b7cc3..66c1f4895b 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -12,6 +12,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; namespace osu.Game.Screens.Edit.Timing @@ -58,6 +59,12 @@ namespace osu.Game.Screens.Edit.Timing }); } + protected override void OnTimelineLoaded(TimelineArea timelineArea) + { + base.OnTimelineLoaded(timelineArea); + timelineArea.Timeline.Zoom = timelineArea.Timeline.MinZoom; + } + public class ControlPointList : CompositeDrawable { private OsuButton deleteButton; From 698042268ff4463a4b18544b68e3dea806c6524a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 16:58:19 +0900 Subject: [PATCH 24/29] Show control points in timing screen timeline --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 66c1f4895b..4ab27ff1c0 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -12,6 +12,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; @@ -30,6 +31,11 @@ namespace osu.Game.Screens.Edit.Timing { } + protected override Drawable CreateTimelineContent() => new ControlPointPart + { + RelativeSizeAxes = Axes.Both, + }; + protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, From 3422db1bb291f7daf0b42887edb24a54ac3637b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 17:10:22 +0900 Subject: [PATCH 25/29] 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 26/29] 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 44fc0c672304486c7706334ab990802f03aaa793 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 18:08:55 +0900 Subject: [PATCH 27/29] Fix default value of bpm being too high --- osu.Game/Screens/Edit/Timing/TimingSection.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 879363ba08..cc79dd2acc 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -103,12 +103,17 @@ namespace osu.Game.Screens.Edit.Timing private const double sane_maximum = 240; private readonly BindableNumber beatLengthBindable = new TimingControlPoint().BeatLengthBindable; - private readonly BindableDouble bpmBindable = new BindableDouble(); + + private readonly BindableDouble bpmBindable = new BindableDouble(60000 / TimingControlPoint.DEFAULT_BEAT_LENGTH) + { + MinValue = sane_minimum, + MaxValue = sane_maximum, + }; public BPMSlider() { beatLengthBindable.BindValueChanged(beatLength => updateCurrent(beatLengthToBpm(beatLength.NewValue)), true); - bpmBindable.BindValueChanged(bpm => bpmBindable.Default = beatLengthBindable.Value = beatLengthToBpm(bpm.NewValue)); + bpmBindable.BindValueChanged(bpm => beatLengthBindable.Value = beatLengthToBpm(bpm.NewValue)); base.Bindable = bpmBindable; } From fab11a8241e470cd428d33a9084e0c927242c542 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 18:36:40 +0900 Subject: [PATCH 28/29] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index dc3e14c141..afc5d4ec52 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6412f707d0..5fa1685d9b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index f1e13169a5..60708a39e2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -80,7 +80,7 @@ - + From a11c74d60044d0ba9ee39e7a1e8e91674577b3cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Sep 2020 20:27:02 +0900 Subject: [PATCH 29/29] 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) => {