From 16d34bcc0a04b319a53d86f20a863a837eb8d73d Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Mon, 12 Apr 2021 16:02:19 -0400 Subject: [PATCH 001/134] Expose the latest end time of storyboard elements Co-authored-by: Marlina Bowring --- osu.Game/Storyboards/IStoryboardElement.cs | 2 ++ osu.Game/Storyboards/Storyboard.cs | 9 +++++++++ osu.Game/Storyboards/StoryboardSample.cs | 2 ++ osu.Game/Storyboards/StoryboardVideo.cs | 2 ++ 4 files changed, 15 insertions(+) diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index c4c150a8a4..03f8b97212 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -12,6 +12,8 @@ namespace osu.Game.Storyboards double StartTime { get; } + double EndTime { get; } + Drawable CreateDrawable(); } } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 1ba25cc11e..41058d9cb3 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -36,6 +36,15 @@ namespace osu.Game.Storyboards /// public double? EarliestEventTime => Layers.SelectMany(l => l.Elements).OrderBy(e => e.StartTime).FirstOrDefault()?.StartTime; + /// + /// Across all layers, find the latest point in time that a storyboard element ends at. + /// Will return null if there are no elements. + /// + /// + /// This iterates all elements and as such should be used sparingly or stored locally. + /// Videos and samples return StartTime as their EndTIme. + /// + public double? LatestEventTime => Layers.SelectMany(l => l.Elements).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; /// /// Depth of the currently front-most storyboard layer, excluding the overlay layer. /// diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index 5d6ce215f5..d0949c93a7 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -15,6 +15,8 @@ namespace osu.Game.Storyboards public double StartTime { get; } + public double EndTime => StartTime; + public int Volume { get; } public IEnumerable LookupNames => new[] diff --git a/osu.Game/Storyboards/StoryboardVideo.cs b/osu.Game/Storyboards/StoryboardVideo.cs index 4652e45852..1314bd7cb9 100644 --- a/osu.Game/Storyboards/StoryboardVideo.cs +++ b/osu.Game/Storyboards/StoryboardVideo.cs @@ -14,6 +14,8 @@ namespace osu.Game.Storyboards public double StartTime { get; } + public double EndTime => StartTime; + public StoryboardVideo(string path, int offset) { Path = path; From 25b8c2f257f8a52aba5761b819ea0ee7f62b86a4 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Wed, 14 Apr 2021 00:04:03 -0400 Subject: [PATCH 002/134] Allow skipping storyboard outro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reuses SkipOverlay by calculating the endtime of the storyboard and using that as a "start point". Upon skipping the outro the score is instantly shown. When the end of the storyboard is reached the score screen automatically shows up. If the player holds ESC (pause) during the outro, the score is displayed The storyboard endtime is calculated by getting the latest endtime of the storyboard's elements, or simply returning 0 if there is no storyboard. Co-Authored-By: Marlina José --- .../Gameplay/TestSceneStoryboardWithOutro.cs | 100 ++++++++++++++++++ .../Multiplayer/MultiplayerPlayer.cs | 1 + .../Screens/Play/GameplayClockContainer.cs | 25 +++++ osu.Game/Screens/Play/Player.cs | 34 ++++++ osu.Game/Screens/Play/PlayerConfiguration.cs | 5 + osu.Game/Storyboards/Storyboard.cs | 1 + 6 files changed, 166 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs new file mode 100644 index 0000000000..1c8b33bb09 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -0,0 +1,100 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading.Tasks; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Scoring; +using osu.Game.Screens.Ranking; +using osu.Game.Storyboards; +using osuTK; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneStoryboardWithOutro : PlayerTestScene + { + protected new OutroPlayer Player => (OutroPlayer)base.Player; + + private Storyboard storyboard; + + private const double storyboard_duration = 2000; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.SetValue(OsuSetting.ShowStoryboard, true); + storyboard = new Storyboard(); + var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero); + sprite.TimelineGroup.Alpha.Add(Easing.None, 0, storyboard_duration, 1, 0); + storyboard.GetLayer("Background").Add(sprite); + } + + [Test] + public void TestStoryboardSkipOutro() + { + AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); + AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + AddStep("skip outro", () => InputManager.Key(osuTK.Input.Key.Space)); + AddAssert("score shown", () => Player.IsScoreShown); + } + + [Test] + public void TestStoryboardNoSkipOutro() + { + AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); + AddUntilStep("storyboard ends", () => Player.HUDOverlay.Progress.ReferenceClock.CurrentTime >= storyboard_duration); + AddWaitStep("wait for score", 10); + AddAssert("score shown", () => Player.IsScoreShown); + } + + [Test] + public void TestStoryboardExitToSkipOutro() + { + AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); + AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + AddStep("exit via pause", () => Player.ExitViaPause()); + AddAssert("score shown", () => Player.IsScoreShown); + } + + protected override bool AllowFail => false; + + protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); + + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new OutroPlayer(); + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) + { + var beatmap = new Beatmap(); + beatmap.HitObjects.Add(new HitCircle()); + return beatmap; + } + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => + new ClockBackedTestWorkingBeatmap(beatmap, storyboard ?? this.storyboard, Clock, Audio); + + protected class OutroPlayer : TestPlayer + { + public void ExitViaPause() => PerformExit(true); + + public bool IsScoreShown => !this.IsCurrentScreen() && this.GetChildScreen() is ResultsScreen; + + public OutroPlayer() + : base(false) + { + } + + protected override Task ImportScore(Score score) + { + // avoid database errors from trying to store the score + return Task.CompletedTask; + } + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index aaacf891bb..b4e8c13e83 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -49,6 +49,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer AllowPause = false, AllowRestart = false, AllowSkippingIntro = false, + AllowSkippingOutro = false, }) { this.userIds = userIds; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index ddbb087962..fc45d661cf 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -228,6 +228,11 @@ namespace osu.Game.Screens.Play adjustableClock.ChangeSource(track); } + /// + /// Gets the endtime of the last element in the storyboard in ms, or start time of the last hitobject if there's no storyboard. + /// + public double StoryboardEndTime => beatmap.Storyboard.LatestEventTime ?? 0; + protected override void Update() { if (!IsPaused.Value) @@ -235,6 +240,8 @@ namespace osu.Game.Screens.Play userOffsetClock.ProcessFrame(); } + updateHasStoryboardEnded(); + base.Update(); } @@ -296,5 +303,23 @@ namespace osu.Game.Screens.Play { } } + + # region Storyboard outro logic + + public IBindable HasStoryboardEnded => hasStoryboardEnded; + + public bool HasTimeLeftInStoryboard => GameplayClock.CurrentTime <= StoryboardEndTime; + + private readonly BindableBool hasStoryboardEnded = new BindableBool(true); + + private void updateHasStoryboardEnded() + { + if (StoryboardEndTime == 0) + return; + + hasStoryboardEnded.Value = GameplayClock.CurrentTime >= StoryboardEndTime; + } + + # endregion } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index efe5d26409..13820738c7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -74,6 +74,8 @@ namespace osu.Game.Screens.Play private Bindable mouseWheelDisabled; + private Bindable storyboardEnabled; + private readonly Bindable storyboardReplacesBackground = new Bindable(); protected readonly Bindable LocalUserPlaying = new Bindable(); @@ -106,6 +108,8 @@ namespace osu.Game.Screens.Play private SkipOverlay skipOverlay; + private SkipOverlay skipOutroOverlay; + protected ScoreProcessor ScoreProcessor { get; private set; } protected HealthProcessor HealthProcessor { get; private set; } @@ -190,6 +194,8 @@ namespace osu.Game.Screens.Play mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); + storyboardEnabled = config.GetBindable(OsuSetting.ShowStoryboard); + if (game != null) gameActive.BindTo(game.IsActive); @@ -285,6 +291,9 @@ namespace osu.Game.Screens.Play ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState; HealthProcessor.Failed += onFail; + // Keep track of whether the storyboard ended after the playable portion + GameplayClockContainer.HasStoryboardEnded.ValueChanged += updateCompletionState; + foreach (var mod in Mods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); @@ -360,6 +369,10 @@ namespace osu.Game.Screens.Play { RequestSkip = performUserRequestedSkip }, + skipOutroOverlay = new SkipOverlay(GameplayClockContainer.StoryboardEndTime) + { + RequestSkip = scheduleCompletion + }, FailOverlay = new FailOverlay { OnRetry = Restart, @@ -389,6 +402,9 @@ namespace osu.Game.Screens.Play if (!Configuration.AllowSkippingIntro) skipOverlay.Expire(); + if (!Configuration.AllowSkippingOutro) + skipOutroOverlay.Expire(); + if (Configuration.AllowRestart) { container.Add(new HotkeyRetryOverlay @@ -403,6 +419,8 @@ namespace osu.Game.Screens.Play }); } + skipOutroOverlay.Hide(); + return container; } @@ -523,6 +541,14 @@ namespace osu.Game.Screens.Play Pause(); return; } + + // show the score if in storyboard outro (score has been set) + bool scoreReady = prepareScoreForDisplayTask != null && prepareScoreForDisplayTask.IsCompleted; + + if (scoreReady) + { + scheduleCompletion(); + } } this.Exit(); @@ -611,6 +637,14 @@ namespace osu.Game.Screens.Play return score.ScoreInfo; }); + // show skip overlay if storyboard is enabled and has an outro + if (storyboardEnabled.Value && GameplayClockContainer.HasTimeLeftInStoryboard) + { + skipOutroOverlay.Show(); + completionProgressDelegate = null; + return; + } + using (BeginDelayedSequence(RESULTS_DISPLAY_DELAY)) scheduleCompletion(); } diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index cd30ead638..ad29563d54 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -24,5 +24,10 @@ namespace osu.Game.Screens.Play /// Whether the player should be allowed to skip the intro, advancing to the start of gameplay. /// public bool AllowSkippingIntro { get; set; } = true; + + /// + /// Whether the player should be allowed to skip the outro, advancing to the end of a storyboard. + /// + public bool AllowSkippingOutro { get; set; } = true; } } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 41058d9cb3..e22c586048 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -45,6 +45,7 @@ namespace osu.Game.Storyboards /// Videos and samples return StartTime as their EndTIme. /// public double? LatestEventTime => Layers.SelectMany(l => l.Elements).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; + /// /// Depth of the currently front-most storyboard layer, excluding the overlay layer. /// From 0e545e1ed9df1d33e0d6506a9edc3a053d6aeb7a Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Thu, 15 Apr 2021 17:17:02 -0400 Subject: [PATCH 003/134] Add IHasDuration interface with EndTime for storyboard elements to implement --- osu.Game/Storyboards/IHasDuration.cs | 10 ++++++++++ osu.Game/Storyboards/IStoryboardElement.cs | 2 -- osu.Game/Storyboards/Storyboard.cs | 6 +----- osu.Game/Storyboards/StoryboardSample.cs | 2 -- osu.Game/Storyboards/StoryboardSprite.cs | 2 +- osu.Game/Storyboards/StoryboardVideo.cs | 2 -- 6 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 osu.Game/Storyboards/IHasDuration.cs diff --git a/osu.Game/Storyboards/IHasDuration.cs b/osu.Game/Storyboards/IHasDuration.cs new file mode 100644 index 0000000000..98f75b8ee2 --- /dev/null +++ b/osu.Game/Storyboards/IHasDuration.cs @@ -0,0 +1,10 @@ +// 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.Storyboards +{ + public interface IHasDuration + { + double EndTime { get; } + } +} diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index 03f8b97212..c4c150a8a4 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -12,8 +12,6 @@ namespace osu.Game.Storyboards double StartTime { get; } - double EndTime { get; } - Drawable CreateDrawable(); } } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index e22c586048..669f6ccc43 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -40,11 +40,7 @@ namespace osu.Game.Storyboards /// Across all layers, find the latest point in time that a storyboard element ends at. /// Will return null if there are no elements. /// - /// - /// This iterates all elements and as such should be used sparingly or stored locally. - /// Videos and samples return StartTime as their EndTIme. - /// - public double? LatestEventTime => Layers.SelectMany(l => l.Elements).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; + public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; /// /// Depth of the currently front-most storyboard layer, excluding the overlay layer. diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index d0949c93a7..5d6ce215f5 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -15,8 +15,6 @@ namespace osu.Game.Storyboards public double StartTime { get; } - public double EndTime => StartTime; - public int Volume { get; } public IEnumerable LookupNames => new[] diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index fdaa59d7d9..8f2c1e9e0c 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -11,7 +11,7 @@ using JetBrains.Annotations; namespace osu.Game.Storyboards { - public class StoryboardSprite : IStoryboardElement + public class StoryboardSprite : IStoryboardElement, IHasDuration { private readonly List loops = new List(); private readonly List triggers = new List(); diff --git a/osu.Game/Storyboards/StoryboardVideo.cs b/osu.Game/Storyboards/StoryboardVideo.cs index 1314bd7cb9..4652e45852 100644 --- a/osu.Game/Storyboards/StoryboardVideo.cs +++ b/osu.Game/Storyboards/StoryboardVideo.cs @@ -14,8 +14,6 @@ namespace osu.Game.Storyboards public double StartTime { get; } - public double EndTime => StartTime; - public StoryboardVideo(string path, int offset) { Path = path; From b15838b22027746fd9174e5fb72e10ade6a68cd2 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Fri, 16 Apr 2021 00:59:10 -0400 Subject: [PATCH 004/134] Move storyboard outro logic to DrawableStoryboard --- .../Gameplay/TestSceneStoryboardWithOutro.cs | 17 +++++++++++-- .../Multiplayer/MultiplayerPlayer.cs | 3 +-- osu.Game/Screens/Play/DimmableStoryboard.cs | 3 +++ .../Screens/Play/GameplayClockContainer.cs | 20 --------------- osu.Game/Screens/Play/Player.cs | 25 ++++++++----------- osu.Game/Screens/Play/PlayerConfiguration.cs | 9 ++----- .../Drawables/DrawableStoryboard.cs | 23 +++++++++++++++++ ...on.cs => IStoryboardElementHasDuration.cs} | 2 +- osu.Game/Storyboards/Storyboard.cs | 2 +- osu.Game/Storyboards/StoryboardSprite.cs | 2 +- 10 files changed, 57 insertions(+), 49 deletions(-) rename osu.Game/Storyboards/{IHasDuration.cs => IStoryboardElementHasDuration.cs} (81%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 1c8b33bb09..27d203d5d6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -6,12 +6,14 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Storyboards; using osuTK; @@ -36,6 +38,16 @@ namespace osu.Game.Tests.Visual.Gameplay storyboard.GetLayer("Background").Add(sprite); } + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + AddStep("ignore user settings", () => + { + Player.DimmableStoryboard.IgnoreUserSettings.Value = true; + }); + } + [Test] public void TestStoryboardSkipOutro() { @@ -50,8 +62,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); AddUntilStep("storyboard ends", () => Player.HUDOverlay.Progress.ReferenceClock.CurrentTime >= storyboard_duration); - AddWaitStep("wait for score", 10); - AddAssert("score shown", () => Player.IsScoreShown); + AddUntilStep("wait for score shown", () => Player.IsScoreShown); } [Test] @@ -85,6 +96,8 @@ namespace osu.Game.Tests.Visual.Gameplay public bool IsScoreShown => !this.IsCurrentScreen() && this.GetChildScreen() is ResultsScreen; + public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; + public OutroPlayer() : base(false) { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index b4e8c13e83..ae2042fbe8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -48,8 +48,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { AllowPause = false, AllowRestart = false, - AllowSkippingIntro = false, - AllowSkippingOutro = false, + AllowSkipping = false, }) { this.userIds = userIds; diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 58eb95b7c6..bebde1b15b 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Containers; using osu.Game.Storyboards; @@ -61,5 +62,7 @@ namespace osu.Game.Screens.Play Add(storyboard); OverlayLayerContainer.Add(storyboard.OverlayLayer.CreateProxy()); } + + public IBindable HasStoryboardEnded => drawableStoryboard?.HasStoryboardEnded; } } diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index fc45d661cf..95419c0b35 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -240,8 +240,6 @@ namespace osu.Game.Screens.Play userOffsetClock.ProcessFrame(); } - updateHasStoryboardEnded(); - base.Update(); } @@ -303,23 +301,5 @@ namespace osu.Game.Screens.Play { } } - - # region Storyboard outro logic - - public IBindable HasStoryboardEnded => hasStoryboardEnded; - - public bool HasTimeLeftInStoryboard => GameplayClock.CurrentTime <= StoryboardEndTime; - - private readonly BindableBool hasStoryboardEnded = new BindableBool(true); - - private void updateHasStoryboardEnded() - { - if (StoryboardEndTime == 0) - return; - - hasStoryboardEnded.Value = GameplayClock.CurrentTime >= StoryboardEndTime; - } - - # endregion } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 14ba9e7e02..81d2621647 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -74,8 +74,6 @@ namespace osu.Game.Screens.Play private Bindable mouseWheelDisabled; - private Bindable storyboardEnabled; - private readonly Bindable storyboardReplacesBackground = new Bindable(); protected readonly Bindable LocalUserPlaying = new Bindable(); @@ -106,7 +104,7 @@ namespace osu.Game.Screens.Play private BreakTracker breakTracker; - private SkipOverlay skipOverlay; + private SkipOverlay skipIntroOverlay; private SkipOverlay skipOutroOverlay; @@ -194,8 +192,6 @@ namespace osu.Game.Screens.Play mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); - storyboardEnabled = config.GetBindable(OsuSetting.ShowStoryboard); - if (game != null) gameActive.BindTo(game.IsActive); @@ -250,7 +246,7 @@ namespace osu.Game.Screens.Play HUDOverlay.ShowHud.Value = false; HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); - skipOverlay.Hide(); + skipIntroOverlay.Hide(); } DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => @@ -292,7 +288,8 @@ namespace osu.Game.Screens.Play HealthProcessor.Failed += onFail; // Keep track of whether the storyboard ended after the playable portion - GameplayClockContainer.HasStoryboardEnded.ValueChanged += updateCompletionState; + if (DimmableStoryboard.HasStoryboardEnded != null) + DimmableStoryboard.HasStoryboardEnded.ValueChanged += updateCompletionState; foreach (var mod in Mods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); @@ -365,7 +362,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre }, - skipOverlay = new SkipOverlay(DrawableRuleset.GameplayStartTime) + skipIntroOverlay = new SkipOverlay(DrawableRuleset.GameplayStartTime) { RequestSkip = performUserRequestedSkip }, @@ -399,11 +396,8 @@ namespace osu.Game.Screens.Play } }; - if (!Configuration.AllowSkippingIntro) - skipOverlay.Expire(); - - if (!Configuration.AllowSkippingOutro) - skipOutroOverlay.Expire(); + if (!Configuration.AllowSkipping) + skipIntroOverlay.Expire(); if (Configuration.AllowRestart) { @@ -637,8 +631,9 @@ namespace osu.Game.Screens.Play return score.ScoreInfo; }); - // show skip overlay if storyboard is enabled and has an outro - if (storyboardEnabled.Value && GameplayClockContainer.HasTimeLeftInStoryboard) + var storyboardHasOutro = DimmableStoryboard.ContentDisplayed && (!DimmableStoryboard.HasStoryboardEnded?.Value ?? false); + + if (storyboardHasOutro) { skipOutroOverlay.Show(); completionProgressDelegate = null; diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index ad29563d54..18ee73374f 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -21,13 +21,8 @@ namespace osu.Game.Screens.Play public bool AllowRestart { get; set; } = true; /// - /// Whether the player should be allowed to skip the intro, advancing to the start of gameplay. + /// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard. /// - public bool AllowSkippingIntro { get; set; } = true; - - /// - /// Whether the player should be allowed to skip the outro, advancing to the end of a storyboard. - /// - public bool AllowSkippingOutro { get; set; } = true; + public bool AllowSkipping { get; set; } = true; } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index af4615c895..08c2bf1b4a 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using osuTK; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; @@ -82,5 +83,27 @@ namespace osu.Game.Storyboards.Drawables foreach (var layer in Children) layer.Enabled = passing ? layer.Layer.VisibleWhenPassing : layer.Layer.VisibleWhenFailing; } + + protected override void Update() + { + base.Update(); + updateHasStoryboardEnded(); + } + + /// + /// Whether the storyboard has ended after the gameplay portion of the beatmap. + /// + public IBindable HasStoryboardEnded => hasStoryboardEnded; + + private readonly BindableBool hasStoryboardEnded = new BindableBool(true); + + private void updateHasStoryboardEnded() + { + if (Storyboard.LatestEventTime == null) + return; + + var time = Clock.CurrentTime; + hasStoryboardEnded.Value = time >= Storyboard.LatestEventTime; + } } } diff --git a/osu.Game/Storyboards/IHasDuration.cs b/osu.Game/Storyboards/IStoryboardElementHasDuration.cs similarity index 81% rename from osu.Game/Storyboards/IHasDuration.cs rename to osu.Game/Storyboards/IStoryboardElementHasDuration.cs index 98f75b8ee2..e6ee373812 100644 --- a/osu.Game/Storyboards/IHasDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementHasDuration.cs @@ -3,7 +3,7 @@ namespace osu.Game.Storyboards { - public interface IHasDuration + public interface IStoryboardElementHasDuration { double EndTime { get; } } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 669f6ccc43..4fa64b7c34 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -40,7 +40,7 @@ namespace osu.Game.Storyboards /// Across all layers, find the latest point in time that a storyboard element ends at. /// Will return null if there are no elements. /// - public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; + public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; /// /// Depth of the currently front-most storyboard layer, excluding the overlay layer. diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 8f2c1e9e0c..51bdce3321 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -11,7 +11,7 @@ using JetBrains.Annotations; namespace osu.Game.Storyboards { - public class StoryboardSprite : IStoryboardElement, IHasDuration + public class StoryboardSprite : IStoryboardElement, IStoryboardElementHasDuration { private readonly List loops = new List(); private readonly List triggers = new List(); From 33a665224e6c1f77846e9f03927fa72b4cd3859f Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Fri, 16 Apr 2021 01:03:15 -0400 Subject: [PATCH 005/134] Clean up skipOutroOverlay if skipping is disabled --- osu.Game/Screens/Play/Player.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 81d2621647..7ad9c1a8af 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -397,7 +397,10 @@ namespace osu.Game.Screens.Play }; if (!Configuration.AllowSkipping) + { skipIntroOverlay.Expire(); + skipOutroOverlay.Expire(); + } if (Configuration.AllowRestart) { From 81be562379d5bb60023be3f20ecb1f8990993ef9 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 12:28:31 -0400 Subject: [PATCH 006/134] Read StoryboardEndTime directly from Beatmap --- osu.Game/Screens/Play/GameplayClockContainer.cs | 5 ----- osu.Game/Screens/Play/Player.cs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 95419c0b35..ddbb087962 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -228,11 +228,6 @@ namespace osu.Game.Screens.Play adjustableClock.ChangeSource(track); } - /// - /// Gets the endtime of the last element in the storyboard in ms, or start time of the last hitobject if there's no storyboard. - /// - public double StoryboardEndTime => beatmap.Storyboard.LatestEventTime ?? 0; - protected override void Update() { if (!IsPaused.Value) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7ad9c1a8af..e998f33cc1 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -366,7 +366,7 @@ namespace osu.Game.Screens.Play { RequestSkip = performUserRequestedSkip }, - skipOutroOverlay = new SkipOverlay(GameplayClockContainer.StoryboardEndTime) + skipOutroOverlay = new SkipOverlay(Beatmap.Value.Storyboard.LatestEventTime ?? 0) { RequestSkip = scheduleCompletion }, From 5a015290b9721e151a689abd29162d2deab1ad18 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 12:34:38 -0400 Subject: [PATCH 007/134] Add remarks back to LatestEventTime --- osu.Game/Storyboards/Storyboard.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 4fa64b7c34..0b02a4921b 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -40,6 +40,10 @@ namespace osu.Game.Storyboards /// Across all layers, find the latest point in time that a storyboard element ends at. /// Will return null if there are no elements. /// + /// + /// This iterates all elements and as such should be used sparingly or stored locally. + /// Videos and samples return StartTime as their EndTIme. + /// public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; /// From 7f5b1e84a16d42763f20ecb69359213e4d6868c9 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 13:57:32 -0400 Subject: [PATCH 008/134] Update TestSceneStoryboardWithOutro.cs - Construct storyboard in CreateWorkingBeatmap() - Use GameplayClockContainer.GameplayClock.CurrentTime - Remove unnecessary lines --- .../Gameplay/TestSceneStoryboardWithOutro.cs | 39 +++++++------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 27d203d5d6..16474d23ea 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -3,7 +3,6 @@ using System.Threading.Tasks; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Framework.Testing; @@ -13,7 +12,6 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Scoring; -using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Storyboards; using osuTK; @@ -24,28 +22,14 @@ namespace osu.Game.Tests.Visual.Gameplay { protected new OutroPlayer Player => (OutroPlayer)base.Player; - private Storyboard storyboard; - private const double storyboard_duration = 2000; - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - config.SetValue(OsuSetting.ShowStoryboard, true); - storyboard = new Storyboard(); - var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero); - sprite.TimelineGroup.Alpha.Add(Easing.None, 0, storyboard_duration, 1, 0); - storyboard.GetLayer("Background").Add(sprite); - } - [SetUpSteps] public override void SetUpSteps() { base.SetUpSteps(); - AddStep("ignore user settings", () => - { - Player.DimmableStoryboard.IgnoreUserSettings.Value = true; - }); + AddStep("enable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, true)); + AddStep("set dim level to 0", () => LocalConfig.SetValue(OsuSetting.DimLevel, 0)); } [Test] @@ -61,7 +45,7 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestStoryboardNoSkipOutro() { AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); - AddUntilStep("storyboard ends", () => Player.HUDOverlay.Progress.ReferenceClock.CurrentTime >= storyboard_duration); + AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= storyboard_duration); AddUntilStep("wait for score shown", () => Player.IsScoreShown); } @@ -87,8 +71,18 @@ namespace osu.Game.Tests.Visual.Gameplay return beatmap; } - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => - new ClockBackedTestWorkingBeatmap(beatmap, storyboard ?? this.storyboard, Clock, Audio); + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) + { + if (storyboard == null) + { + storyboard = new Storyboard(); + var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero); + sprite.TimelineGroup.Alpha.Add(Easing.None, 0, storyboard_duration, 1, 0); + storyboard.GetLayer("Background").Add(sprite); + } + + return base.CreateWorkingBeatmap(beatmap, storyboard); + } protected class OutroPlayer : TestPlayer { @@ -96,8 +90,6 @@ namespace osu.Game.Tests.Visual.Gameplay public bool IsScoreShown => !this.IsCurrentScreen() && this.GetChildScreen() is ResultsScreen; - public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; - public OutroPlayer() : base(false) { @@ -105,7 +97,6 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Task ImportScore(Score score) { - // avoid database errors from trying to store the score return Task.CompletedTask; } } From e40cb6797df3896d6179dc0f85edef8168c5ee09 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 15:27:22 -0400 Subject: [PATCH 009/134] Use GetEndTime() to get storyboard endtime --- osu.Game/Storyboards/IStoryboardElement.cs | 13 +++++++++++++ .../Storyboards/IStoryboardElementHasDuration.cs | 3 +++ osu.Game/Storyboards/Storyboard.cs | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index c4c150a8a4..377ad57ab2 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -14,4 +14,17 @@ namespace osu.Game.Storyboards Drawable CreateDrawable(); } + + public static class StoryboardElementExtensions + { + /// + /// Returns the end time of this object. + /// + /// + /// This returns the where available, falling back to otherwise. + /// + /// The object. + /// The end time of this object. + public static double GetEndTime(this IStoryboardElement storyboardElement) => (storyboardElement as IStoryboardElementHasDuration)?.EndTime ?? storyboardElement.StartTime; + } } diff --git a/osu.Game/Storyboards/IStoryboardElementHasDuration.cs b/osu.Game/Storyboards/IStoryboardElementHasDuration.cs index e6ee373812..daa0c55704 100644 --- a/osu.Game/Storyboards/IStoryboardElementHasDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementHasDuration.cs @@ -3,6 +3,9 @@ namespace osu.Game.Storyboards { + /// + /// A StoryboardElement that ends at a different time than its start time. + /// public interface IStoryboardElementHasDuration { double EndTime { get; } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 0b02a4921b..bc61f704dd 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -44,7 +44,7 @@ namespace osu.Game.Storyboards /// This iterates all elements and as such should be used sparingly or stored locally. /// Videos and samples return StartTime as their EndTIme. /// - public double? LatestEventTime => Layers.SelectMany(l => l.Elements.OfType()).OrderByDescending(e => e.EndTime).FirstOrDefault()?.EndTime; + public double? LatestEventTime => Layers.SelectMany(l => l.Elements).OrderBy(e => e.GetEndTime()).LastOrDefault()?.GetEndTime(); /// /// Depth of the currently front-most storyboard layer, excluding the overlay layer. From fdcb5e924c9153de2065731689d902d887652bca Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 17:45:38 -0400 Subject: [PATCH 010/134] Initialize skipOutroOverlay with alpha 0, other small changes --- osu.Game/Screens/Play/Player.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e998f33cc1..ef0caa2fa3 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -247,6 +247,7 @@ namespace osu.Game.Screens.Play HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); skipIntroOverlay.Hide(); + skipOutroOverlay.Hide(); } DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => @@ -368,7 +369,8 @@ namespace osu.Game.Screens.Play }, skipOutroOverlay = new SkipOverlay(Beatmap.Value.Storyboard.LatestEventTime ?? 0) { - RequestSkip = scheduleCompletion + RequestSkip = scheduleCompletion, + Alpha = 0 }, FailOverlay = new FailOverlay { @@ -416,8 +418,6 @@ namespace osu.Game.Screens.Play }); } - skipOutroOverlay.Hide(); - return container; } @@ -539,13 +539,9 @@ namespace osu.Game.Screens.Play return; } - // show the score if in storyboard outro (score has been set) - bool scoreReady = prepareScoreForDisplayTask != null && prepareScoreForDisplayTask.IsCompleted; - - if (scoreReady) - { + // if the score is ready for display but results screen has not been pushed yet (e.g. storyboard is still playing beyond gameplay), then transition to results screen instead of exiting. + if (prepareScoreForDisplayTask != null) scheduleCompletion(); - } } this.Exit(); @@ -639,7 +635,6 @@ namespace osu.Game.Screens.Play if (storyboardHasOutro) { skipOutroOverlay.Show(); - completionProgressDelegate = null; return; } From 97bacbdc760942ccb7052441b249f6a1c87ce2bd Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 17:55:46 -0400 Subject: [PATCH 011/134] Show score after the end of the storyboard after it was toggled --- osu.Game/Screens/Play/DimmableStoryboard.cs | 3 ++- osu.Game/Storyboards/Drawables/DrawableStoryboard.cs | 10 ++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index bebde1b15b..73b4153601 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -50,6 +50,7 @@ namespace osu.Game.Screens.Play return; drawableStoryboard = storyboard.CreateDrawable(); + HasStoryboardEnded.BindTo(drawableStoryboard.HasStoryboardEnded); if (async) LoadComponentAsync(drawableStoryboard, onStoryboardCreated); @@ -63,6 +64,6 @@ namespace osu.Game.Screens.Play OverlayLayerContainer.Add(storyboard.OverlayLayer.CreateProxy()); } - public IBindable HasStoryboardEnded => drawableStoryboard?.HasStoryboardEnded; + public IBindable HasStoryboardEnded = new BindableBool(true); } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 08c2bf1b4a..abfb4598ec 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -95,15 +95,13 @@ namespace osu.Game.Storyboards.Drawables /// public IBindable HasStoryboardEnded => hasStoryboardEnded; - private readonly BindableBool hasStoryboardEnded = new BindableBool(true); + private readonly BindableBool hasStoryboardEnded = new BindableBool(); private void updateHasStoryboardEnded() { - if (Storyboard.LatestEventTime == null) - return; - - var time = Clock.CurrentTime; - hasStoryboardEnded.Value = time >= Storyboard.LatestEventTime; + hasStoryboardEnded.Value = + Storyboard.LatestEventTime == null || + Time.Current >= Storyboard.LatestEventTime; } } } From c77f838fb051a4edaf2de036438045d489c10db2 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 21:49:07 -0400 Subject: [PATCH 012/134] HasStoryboardEnded doesn't trigger updateCompletionState() Scores won't be shown prematurely if the storyboard ends before the playable portion of the beatmap. --- osu.Game/Screens/Play/Player.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ef0caa2fa3..622d99f078 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -284,14 +284,16 @@ namespace osu.Game.Screens.Play ScoreProcessor.RevertResult(r); }; + DimmableStoryboard.HasStoryboardEnded.ValueChanged += _ => + { + if (ScoreProcessor.HasCompleted.Value) + scheduleCompletion(); + }; + // Bind the judgement processors to ourselves ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState; HealthProcessor.Failed += onFail; - // Keep track of whether the storyboard ended after the playable portion - if (DimmableStoryboard.HasStoryboardEnded != null) - DimmableStoryboard.HasStoryboardEnded.ValueChanged += updateCompletionState; - foreach (var mod in Mods.Value.OfType()) mod.ApplyToScoreProcessor(ScoreProcessor); @@ -630,7 +632,7 @@ namespace osu.Game.Screens.Play return score.ScoreInfo; }); - var storyboardHasOutro = DimmableStoryboard.ContentDisplayed && (!DimmableStoryboard.HasStoryboardEnded?.Value ?? false); + var storyboardHasOutro = DimmableStoryboard.ContentDisplayed && !DimmableStoryboard.HasStoryboardEnded.Value; if (storyboardHasOutro) { From e9f8fa64b88b49c50c2ac9284e8d048034269e4d Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 21:49:29 -0400 Subject: [PATCH 013/134] Added a test for toggling the storyboard after the map is loaded --- .../Visual/Gameplay/TestSceneStoryboardWithOutro.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 16474d23ea..e86b7591c6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -58,6 +58,16 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("score shown", () => Player.IsScoreShown); } + [TestCase(false)] + [TestCase(true)] + public void TestStoryboardToggle(bool enabledAtBeginning) + { + AddStep($"{(enabledAtBeginning ? "enable" : "disable")} storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, enabledAtBeginning)); + AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); + AddStep($"toggle storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, !enabledAtBeginning)); + AddUntilStep("wait for score shown", () => Player.IsScoreShown); + } + protected override bool AllowFail => false; protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); From 7b1d40db7de4fc6544ebc1f4070d600a024df488 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 17 Apr 2021 22:13:28 -0400 Subject: [PATCH 014/134] Remove redundant string interpolation --- osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index e86b7591c6..59d543d686 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep($"{(enabledAtBeginning ? "enable" : "disable")} storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, enabledAtBeginning)); AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); - AddStep($"toggle storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, !enabledAtBeginning)); + AddStep("toggle storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, !enabledAtBeginning)); AddUntilStep("wait for score shown", () => Player.IsScoreShown); } From a73bae7a66889f22f8a321745baf25eafafd3efe Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Apr 2021 06:35:43 +0300 Subject: [PATCH 015/134] Schedule completion when storyboard has actually ended --- osu.Game/Screens/Play/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 622d99f078..cb8ebdcce7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -284,9 +284,9 @@ namespace osu.Game.Screens.Play ScoreProcessor.RevertResult(r); }; - DimmableStoryboard.HasStoryboardEnded.ValueChanged += _ => + DimmableStoryboard.HasStoryboardEnded.ValueChanged += storyboardEnded => { - if (ScoreProcessor.HasCompleted.Value) + if (storyboardEnded.NewValue && ScoreProcessor.HasCompleted.Value) scheduleCompletion(); }; From f6a09be62d4a88ec2f15a4040c3b1e1d9e0e2329 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Apr 2021 06:35:54 +0300 Subject: [PATCH 016/134] Add further xmldoc --- osu.Game/Screens/Play/DimmableStoryboard.cs | 10 ++++++++-- osu.Game/Storyboards/Drawables/DrawableStoryboard.cs | 2 +- osu.Game/Storyboards/IStoryboardElement.cs | 8 ++++---- osu.Game/Storyboards/IStoryboardElementHasDuration.cs | 5 ++++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 73b4153601..f8cedddfbe 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -20,6 +20,14 @@ namespace osu.Game.Screens.Play private readonly Storyboard storyboard; private DrawableStoryboard drawableStoryboard; + /// + /// Whether the storyboard is considered finished. + /// + /// + /// This is true by default in here, until an actual drawable storyboard is loaded, in which case it'll bind to it. + /// + public IBindable HasStoryboardEnded = new BindableBool(true); + public DimmableStoryboard(Storyboard storyboard) { this.storyboard = storyboard; @@ -63,7 +71,5 @@ namespace osu.Game.Screens.Play Add(storyboard); OverlayLayerContainer.Add(storyboard.OverlayLayer.CreateProxy()); } - - public IBindable HasStoryboardEnded = new BindableBool(true); } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index abfb4598ec..a9a8b8a4ac 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -91,7 +91,7 @@ namespace osu.Game.Storyboards.Drawables } /// - /// Whether the storyboard has ended after the gameplay portion of the beatmap. + /// Whether the storyboard is considered finished. /// public IBindable HasStoryboardEnded => hasStoryboardEnded; diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index 377ad57ab2..2f05e92070 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -18,13 +18,13 @@ namespace osu.Game.Storyboards public static class StoryboardElementExtensions { /// - /// Returns the end time of this object. + /// Returns the end time of this storyboard element. /// /// /// This returns the where available, falling back to otherwise. /// - /// The object. - /// The end time of this object. - public static double GetEndTime(this IStoryboardElement storyboardElement) => (storyboardElement as IStoryboardElementHasDuration)?.EndTime ?? storyboardElement.StartTime; + /// The storyboard element. + /// The end time of this element. + public static double GetEndTime(this IStoryboardElement element) => (element as IStoryboardElementHasDuration)?.EndTime ?? element.StartTime; } } diff --git a/osu.Game/Storyboards/IStoryboardElementHasDuration.cs b/osu.Game/Storyboards/IStoryboardElementHasDuration.cs index daa0c55704..b8d3b66694 100644 --- a/osu.Game/Storyboards/IStoryboardElementHasDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementHasDuration.cs @@ -4,10 +4,13 @@ namespace osu.Game.Storyboards { /// - /// A StoryboardElement that ends at a different time than its start time. + /// A that ends at a different time than its start time. /// public interface IStoryboardElementHasDuration { + /// + /// The time at which the ends. + /// double EndTime { get; } } } From f45aed125903673a1eaa27484bce71c5026d61e8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Apr 2021 07:16:00 +0300 Subject: [PATCH 017/134] Remove new line between skip overlay fields --- osu.Game/Screens/Play/Player.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index cb8ebdcce7..da877fcd22 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -105,7 +105,6 @@ namespace osu.Game.Screens.Play private BreakTracker breakTracker; private SkipOverlay skipIntroOverlay; - private SkipOverlay skipOutroOverlay; protected ScoreProcessor ScoreProcessor { get; private set; } From 98460c8febc37c17acb949a864f528c32ef637cb Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sun, 18 Apr 2021 00:45:24 -0400 Subject: [PATCH 018/134] Rename IStoryboardElementHasDuration, remove unnecessary step in tests, add Duration field --- .../Visual/Gameplay/TestSceneStoryboardWithOutro.cs | 4 ---- osu.Game/Storyboards/IStoryboardElement.cs | 4 ++-- ...entHasDuration.cs => IStoryboardElementWithDuration.cs} | 7 ++++++- osu.Game/Storyboards/StoryboardSprite.cs | 4 +++- 4 files changed, 11 insertions(+), 8 deletions(-) rename osu.Game/Storyboards/{IStoryboardElementHasDuration.cs => IStoryboardElementWithDuration.cs} (70%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 59d543d686..fa1c4aa0d1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -35,7 +35,6 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestStoryboardSkipOutro() { - AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("skip outro", () => InputManager.Key(osuTK.Input.Key.Space)); AddAssert("score shown", () => Player.IsScoreShown); @@ -44,7 +43,6 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestStoryboardNoSkipOutro() { - AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= storyboard_duration); AddUntilStep("wait for score shown", () => Player.IsScoreShown); } @@ -52,7 +50,6 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestStoryboardExitToSkipOutro() { - AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("exit via pause", () => Player.ExitViaPause()); AddAssert("score shown", () => Player.IsScoreShown); @@ -63,7 +60,6 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestStoryboardToggle(bool enabledAtBeginning) { AddStep($"{(enabledAtBeginning ? "enable" : "disable")} storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, enabledAtBeginning)); - AddUntilStep("storyboard loaded", () => Player.Beatmap.Value.StoryboardLoaded); AddStep("toggle storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, !enabledAtBeginning)); AddUntilStep("wait for score shown", () => Player.IsScoreShown); } diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index 2f05e92070..9a059991e6 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -21,10 +21,10 @@ namespace osu.Game.Storyboards /// Returns the end time of this storyboard element. /// /// - /// This returns the where available, falling back to otherwise. + /// This returns the where available, falling back to otherwise. /// /// The storyboard element. /// The end time of this element. - public static double GetEndTime(this IStoryboardElement element) => (element as IStoryboardElementHasDuration)?.EndTime ?? element.StartTime; + public static double GetEndTime(this IStoryboardElement element) => (element as IStoryboardElementWithDuration)?.EndTime ?? element.StartTime; } } diff --git a/osu.Game/Storyboards/IStoryboardElementHasDuration.cs b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs similarity index 70% rename from osu.Game/Storyboards/IStoryboardElementHasDuration.cs rename to osu.Game/Storyboards/IStoryboardElementWithDuration.cs index b8d3b66694..02b438cb76 100644 --- a/osu.Game/Storyboards/IStoryboardElementHasDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs @@ -6,11 +6,16 @@ namespace osu.Game.Storyboards /// /// A that ends at a different time than its start time. /// - public interface IStoryboardElementHasDuration + public interface IStoryboardElementWithDuration : IStoryboardElement { /// /// The time at which the ends. /// double EndTime { get; } + + /// + /// The duration of the StoryboardElement. + /// + double Duration { get; } } } diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 51bdce3321..0aaf264341 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -11,7 +11,7 @@ using JetBrains.Annotations; namespace osu.Game.Storyboards { - public class StoryboardSprite : IStoryboardElement, IStoryboardElementHasDuration + public class StoryboardSprite : IStoryboardElementWithDuration { private readonly List loops = new List(); private readonly List triggers = new List(); @@ -65,6 +65,8 @@ namespace osu.Game.Storyboards } } + public double Duration => EndTime - StartTime; + public bool HasCommands => TimelineGroup.HasCommands || loops.Any(l => l.HasCommands); private delegate void DrawablePropertyInitializer(Drawable drawable, T value); From 99fab456b57adb11d4bbb6a92b959633fb33c21c Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sun, 18 Apr 2021 23:25:20 -0400 Subject: [PATCH 019/134] Storyboard completion calls updateCompletionState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - If the storyboard ends after the beatmap, call updateCompletionState as if the score processor has completed at that time. (completionProgressDelegate is null here since earlier when the score processor actually completed, updateCompletionState returned after showing the skip overlay.) - If the storyboard ends before the beatmap does, updateCompletionState simply returns and waits until the score processor is completed. - If the storyboard and beatmap end at the exact same time, make sure updateCompletionState() is called only once by the score processor completion. Co-Authored-By: Marlina José --- osu.Game/Screens/Play/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index da877fcd22..231fcbc174 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -285,8 +285,8 @@ namespace osu.Game.Screens.Play DimmableStoryboard.HasStoryboardEnded.ValueChanged += storyboardEnded => { - if (storyboardEnded.NewValue && ScoreProcessor.HasCompleted.Value) - scheduleCompletion(); + if (storyboardEnded.NewValue && completionProgressDelegate == null) + updateCompletionState(new ValueChangedEvent(true, ScoreProcessor.HasCompleted.Value)); }; // Bind the judgement processors to ourselves From fd1241cc8513c72674f723a4c8767d9d5672430d Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sun, 18 Apr 2021 23:26:50 -0400 Subject: [PATCH 020/134] Added tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New tests: - storyboard ending during the failing animation - showResults = false - storyboard ending before score processor completion Co-Authored-By: Marlina José --- .../Gameplay/TestSceneStoryboardWithOutro.cs | 92 ++++++++++++++++--- 1 file changed, 78 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index fa1c4aa0d1..8326063f81 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -1,17 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Storyboards; using osuTK; @@ -20,9 +25,15 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneStoryboardWithOutro : PlayerTestScene { + protected override bool HasCustomSteps => true; + protected new OutroPlayer Player => (OutroPlayer)base.Player; - private const double storyboard_duration = 2000; + private double currentStoryboardDuration; + + private bool showResults = true; + + private event Func currentFailConditions; [SetUpSteps] public override void SetUpSteps() @@ -30,11 +41,15 @@ namespace osu.Game.Tests.Visual.Gameplay base.SetUpSteps(); AddStep("enable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, true)); AddStep("set dim level to 0", () => LocalConfig.SetValue(OsuSetting.DimLevel, 0)); + AddStep("reset fail conditions", () => currentFailConditions = (_, __) => false); + AddStep("set storyboard duration to 2s", () => currentStoryboardDuration = 2000); + AddStep("set ShowResults = true", () => showResults = true); } [Test] public void TestStoryboardSkipOutro() { + CreateTest(null); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("skip outro", () => InputManager.Key(osuTK.Input.Key.Space)); AddAssert("score shown", () => Player.IsScoreShown); @@ -43,13 +58,15 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestStoryboardNoSkipOutro() { - AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= storyboard_duration); + CreateTest(null); + AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration); AddUntilStep("wait for score shown", () => Player.IsScoreShown); } [Test] public void TestStoryboardExitToSkipOutro() { + CreateTest(null); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("exit via pause", () => Player.ExitViaPause()); AddAssert("score shown", () => Player.IsScoreShown); @@ -59,16 +76,51 @@ namespace osu.Game.Tests.Visual.Gameplay [TestCase(true)] public void TestStoryboardToggle(bool enabledAtBeginning) { + CreateTest(null); AddStep($"{(enabledAtBeginning ? "enable" : "disable")} storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, enabledAtBeginning)); AddStep("toggle storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, !enabledAtBeginning)); AddUntilStep("wait for score shown", () => Player.IsScoreShown); } - protected override bool AllowFail => false; + [Test] + public void TestOutroEndsDuringFailAnimation() + { + CreateTest(() => + { + AddStep("fail on first judgement", () => currentFailConditions = (_, __) => true); + AddStep("set storyboard duration to 1.3s", () => currentStoryboardDuration = 1300); + }); + AddUntilStep("wait for fail", () => Player.HasFailed); + AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration); + AddUntilStep("wait for fail overlay", () => Player.FailOverlay.State.Value == Visibility.Visible); + } + + [Test] + public void TestShowResultsFalse() + { + CreateTest(() => + { + AddStep("set ShowResults = false", () => showResults = false); + }); + AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration); + AddWaitStep("wait", 10); + AddAssert("no score shown", () => !Player.IsScoreShown); + } + + [Test] + public void TestStoryboardEndsBeforeCompletion() + { + CreateTest(() => AddStep("set storyboard duration to .1s", () => currentStoryboardDuration = 100)); + AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration); + AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + AddUntilStep("wait for score shown", () => Player.IsScoreShown); + } + + protected override bool AllowFail => true; protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); - protected override TestPlayer CreatePlayer(Ruleset ruleset) => new OutroPlayer(); + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new OutroPlayer(currentFailConditions, showResults); protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) { @@ -79,26 +131,38 @@ namespace osu.Game.Tests.Visual.Gameplay protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - if (storyboard == null) - { - storyboard = new Storyboard(); - var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero); - sprite.TimelineGroup.Alpha.Add(Easing.None, 0, storyboard_duration, 1, 0); - storyboard.GetLayer("Background").Add(sprite); - } + return base.CreateWorkingBeatmap(beatmap, createStoryboard(currentStoryboardDuration)); + } - return base.CreateWorkingBeatmap(beatmap, storyboard); + private Storyboard createStoryboard(double duration) + { + var storyboard = new Storyboard(); + var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero); + sprite.TimelineGroup.Alpha.Add(Easing.None, 0, duration, 1, 0); + storyboard.GetLayer("Background").Add(sprite); + return storyboard; } protected class OutroPlayer : TestPlayer { public void ExitViaPause() => PerformExit(true); + public new FailOverlay FailOverlay => base.FailOverlay; + public bool IsScoreShown => !this.IsCurrentScreen() && this.GetChildScreen() is ResultsScreen; - public OutroPlayer() - : base(false) + private event Func failConditions; + + public OutroPlayer(Func failConditions, bool showResults = true) + : base(false, showResults) { + this.failConditions = failConditions; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + HealthProcessor.FailConditions += failConditions; } protected override Task ImportScore(Score score) From 0b36dd9bce6e4f958b51e91d52c7fd650abf2673 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Mon, 19 Apr 2021 01:23:21 -0400 Subject: [PATCH 021/134] Skip outro overlay and PerformExit() call updateCompletionState() instead of scheduleCompletion() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Marlina José --- osu.Game/Screens/Play/Player.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 231fcbc174..ef2e042260 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -290,7 +290,7 @@ namespace osu.Game.Screens.Play }; // Bind the judgement processors to ourselves - ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState; + ScoreProcessor.HasCompleted.BindValueChanged(e => updateCompletionState(e)); HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType()) @@ -370,7 +370,7 @@ namespace osu.Game.Screens.Play }, skipOutroOverlay = new SkipOverlay(Beatmap.Value.Storyboard.LatestEventTime ?? 0) { - RequestSkip = scheduleCompletion, + RequestSkip = () => updateCompletionState(new ValueChangedEvent(true, true), true), Alpha = 0 }, FailOverlay = new FailOverlay @@ -542,7 +542,7 @@ namespace osu.Game.Screens.Play // if the score is ready for display but results screen has not been pushed yet (e.g. storyboard is still playing beyond gameplay), then transition to results screen instead of exiting. if (prepareScoreForDisplayTask != null) - scheduleCompletion(); + updateCompletionState(new ValueChangedEvent(true, true), true); } this.Exit(); @@ -581,7 +581,7 @@ namespace osu.Game.Screens.Play private ScheduledDelegate completionProgressDelegate; private Task prepareScoreForDisplayTask; - private void updateCompletionState(ValueChangedEvent completionState) + private void updateCompletionState(ValueChangedEvent completionState, bool skipStoryboardOutro = false) { // screen may be in the exiting transition phase. if (!this.IsCurrentScreen()) @@ -631,6 +631,12 @@ namespace osu.Game.Screens.Play return score.ScoreInfo; }); + if (skipStoryboardOutro) + { + scheduleCompletion(); + return; + } + var storyboardHasOutro = DimmableStoryboard.ContentDisplayed && !DimmableStoryboard.HasStoryboardEnded.Value; if (storyboardHasOutro) From abfa6aec87047027380c54f75fcba502da3941df Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Mon, 19 Apr 2021 01:58:19 -0400 Subject: [PATCH 022/134] Remove completionState parameter --- osu.Game/Screens/Play/Player.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ef2e042260..dd7cf944f7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -286,11 +286,11 @@ namespace osu.Game.Screens.Play DimmableStoryboard.HasStoryboardEnded.ValueChanged += storyboardEnded => { if (storyboardEnded.NewValue && completionProgressDelegate == null) - updateCompletionState(new ValueChangedEvent(true, ScoreProcessor.HasCompleted.Value)); + updateCompletionState(); }; // Bind the judgement processors to ourselves - ScoreProcessor.HasCompleted.BindValueChanged(e => updateCompletionState(e)); + ScoreProcessor.HasCompleted.BindValueChanged(_ => updateCompletionState()); HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType()) @@ -370,7 +370,7 @@ namespace osu.Game.Screens.Play }, skipOutroOverlay = new SkipOverlay(Beatmap.Value.Storyboard.LatestEventTime ?? 0) { - RequestSkip = () => updateCompletionState(new ValueChangedEvent(true, true), true), + RequestSkip = () => updateCompletionState(true), Alpha = 0 }, FailOverlay = new FailOverlay @@ -542,7 +542,7 @@ namespace osu.Game.Screens.Play // if the score is ready for display but results screen has not been pushed yet (e.g. storyboard is still playing beyond gameplay), then transition to results screen instead of exiting. if (prepareScoreForDisplayTask != null) - updateCompletionState(new ValueChangedEvent(true, true), true); + updateCompletionState(true); } this.Exit(); @@ -581,13 +581,13 @@ namespace osu.Game.Screens.Play private ScheduledDelegate completionProgressDelegate; private Task prepareScoreForDisplayTask; - private void updateCompletionState(ValueChangedEvent completionState, bool skipStoryboardOutro = false) + private void updateCompletionState(bool skipStoryboardOutro = false) { // screen may be in the exiting transition phase. if (!this.IsCurrentScreen()) return; - if (!completionState.NewValue) + if (!ScoreProcessor.HasCompleted.Value) { completionProgressDelegate?.Cancel(); completionProgressDelegate = null; From 505a117862cce9818970a71833736c7a294b84c2 Mon Sep 17 00:00:00 2001 From: Denrage Date: Mon, 19 Apr 2021 23:41:51 +0200 Subject: [PATCH 023/134] splitted updateable part of wedge --- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 16 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 261 ++++++++++-------- 2 files changed, 152 insertions(+), 125 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 7ea6373763..9c10c9751c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -112,8 +112,8 @@ namespace osu.Game.Tests.Visual.SongSelect private void testInfoLabels(int expectedCount) { - AddAssert("check info labels exists", () => infoWedge.Info.ChildrenOfType().Any()); - AddAssert("check info labels count", () => infoWedge.Info.ChildrenOfType().Count() == expectedCount); + AddAssert("check info labels exists", () => infoWedge.Info.ChildrenOfType().Any()); + AddAssert("check info labels count", () => infoWedge.Info.ChildrenOfType().Count() == expectedCount); } [Test] @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("check default title", () => infoWedge.Info.TitleLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Title); AddAssert("check default artist", () => infoWedge.Info.ArtistLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Artist); AddAssert("check empty author", () => !infoWedge.Info.MapperContainer.Children.Any()); - AddAssert("check no info labels", () => !infoWedge.Info.ChildrenOfType().Any()); + AddAssert("check no info labels", () => !infoWedge.Info.ChildrenOfType().Any()); } [Test] @@ -135,15 +135,15 @@ namespace osu.Game.Tests.Visual.SongSelect private void selectBeatmap([CanBeNull] IBeatmap b) { - BeatmapInfoWedge.BufferedWedgeInfo infoBefore = null; + BeatmapInfoWedge.BufferedWedgeBackground backgroundBefore = null; AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () => { - infoBefore = infoWedge.Info; + backgroundBefore = infoWedge.Background; infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : CreateWorkingBeatmap(b); }); - AddUntilStep("wait for async load", () => infoWedge.Info != infoBefore); + AddUntilStep("wait for async load", () => infoWedge.Background != backgroundBefore); } private IBeatmap createTestBeatmap(RulesetInfo ruleset) @@ -193,7 +193,9 @@ namespace osu.Game.Tests.Visual.SongSelect private class TestBeatmapInfoWedge : BeatmapInfoWedge { - public new BufferedWedgeInfo Info => base.Info; + public new BufferedWedgeBackground Background => base.Background; + + public new WedgeInfoText Info => base.Info; } private class TestHitObject : ConvertHitObject, IHasPosition diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 4069dc82ed..0b72970bb0 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -49,7 +49,8 @@ namespace osu.Game.Screens.Select private IBindable beatmapDifficulty; - protected BufferedWedgeInfo Info; + protected BufferedWedgeBackground Background; + protected WedgeInfoText Info; public BeatmapInfoWedge() { @@ -110,9 +111,9 @@ namespace osu.Game.Screens.Select } } - public override bool IsPresent => base.IsPresent || Info == null; // Visibility is updated in the LoadComponentAsync callback + public override bool IsPresent => base.IsPresent || Background == null; // Visibility is updated in the LoadComponentAsync callback - private BufferedWedgeInfo loadingInfo; + private BufferedWedgeBackground loadingInfo; private void updateDisplay() { @@ -127,6 +128,10 @@ namespace osu.Game.Screens.Select Info?.FadeOut(250); Info?.Expire(); Info = null; + + Background?.FadeOut(250); + Background?.Expire(); + Background = null; } if (beatmap == null) @@ -135,17 +140,21 @@ namespace osu.Game.Screens.Select return; } - LoadComponentAsync(loadingInfo = new BufferedWedgeInfo(beatmap, ruleset.Value, mods.Value, beatmapDifficulty.Value ?? new StarDifficulty()) + LoadComponentAsync(loadingInfo = new BufferedWedgeBackground(beatmap) { Shear = -Shear, - Depth = Info?.Depth + 1 ?? 0 + Depth = Background?.Depth + 1 ?? 0 }, loaded => { // ensure we are the most recent loaded wedge. if (loaded != loadingInfo) return; removeOldInfo(); - Add(Info = loaded); + Add(Background = loaded); + Add(Info = new WedgeInfoText(beatmap, ruleset.Value, mods.Value, beatmapDifficulty.Value ?? new StarDifficulty()) + { + Shear = -Shear + }); }); } } @@ -156,28 +165,26 @@ namespace osu.Game.Screens.Select cancellationSource?.Cancel(); } - public class BufferedWedgeInfo : BufferedContainer + public class WedgeInfoText : Container { - public OsuSpriteText VersionLabel { get; private set; } + public FillFlowContainer MapperContainer { get; private set; } public OsuSpriteText TitleLabel { get; private set; } public OsuSpriteText ArtistLabel { get; private set; } + public OsuSpriteText VersionLabel { get; private set; } public BeatmapSetOnlineStatusPill StatusPill { get; private set; } - public FillFlowContainer MapperContainer { get; private set; } private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; private FillFlowContainer infoLabelContainer; private Container bpmLabelContainer; + private ModSettingChangeTracker settingChangeTracker; private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; private readonly IReadOnlyList mods; private readonly StarDifficulty starDifficulty; - private ModSettingChangeTracker settingChangeTracker; - - public BufferedWedgeInfo(WorkingBeatmap beatmap, RulesetInfo userRuleset, IReadOnlyList mods, StarDifficulty difficulty) - : base(pixelSnapping: true) + public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IReadOnlyList mods, StarDifficulty difficulty) { this.beatmap = beatmap; ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset; @@ -191,7 +198,6 @@ namespace osu.Game.Screens.Select var beatmapInfo = beatmap.BeatmapInfo; var metadata = beatmapInfo.Metadata ?? beatmap.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); - CacheDrawnFrameBuffer = true; RelativeSizeAxes = Axes.Both; titleBinding = localisation.GetLocalisedString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); @@ -199,32 +205,6 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { - // We will create the white-to-black gradient by modulating transparency and having - // a black backdrop. This results in an sRGB-space gradient and not linear space, - // transitioning from white to black more perceptually uniformly. - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - // We use a container, such that we can set the colour gradient to go across the - // vertices of the masked container instead of the vertices of the (larger) sprite. - new Container - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.White, Color4.White.Opacity(0.3f)), - Children = new[] - { - // Zoomed-in and cropped beatmap background - new BeatmapBackgroundSprite(beatmap) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - }, - }, - }, new DifficultyColourBar(starDifficulty) { RelativeSizeAxes = Axes.Y, @@ -329,51 +309,6 @@ namespace osu.Game.Screens.Select addInfoLabels(); } - private static Drawable createStarRatingDisplay(StarDifficulty difficulty) => difficulty.Stars > 0 - ? new StarRatingDisplay(difficulty) - { - Margin = new MarginPadding { Bottom = 5 } - } - : Empty(); - - private void setMetadata(string source) - { - ArtistLabel.Text = artistBinding.Value; - TitleLabel.Text = string.IsNullOrEmpty(source) ? titleBinding.Value : source + " — " + titleBinding.Value; - ForceRedraw(); - } - - private void addInfoLabels() - { - if (beatmap.Beatmap?.HitObjects?.Any() != true) - return; - - infoLabelContainer.Children = new Drawable[] - { - new InfoLabel(new BeatmapStatistic - { - Name = "Length", - CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Length), - Content = TimeSpan.FromMilliseconds(beatmap.BeatmapInfo.Length).ToString(@"m\:ss"), - }), - bpmLabelContainer = new Container - { - AutoSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(20, 0), - Children = getRulesetInfoLabels() - } - }; - - settingChangeTracker = new ModSettingChangeTracker(mods); - settingChangeTracker.SettingChanged += _ => refreshBPMLabel(); - - refreshBPMLabel(); - } - private InfoLabel[] getRulesetInfoLabels() { try @@ -426,8 +361,43 @@ namespace osu.Game.Screens.Select CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Bpm), Content = labelText }); + } - ForceRedraw(); + private void setMetadata(string source) + { + ArtistLabel.Text = artistBinding.Value; + TitleLabel.Text = string.IsNullOrEmpty(source) ? titleBinding.Value : source + " — " + titleBinding.Value; + } + + private void addInfoLabels() + { + if (beatmap.Beatmap?.HitObjects?.Any() != true) + return; + + infoLabelContainer.Children = new Drawable[] + { + new InfoLabel(new BeatmapStatistic + { + Name = "Length", + CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Length), + Content = TimeSpan.FromMilliseconds(beatmap.BeatmapInfo.Length).ToString(@"m\:ss"), + }), + bpmLabelContainer = new Container + { + AutoSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(20, 0), + Children = getRulesetInfoLabels() + } + }; + + settingChangeTracker = new ModSettingChangeTracker(mods); + settingChangeTracker.SettingChanged += _ => refreshBPMLabel(); + + refreshBPMLabel(); } private OsuSpriteText[] getMapper(BeatmapMetadata metadata) @@ -450,10 +420,48 @@ namespace osu.Game.Screens.Select }; } - protected override void Dispose(bool isDisposing) + private static Drawable createStarRatingDisplay(StarDifficulty difficulty) => difficulty.Stars > 0 + ? new StarRatingDisplay(difficulty) + { + Margin = new MarginPadding { Bottom = 5 } + } + : Empty(); + + private class DifficultyColourBar : Container { - base.Dispose(isDisposing); - settingChangeTracker?.Dispose(); + private readonly StarDifficulty difficulty; + + public DifficultyColourBar(StarDifficulty difficulty) + { + this.difficulty = difficulty; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + const float full_opacity_ratio = 0.7f; + + var difficultyColour = colours.ForDifficultyRating(difficulty.DifficultyRating); + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = difficultyColour, + Width = full_opacity_ratio, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Colour = difficultyColour, + Alpha = 0.5f, + X = full_opacity_ratio, + Width = 1 - full_opacity_ratio, + } + }; + } } public class InfoLabel : Container, IHasTooltip @@ -515,41 +523,58 @@ namespace osu.Game.Screens.Select } } - private class DifficultyColourBar : Container + protected override void Dispose(bool isDisposing) { - private readonly StarDifficulty difficulty; + base.Dispose(isDisposing); + settingChangeTracker?.Dispose(); + } + } - public DifficultyColourBar(StarDifficulty difficulty) + public class BufferedWedgeBackground : BufferedContainer + { + private readonly WorkingBeatmap beatmap; + + public BufferedWedgeBackground(WorkingBeatmap beatmap) + : base(pixelSnapping: true) + { + this.beatmap = beatmap; + } + + [BackgroundDependencyLoader] + private void load(LocalisationManager localisation) + { + CacheDrawnFrameBuffer = true; + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] { - this.difficulty = difficulty; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - const float full_opacity_ratio = 0.7f; - - var difficultyColour = colours.ForDifficultyRating(difficulty.DifficultyRating); - - Children = new Drawable[] + // We will create the white-to-black gradient by modulating transparency and having + // a black backdrop. This results in an sRGB-space gradient and not linear space, + // transitioning from white to black more perceptually uniformly. + new Box { - new Box + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + // We use a container, such that we can set the colour gradient to go across the + // vertices of the masked container instead of the vertices of the (larger) sprite. + new Container + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.White, Color4.White.Opacity(0.3f)), + Children = new[] { - RelativeSizeAxes = Axes.Both, - Colour = difficultyColour, - Width = full_opacity_ratio, + // Zoomed-in and cropped beatmap background + new BeatmapBackgroundSprite(beatmap) + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + }, }, - new Box - { - RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Both, - Colour = difficultyColour, - Alpha = 0.5f, - X = full_opacity_ratio, - Width = 1 - full_opacity_ratio, - } - }; - } + }, + }; } } } From 6e72ee5f7647eb77b2cc1447e32baeb3d4c990c4 Mon Sep 17 00:00:00 2001 From: Denrage Date: Tue, 20 Apr 2021 10:25:12 +0200 Subject: [PATCH 024/134] Added bindable stardifficulty to StarRatingDisplay --- .../Ranking/Expanded/StarRatingDisplay.cs | 79 +++++++++++++------ osu.Game/Screens/Select/BeatmapInfoWedge.cs | 64 +++++++++------ 2 files changed, 95 insertions(+), 48 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index f7e50fdc8a..081b782034 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Globalization; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -22,7 +24,11 @@ namespace osu.Game.Screens.Ranking.Expanded /// public class StarRatingDisplay : CompositeDrawable { - private readonly StarDifficulty difficulty; + private CircularContainer colorContainer; + private OsuTextFlowContainer textContainer; + + private readonly StarDifficulty starDifficulty; + private readonly IBindable bindableStarDifficulty; /// /// Creates a new using an already computed . @@ -30,14 +36,21 @@ namespace osu.Game.Screens.Ranking.Expanded /// The already computed to display the star difficulty of. public StarRatingDisplay(StarDifficulty starDifficulty) { - difficulty = starDifficulty; + this.starDifficulty = starDifficulty; } - [BackgroundDependencyLoader] - private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) + /// + /// Creates a new using a binded nullable . + /// + /// The binded nullable to display the star difficulty of. If null, a new instance of will be created + public StarRatingDisplay(IBindable starDifficulty) { - AutoSizeAxes = Axes.Both; + bindableStarDifficulty = starDifficulty; + } + private void setDifficulty(OsuColour colours) + { + var difficulty = bindableStarDifficulty == null ? starDifficulty : bindableStarDifficulty.Value ?? new StarDifficulty(); var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); string wholePart = starRatingParts[0]; string fractionPart = starRatingParts[1]; @@ -47,9 +60,36 @@ namespace osu.Game.Screens.Ranking.Expanded ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); + colorContainer.Colour = backgroundColour; + + textContainer.Text = string.Empty; + + textContainer.With(t => + { + t.AddText($"{wholePart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 14); + s.UseFullGlyphHeight = false; + }); + + t.AddText($"{separator}{fractionPart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 7); + s.UseFullGlyphHeight = false; + }); + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) + { + AutoSizeAxes = Axes.Both; + InternalChildren = new Drawable[] { - new CircularContainer + colorContainer = new CircularContainer { RelativeSizeAxes = Axes.Both, Masking = true, @@ -58,7 +98,6 @@ namespace osu.Game.Screens.Ranking.Expanded new Box { RelativeSizeAxes = Axes.Both, - Colour = backgroundColour }, } }, @@ -78,32 +117,24 @@ namespace osu.Game.Screens.Ranking.Expanded Icon = FontAwesome.Solid.Star, Colour = Color4.Black }, - new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + textContainer = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, TextAnchor = Anchor.BottomLeft, - }.With(t => - { - t.AddText($"{wholePart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); - - t.AddText($"{separator}{fractionPart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); - }) + }, } } }; + + if (bindableStarDifficulty != null) + { + bindableStarDifficulty.BindValueChanged(_ => setDifficulty(colours)); + } + + setDifficulty(colours); } } } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 0b72970bb0..9dccdd2897 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -105,7 +105,6 @@ namespace osu.Game.Screens.Select beatmapDifficulty?.UnbindAll(); beatmapDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo, cancellationSource.Token); - beatmapDifficulty.BindValueChanged(_ => updateDisplay()); updateDisplay(); } @@ -151,7 +150,7 @@ namespace osu.Game.Screens.Select removeOldInfo(); Add(Background = loaded); - Add(Info = new WedgeInfoText(beatmap, ruleset.Value, mods.Value, beatmapDifficulty.Value ?? new StarDifficulty()) + Add(Info = new WedgeInfoText(beatmap, ruleset.Value, mods.Value, beatmapDifficulty) { Shear = -Shear }); @@ -176,15 +175,16 @@ namespace osu.Game.Screens.Select private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; private FillFlowContainer infoLabelContainer; + private Drawable starRatingDisplay; private Container bpmLabelContainer; private ModSettingChangeTracker settingChangeTracker; private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; private readonly IReadOnlyList mods; - private readonly StarDifficulty starDifficulty; + private readonly IBindable starDifficulty; - public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IReadOnlyList mods, StarDifficulty difficulty) + public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IReadOnlyList mods, IBindable difficulty) { this.beatmap = beatmap; ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset; @@ -241,12 +241,13 @@ namespace osu.Game.Screens.Select Shear = wedged_container_shear, Children = new[] { - createStarRatingDisplay(starDifficulty).With(display => + starRatingDisplay = new StarRatingDisplay(starDifficulty) { - display.Anchor = Anchor.TopRight; - display.Origin = Anchor.TopRight; - display.Shear = -wedged_container_shear; - }), + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -wedged_container_shear, + Margin = new MarginPadding { Bottom = 5 } + }, StatusPill = new BeatmapSetOnlineStatusPill { Anchor = Anchor.TopRight, @@ -309,6 +310,18 @@ namespace osu.Game.Screens.Select addInfoLabels(); } + private void setStarRatingDisplayVisibility() + { + if (starDifficulty.Value.HasValue && starDifficulty.Value.Value.Stars > 0) + { + starRatingDisplay.Show(); + } + else + { + starRatingDisplay.Hide(); + } + } + private InfoLabel[] getRulesetInfoLabels() { try @@ -420,18 +433,14 @@ namespace osu.Game.Screens.Select }; } - private static Drawable createStarRatingDisplay(StarDifficulty difficulty) => difficulty.Stars > 0 - ? new StarRatingDisplay(difficulty) - { - Margin = new MarginPadding { Bottom = 5 } - } - : Empty(); - private class DifficultyColourBar : Container { - private readonly StarDifficulty difficulty; + private Box solidDifficultyBox; + private Box transparentDifficultyBox; - public DifficultyColourBar(StarDifficulty difficulty) + private readonly IBindable difficulty; + + public DifficultyColourBar(IBindable difficulty) { this.difficulty = difficulty; } @@ -441,26 +450,33 @@ namespace osu.Game.Screens.Select { const float full_opacity_ratio = 0.7f; - var difficultyColour = colours.ForDifficultyRating(difficulty.DifficultyRating); - Children = new Drawable[] { - new Box + solidDifficultyBox = new Box { RelativeSizeAxes = Axes.Both, - Colour = difficultyColour, Width = full_opacity_ratio, }, - new Box + transparentDifficultyBox = new Box { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, - Colour = difficultyColour, Alpha = 0.5f, X = full_opacity_ratio, Width = 1 - full_opacity_ratio, } }; + + difficulty.BindValueChanged(_ => setColour(colours)); + setColour(colours); + } + + private void setColour(OsuColour colours) + { + var difficultyColour = colours.ForDifficultyRating(difficulty.Value?.DifficultyRating ?? (new StarDifficulty()).DifficultyRating); + + solidDifficultyBox.Colour = difficultyColour; + transparentDifficultyBox.Colour = difficultyColour; } } From 4e6cd8082ea784ee4223f2f36e7c05f1253aeac5 Mon Sep 17 00:00:00 2001 From: Denrage Date: Tue, 20 Apr 2021 12:00:04 +0200 Subject: [PATCH 025/134] WIP refresh BPM-Label on mod change --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 27 +++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 9dccdd2897..b3aa4f0ba5 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -150,7 +150,7 @@ namespace osu.Game.Screens.Select removeOldInfo(); Add(Background = loaded); - Add(Info = new WedgeInfoText(beatmap, ruleset.Value, mods.Value, beatmapDifficulty) + Add(Info = new WedgeInfoText(beatmap, ruleset.Value, mods, beatmapDifficulty) { Shear = -Shear }); @@ -181,10 +181,10 @@ namespace osu.Game.Screens.Select private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; - private readonly IReadOnlyList mods; + private readonly IBindable> mods; private readonly IBindable starDifficulty; - public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IReadOnlyList mods, IBindable difficulty) + public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IBindable> mods, IBindable difficulty) { this.beatmap = beatmap; ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset; @@ -300,14 +300,16 @@ namespace osu.Game.Screens.Select } }; + addInfoLabels(); + titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); + starDifficulty.BindValueChanged(_ => setStarRatingDisplayVisibility(), true); // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) StatusPill.Hide(); - addInfoLabels(); } private void setStarRatingDisplayVisibility() @@ -349,7 +351,7 @@ namespace osu.Game.Screens.Select return Array.Empty(); } - private void refreshBPMLabel() + private void refreshBPMLabel(IReadOnlyList mods) { var b = beatmap.Beatmap; if (b == null) @@ -407,10 +409,16 @@ namespace osu.Game.Screens.Select } }; - settingChangeTracker = new ModSettingChangeTracker(mods); - settingChangeTracker.SettingChanged += _ => refreshBPMLabel(); + // this is currently not triggering when a mod gets (de)selected + mods.BindValueChanged(mods => refreshModInformation(mods), true); + } - refreshBPMLabel(); + private void refreshModInformation(ValueChangedEvent> modsChangedEvent) + { + settingChangeTracker?.Dispose(); + settingChangeTracker = new ModSettingChangeTracker(modsChangedEvent.NewValue); + settingChangeTracker.SettingChanged += _ => refreshBPMLabel(modsChangedEvent.NewValue); + refreshBPMLabel(mods.Value); } private OsuSpriteText[] getMapper(BeatmapMetadata metadata) @@ -467,8 +475,7 @@ namespace osu.Game.Screens.Select } }; - difficulty.BindValueChanged(_ => setColour(colours)); - setColour(colours); + difficulty.BindValueChanged(_ => setColour(colours), true); } private void setColour(OsuColour colours) From c5d35ab78733cdd64322467e378474e526096a83 Mon Sep 17 00:00:00 2001 From: Denrage Date: Tue, 20 Apr 2021 12:35:31 +0200 Subject: [PATCH 026/134] removed mods binding passthrough --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index b3aa4f0ba5..c308f14f74 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -41,9 +41,6 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable ruleset { get; set; } - [Resolved] - private IBindable> mods { get; set; } - [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } @@ -150,7 +147,7 @@ namespace osu.Game.Screens.Select removeOldInfo(); Add(Background = loaded); - Add(Info = new WedgeInfoText(beatmap, ruleset.Value, mods, beatmapDifficulty) + Add(Info = new WedgeInfoText(beatmap, ruleset.Value, beatmapDifficulty) { Shear = -Shear }); @@ -172,6 +169,9 @@ namespace osu.Game.Screens.Select public OsuSpriteText VersionLabel { get; private set; } public BeatmapSetOnlineStatusPill StatusPill { get; private set; } + [Resolved] + private IBindable> mods { get; set; } + private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; private FillFlowContainer infoLabelContainer; @@ -181,14 +181,12 @@ namespace osu.Game.Screens.Select private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; - private readonly IBindable> mods; private readonly IBindable starDifficulty; - public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IBindable> mods, IBindable difficulty) + public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IBindable difficulty) { this.beatmap = beatmap; ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset; - this.mods = mods; starDifficulty = difficulty; } @@ -409,7 +407,6 @@ namespace osu.Game.Screens.Select } }; - // this is currently not triggering when a mod gets (de)selected mods.BindValueChanged(mods => refreshModInformation(mods), true); } @@ -418,7 +415,7 @@ namespace osu.Game.Screens.Select settingChangeTracker?.Dispose(); settingChangeTracker = new ModSettingChangeTracker(modsChangedEvent.NewValue); settingChangeTracker.SettingChanged += _ => refreshBPMLabel(modsChangedEvent.NewValue); - refreshBPMLabel(mods.Value); + refreshBPMLabel(modsChangedEvent.NewValue); } private OsuSpriteText[] getMapper(BeatmapMetadata metadata) From f799a6e733e0d2075f7feafd9333cfaf5c604fad Mon Sep 17 00:00:00 2001 From: Denrage Date: Tue, 20 Apr 2021 14:18:41 +0200 Subject: [PATCH 027/134] Removed StarDifficulty binding passthrough --- .../Ranking/Expanded/StarRatingDisplay.cs | 42 +++++++---- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 69 ++++++++++--------- 2 files changed, 67 insertions(+), 44 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 081b782034..1aa8f5ca73 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -3,6 +3,7 @@ using System; using System.Globalization; +using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -24,11 +25,16 @@ namespace osu.Game.Screens.Ranking.Expanded /// public class StarRatingDisplay : CompositeDrawable { + [Resolved] + private OsuColour colours { get; set; } + private CircularContainer colorContainer; private OsuTextFlowContainer textContainer; + private CancellationTokenSource cancellationTokenSource; + private IBindable bindableStarDifficulty; private readonly StarDifficulty starDifficulty; - private readonly IBindable bindableStarDifficulty; + private readonly BeatmapInfo beatmapInfo; /// /// Creates a new using an already computed . @@ -40,17 +46,16 @@ namespace osu.Game.Screens.Ranking.Expanded } /// - /// Creates a new using a binded nullable . + /// Creates a new using a to use a bindable for the difficulty. /// - /// The binded nullable to display the star difficulty of. If null, a new instance of will be created - public StarRatingDisplay(IBindable starDifficulty) + /// The to use to create a bindable for + public StarRatingDisplay(BeatmapInfo beatmapInfo) { - bindableStarDifficulty = starDifficulty; + this.beatmapInfo = beatmapInfo; } - private void setDifficulty(OsuColour colours) + private void setDifficulty(StarDifficulty difficulty) { - var difficulty = bindableStarDifficulty == null ? starDifficulty : bindableStarDifficulty.Value ?? new StarDifficulty(); var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); string wholePart = starRatingParts[0]; string fractionPart = starRatingParts[1]; @@ -83,8 +88,17 @@ namespace osu.Game.Screens.Ranking.Expanded } [BackgroundDependencyLoader] - private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) + private void load(BeatmapDifficultyCache difficultyCache) { + if (beatmapInfo != null) + { + cancellationTokenSource?.Cancel(); + cancellationTokenSource = new CancellationTokenSource(); + + bindableStarDifficulty?.UnbindAll(); + bindableStarDifficulty = difficultyCache.GetBindableDifficulty(beatmapInfo, cancellationTokenSource.Token); + } + AutoSizeAxes = Axes.Both; InternalChildren = new Drawable[] @@ -130,11 +144,15 @@ namespace osu.Game.Screens.Ranking.Expanded }; if (bindableStarDifficulty != null) - { - bindableStarDifficulty.BindValueChanged(_ => setDifficulty(colours)); - } + bindableStarDifficulty.BindValueChanged(valueChanged => setDifficulty(valueChanged.NewValue ?? new StarDifficulty()), true); + else + setDifficulty(starDifficulty); + } - setDifficulty(colours); + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + cancellationTokenSource?.Cancel(); } } } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index c308f14f74..e3afd53210 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -41,11 +41,6 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable ruleset { get; set; } - [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } - - private IBindable beatmapDifficulty; - protected BufferedWedgeBackground Background; protected WedgeInfoText Info; @@ -87,8 +82,6 @@ namespace osu.Game.Screens.Select private WorkingBeatmap beatmap; - private CancellationTokenSource cancellationSource; - public WorkingBeatmap Beatmap { get => beatmap; @@ -97,12 +90,6 @@ namespace osu.Game.Screens.Select if (beatmap == value) return; beatmap = value; - cancellationSource?.Cancel(); - cancellationSource = new CancellationTokenSource(); - - beatmapDifficulty?.UnbindAll(); - beatmapDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo, cancellationSource.Token); - updateDisplay(); } } @@ -147,7 +134,7 @@ namespace osu.Game.Screens.Select removeOldInfo(); Add(Background = loaded); - Add(Info = new WedgeInfoText(beatmap, ruleset.Value, beatmapDifficulty) + Add(Info = new WedgeInfoText(beatmap, ruleset.Value) { Shear = -Shear }); @@ -158,7 +145,6 @@ namespace osu.Game.Screens.Select protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - cancellationSource?.Cancel(); } public class WedgeInfoText : Container @@ -178,24 +164,30 @@ namespace osu.Game.Screens.Select private Drawable starRatingDisplay; private Container bpmLabelContainer; private ModSettingChangeTracker settingChangeTracker; + private CancellationTokenSource cancellationTokenSource; + private IBindable starDifficulty; private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; - private readonly IBindable starDifficulty; - public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IBindable difficulty) + public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset) { this.beatmap = beatmap; ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset; - starDifficulty = difficulty; } [BackgroundDependencyLoader] - private void load(LocalisationManager localisation) + private void load(LocalisationManager localisation, BeatmapDifficultyCache difficultyCache) { var beatmapInfo = beatmap.BeatmapInfo; var metadata = beatmapInfo.Metadata ?? beatmap.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); + cancellationTokenSource?.Cancel(); + cancellationTokenSource = new CancellationTokenSource(); + + starDifficulty?.UnbindAll(); + starDifficulty = difficultyCache.GetBindableDifficulty(beatmapInfo, cancellationTokenSource.Token); + RelativeSizeAxes = Axes.Both; titleBinding = localisation.GetLocalisedString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); @@ -203,7 +195,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { - new DifficultyColourBar(starDifficulty) + new DifficultyColourBar(beatmapInfo) { RelativeSizeAxes = Axes.Y, Width = 20, @@ -239,7 +231,7 @@ namespace osu.Game.Screens.Select Shear = wedged_container_shear, Children = new[] { - starRatingDisplay = new StarRatingDisplay(starDifficulty) + starRatingDisplay = new StarRatingDisplay(beatmapInfo) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -313,13 +305,9 @@ namespace osu.Game.Screens.Select private void setStarRatingDisplayVisibility() { if (starDifficulty.Value.HasValue && starDifficulty.Value.Value.Stars > 0) - { starRatingDisplay.Show(); - } else - { starRatingDisplay.Hide(); - } } private InfoLabel[] getRulesetInfoLabels() @@ -440,21 +428,32 @@ namespace osu.Game.Screens.Select private class DifficultyColourBar : Container { + [Resolved] + private OsuColour colours { get; set; } + private Box solidDifficultyBox; private Box transparentDifficultyBox; + private CancellationTokenSource cancellationTokenSource; + private IBindable starDifficulty; - private readonly IBindable difficulty; + private readonly BeatmapInfo beatmapInfo; - public DifficultyColourBar(IBindable difficulty) + public DifficultyColourBar(BeatmapInfo beatmapInfo) { - this.difficulty = difficulty; + this.beatmapInfo = beatmapInfo; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(BeatmapDifficultyCache difficultyCache) { const float full_opacity_ratio = 0.7f; + cancellationTokenSource?.Cancel(); + cancellationTokenSource = new CancellationTokenSource(); + + starDifficulty?.UnbindAll(); + starDifficulty = difficultyCache.GetBindableDifficulty(beatmapInfo, cancellationTokenSource.Token); + Children = new Drawable[] { solidDifficultyBox = new Box @@ -472,16 +471,22 @@ namespace osu.Game.Screens.Select } }; - difficulty.BindValueChanged(_ => setColour(colours), true); + starDifficulty.BindValueChanged(valueChangedEvent => setColour(valueChangedEvent), true); } - private void setColour(OsuColour colours) + private void setColour(ValueChangedEvent valueChanged) { - var difficultyColour = colours.ForDifficultyRating(difficulty.Value?.DifficultyRating ?? (new StarDifficulty()).DifficultyRating); + var difficultyColour = colours.ForDifficultyRating(valueChanged.NewValue?.DifficultyRating ?? (new StarDifficulty()).DifficultyRating); solidDifficultyBox.Colour = difficultyColour; transparentDifficultyBox.Colour = difficultyColour; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + cancellationTokenSource?.Cancel(); + } } public class InfoLabel : Container, IHasTooltip From df29e61147fd45f0f310453c19393266d10609dd Mon Sep 17 00:00:00 2001 From: Denrage Date: Tue, 20 Apr 2021 14:22:49 +0200 Subject: [PATCH 028/134] Fix CodeFactor error --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index e3afd53210..44dbd5a5c6 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -299,7 +299,6 @@ namespace osu.Game.Screens.Select // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) StatusPill.Hide(); - } private void setStarRatingDisplayVisibility() From 583754b22a430dba73db9688d106dd7d734d6be4 Mon Sep 17 00:00:00 2001 From: Denrage Date: Tue, 20 Apr 2021 14:29:53 +0200 Subject: [PATCH 029/134] Removed unnecessary whitespaces --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 44dbd5a5c6..7cb6f2caf3 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -598,7 +598,7 @@ namespace osu.Game.Screens.Select }, }, }, - }; + }; } } } From e9571b72cf149a1941717bd1a1e9a22015feca20 Mon Sep 17 00:00:00 2001 From: Denrage Date: Tue, 20 Apr 2021 14:53:35 +0200 Subject: [PATCH 030/134] Fixed InspectCode --- osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs | 3 +-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 9 ++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 1aa8f5ca73..a3e9336648 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Globalization; using System.Threading; using osu.Framework.Allocation; @@ -46,7 +45,7 @@ namespace osu.Game.Screens.Ranking.Expanded } /// - /// Creates a new using a to use a bindable for the difficulty. + /// Creates a new using a to use a bindable for the difficulty. /// /// The to use to create a bindable for public StarRatingDisplay(BeatmapInfo beatmapInfo) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 7cb6f2caf3..9077c115d4 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -142,11 +142,6 @@ namespace osu.Game.Screens.Select } } - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - } - public class WedgeInfoText : Container { public FillFlowContainer MapperContainer { get; private set; } @@ -394,7 +389,7 @@ namespace osu.Game.Screens.Select } }; - mods.BindValueChanged(mods => refreshModInformation(mods), true); + mods.BindValueChanged(refreshModInformation, true); } private void refreshModInformation(ValueChangedEvent> modsChangedEvent) @@ -470,7 +465,7 @@ namespace osu.Game.Screens.Select } }; - starDifficulty.BindValueChanged(valueChangedEvent => setColour(valueChangedEvent), true); + starDifficulty.BindValueChanged(setColour, true); } private void setColour(ValueChangedEvent valueChanged) From de04caeace220426ed615efa6d3cabe4f76c88af Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 21 Apr 2021 13:53:08 +0200 Subject: [PATCH 031/134] Fixed race condition in StarRatingDisplay --- .../Ranking/Expanded/StarRatingDisplay.cs | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index a3e9336648..8367b1fc6d 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -28,9 +29,10 @@ namespace osu.Game.Screens.Ranking.Expanded private OsuColour colours { get; set; } private CircularContainer colorContainer; - private OsuTextFlowContainer textContainer; private CancellationTokenSource cancellationTokenSource; private IBindable bindableStarDifficulty; + private OsuSpriteText wholePartText; + private OsuSpriteText fractionPartText; private readonly StarDifficulty starDifficulty; private readonly BeatmapInfo beatmapInfo; @@ -66,24 +68,10 @@ namespace osu.Game.Screens.Ranking.Expanded colorContainer.Colour = backgroundColour; - textContainer.Text = string.Empty; + wholePartText.Text = $"{wholePart}"; + fractionPartText.Text = $"{separator}{fractionPart}"; - textContainer.With(t => - { - t.AddText($"{wholePart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); - - t.AddText($"{separator}{fractionPart}", s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); - }); + } [BackgroundDependencyLoader] @@ -130,14 +118,28 @@ namespace osu.Game.Screens.Ranking.Expanded Icon = FontAwesome.Solid.Star, Colour = Color4.Black }, - textContainer = new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, TextAnchor = Anchor.BottomLeft, - }, + }.With(t => + { + t.AddText(wholePartText = new OsuSpriteText(), s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size:14); + s.UseFullGlyphHeight = false; + }); + t.AddText(fractionPartText = new OsuSpriteText(), s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 7); + s.UseFullGlyphHeight = false; + }); + }), } } }; From 9fba87f67ace6c74bb452d8b8720a78dfc97b82c Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 21 Apr 2021 13:53:25 +0200 Subject: [PATCH 032/134] Moved Info and Background into own container --- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 8 ++- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 58 +++++++++++++------ 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 9c10c9751c..90bd4ceb88 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -135,15 +135,15 @@ namespace osu.Game.Tests.Visual.SongSelect private void selectBeatmap([CanBeNull] IBeatmap b) { - BeatmapInfoWedge.BufferedWedgeBackground backgroundBefore = null; + BeatmapInfoWedge.BeatmapInfoWedgeContainer containerBefore = null; AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () => { - backgroundBefore = infoWedge.Background; + containerBefore = infoWedge.Container; infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : CreateWorkingBeatmap(b); }); - AddUntilStep("wait for async load", () => infoWedge.Background != backgroundBefore); + AddUntilStep("wait for async load", () => infoWedge.Container != containerBefore); } private IBeatmap createTestBeatmap(RulesetInfo ruleset) @@ -196,6 +196,8 @@ namespace osu.Game.Tests.Visual.SongSelect public new BufferedWedgeBackground Background => base.Background; public new WedgeInfoText Info => base.Info; + + public new BeatmapInfoWedgeContainer Container => base.Container; } private class TestHitObject : ConvertHitObject, IHasPosition diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 9077c115d4..5bb7bbe9fd 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -41,8 +41,9 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable ruleset { get; set; } - protected BufferedWedgeBackground Background; - protected WedgeInfoText Info; + protected BeatmapInfoWedgeContainer Container; + protected WedgeInfoText Info => Container.Info; + protected BufferedWedgeBackground Background => Container.Background; public BeatmapInfoWedge() { @@ -94,9 +95,9 @@ namespace osu.Game.Screens.Select } } - public override bool IsPresent => base.IsPresent || Background == null; // Visibility is updated in the LoadComponentAsync callback + public override bool IsPresent => base.IsPresent || Container == null; // Visibility is updated in the LoadComponentAsync callback - private BufferedWedgeBackground loadingInfo; + private BeatmapInfoWedgeContainer loadingInfo; private void updateDisplay() { @@ -108,13 +109,9 @@ namespace osu.Game.Screens.Select { State.Value = beatmap == null ? Visibility.Hidden : Visibility.Visible; - Info?.FadeOut(250); - Info?.Expire(); - Info = null; - - Background?.FadeOut(250); - Background?.Expire(); - Background = null; + Container?.FadeOut(250); + Container?.Expire(); + Container = null; } if (beatmap == null) @@ -123,25 +120,50 @@ namespace osu.Game.Screens.Select return; } - LoadComponentAsync(loadingInfo = new BufferedWedgeBackground(beatmap) + LoadComponentAsync(loadingInfo = new BeatmapInfoWedgeContainer(beatmap, ruleset.Value) { Shear = -Shear, - Depth = Background?.Depth + 1 ?? 0 }, loaded => { // ensure we are the most recent loaded wedge. if (loaded != loadingInfo) return; removeOldInfo(); - Add(Background = loaded); - Add(Info = new WedgeInfoText(beatmap, ruleset.Value) - { - Shear = -Shear - }); + Add(Container = loaded); }); } } + public class BeatmapInfoWedgeContainer : Container + { + private readonly WorkingBeatmap beatmap; + private readonly RulesetInfo ruleset; + + internal BufferedWedgeBackground Background; + internal WedgeInfoText Info; + + public BeatmapInfoWedgeContainer(WorkingBeatmap beatmap, RulesetInfo ruleset) + { + this.beatmap = beatmap; + this.ruleset = ruleset; + } + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + Background = new BufferedWedgeBackground(beatmap) + { + Depth = Background?.Depth + 1 ?? 0, + }, + Info = new WedgeInfoText(beatmap, ruleset), + }; + } + } + public class WedgeInfoText : Container { public FillFlowContainer MapperContainer { get; private set; } From d6928e91fd1046373476a3ba3a53d16ce55563b4 Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 21 Apr 2021 14:02:09 +0200 Subject: [PATCH 033/134] Removed BeatmapInfo in StarRatingDisplay --- .../Ranking/Expanded/StarRatingDisplay.cs | 45 +++++-------------- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 14 +++--- 2 files changed, 20 insertions(+), 39 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 8367b1fc6d..ea4936bd82 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -29,13 +29,19 @@ namespace osu.Game.Screens.Ranking.Expanded private OsuColour colours { get; set; } private CircularContainer colorContainer; - private CancellationTokenSource cancellationTokenSource; - private IBindable bindableStarDifficulty; private OsuSpriteText wholePartText; private OsuSpriteText fractionPartText; + private StarDifficulty starDifficulty; - private readonly StarDifficulty starDifficulty; - private readonly BeatmapInfo beatmapInfo; + public StarDifficulty StarDifficulty + { + get => starDifficulty; + set + { + starDifficulty = value; + setDifficulty(starDifficulty); + } + } /// /// Creates a new using an already computed . @@ -46,15 +52,6 @@ namespace osu.Game.Screens.Ranking.Expanded this.starDifficulty = starDifficulty; } - /// - /// Creates a new using a to use a bindable for the difficulty. - /// - /// The to use to create a bindable for - public StarRatingDisplay(BeatmapInfo beatmapInfo) - { - this.beatmapInfo = beatmapInfo; - } - private void setDifficulty(StarDifficulty difficulty) { var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); @@ -71,21 +68,12 @@ namespace osu.Game.Screens.Ranking.Expanded wholePartText.Text = $"{wholePart}"; fractionPartText.Text = $"{separator}{fractionPart}"; - + } [BackgroundDependencyLoader] private void load(BeatmapDifficultyCache difficultyCache) { - if (beatmapInfo != null) - { - cancellationTokenSource?.Cancel(); - cancellationTokenSource = new CancellationTokenSource(); - - bindableStarDifficulty?.UnbindAll(); - bindableStarDifficulty = difficultyCache.GetBindableDifficulty(beatmapInfo, cancellationTokenSource.Token); - } - AutoSizeAxes = Axes.Both; InternalChildren = new Drawable[] @@ -144,16 +132,7 @@ namespace osu.Game.Screens.Ranking.Expanded } }; - if (bindableStarDifficulty != null) - bindableStarDifficulty.BindValueChanged(valueChanged => setDifficulty(valueChanged.NewValue ?? new StarDifficulty()), true); - else - setDifficulty(starDifficulty); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - cancellationTokenSource?.Cancel(); + setDifficulty(starDifficulty); } } } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 5bb7bbe9fd..7803b190e6 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -178,7 +178,7 @@ namespace osu.Game.Screens.Select private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; private FillFlowContainer infoLabelContainer; - private Drawable starRatingDisplay; + private StarRatingDisplay starRatingDisplay; private Container bpmLabelContainer; private ModSettingChangeTracker settingChangeTracker; private CancellationTokenSource cancellationTokenSource; @@ -246,9 +246,9 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Top = 14, Right = shear_width / 2 }, AutoSizeAxes = Axes.Both, Shear = wedged_container_shear, - Children = new[] + Children = new Drawable[] { - starRatingDisplay = new StarRatingDisplay(beatmapInfo) + starRatingDisplay = new StarRatingDisplay(starDifficulty.Value ?? new StarDifficulty()) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -311,19 +311,21 @@ namespace osu.Game.Screens.Select titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); - starDifficulty.BindValueChanged(_ => setStarRatingDisplayVisibility(), true); + starDifficulty.BindValueChanged(updateStarRatingDisplay, true); // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) StatusPill.Hide(); } - private void setStarRatingDisplayVisibility() + private void updateStarRatingDisplay(ValueChangedEvent valueChanged) { - if (starDifficulty.Value.HasValue && starDifficulty.Value.Value.Stars > 0) + if (valueChanged.NewValue.HasValue && valueChanged.NewValue.Value.Stars > 0) starRatingDisplay.Show(); else starRatingDisplay.Hide(); + + starRatingDisplay.StarDifficulty = valueChanged.NewValue ?? new StarDifficulty(); } private InfoLabel[] getRulesetInfoLabels() From 0dfd0bb59d731a46419f4840883ff433b88ce5d1 Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 21 Apr 2021 14:16:16 +0200 Subject: [PATCH 034/134] Refactored background of BeatmapInfoWedge --- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 2 - osu.Game/Screens/Select/BeatmapInfoWedge.cs | 57 +--------------- .../Select/BeatmapInfoWedgeBackground.cs | 66 +++++++++++++++++++ 3 files changed, 68 insertions(+), 57 deletions(-) create mode 100644 osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 90bd4ceb88..688cc9a035 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -193,8 +193,6 @@ namespace osu.Game.Tests.Visual.SongSelect private class TestBeatmapInfoWedge : BeatmapInfoWedge { - public new BufferedWedgeBackground Background => base.Background; - public new WedgeInfoText Info => base.Info; public new BeatmapInfoWedgeContainer Container => base.Container; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 7803b190e6..b499423412 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -11,7 +11,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Beatmaps; @@ -43,7 +42,6 @@ namespace osu.Game.Screens.Select protected BeatmapInfoWedgeContainer Container; protected WedgeInfoText Info => Container.Info; - protected BufferedWedgeBackground Background => Container.Background; public BeatmapInfoWedge() { @@ -123,6 +121,7 @@ namespace osu.Game.Screens.Select LoadComponentAsync(loadingInfo = new BeatmapInfoWedgeContainer(beatmap, ruleset.Value) { Shear = -Shear, + Depth = Container?.Depth + 1 ?? 0, }, loaded => { // ensure we are the most recent loaded wedge. @@ -139,7 +138,6 @@ namespace osu.Game.Screens.Select private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; - internal BufferedWedgeBackground Background; internal WedgeInfoText Info; public BeatmapInfoWedgeContainer(WorkingBeatmap beatmap, RulesetInfo ruleset) @@ -155,10 +153,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { - Background = new BufferedWedgeBackground(beatmap) - { - Depth = Background?.Depth + 1 ?? 0, - }, + new BeatmapInfoWedgeBackground(beatmap), Info = new WedgeInfoText(beatmap, ruleset), }; } @@ -572,53 +567,5 @@ namespace osu.Game.Screens.Select settingChangeTracker?.Dispose(); } } - - public class BufferedWedgeBackground : BufferedContainer - { - private readonly WorkingBeatmap beatmap; - - public BufferedWedgeBackground(WorkingBeatmap beatmap) - : base(pixelSnapping: true) - { - this.beatmap = beatmap; - } - - [BackgroundDependencyLoader] - private void load(LocalisationManager localisation) - { - CacheDrawnFrameBuffer = true; - RelativeSizeAxes = Axes.Both; - - Children = new Drawable[] - { - // We will create the white-to-black gradient by modulating transparency and having - // a black backdrop. This results in an sRGB-space gradient and not linear space, - // transitioning from white to black more perceptually uniformly. - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - // We use a container, such that we can set the colour gradient to go across the - // vertices of the masked container instead of the vertices of the (larger) sprite. - new Container - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.White, Color4.White.Opacity(0.3f)), - Children = new[] - { - // Zoomed-in and cropped beatmap background - new BeatmapBackgroundSprite(beatmap) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - }, - }, - }, - }; - } - } } } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs new file mode 100644 index 0000000000..566f49a799 --- /dev/null +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.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 osuTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Framework.Graphics.Shapes; + +namespace osu.Game.Screens.Select +{ + internal class BeatmapInfoWedgeBackground : CompositeDrawable + { + private readonly WorkingBeatmap beatmap; + + public BeatmapInfoWedgeBackground(WorkingBeatmap beatmap) + { + this.beatmap = beatmap; + } + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new BufferedContainer(pixelSnapping: true) + { + CacheDrawnFrameBuffer = true, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + // We will create the white-to-black gradient by modulating transparency and having + // a black backdrop. This results in an sRGB-space gradient and not linear space, + // transitioning from white to black more perceptually uniformly. + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + // We use a container, such that we can set the colour gradient to go across the + // vertices of the masked container instead of the vertices of the (larger) sprite. + new Container + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.White, Color4.White.Opacity(0.3f)), + Children = new[] + { + // Zoomed-in and cropped beatmap background + new BeatmapBackgroundSprite(beatmap) + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + }, + }, + }, + } + }; + } + } +} From 56a69ed95682e9096f2b8e4b518346b7a66b9308 Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 21 Apr 2021 15:53:28 +0200 Subject: [PATCH 035/134] Codestyle fixes --- osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index ea4936bd82..bfc336a677 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -2,9 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Globalization; -using System.Threading; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -67,8 +65,6 @@ namespace osu.Game.Screens.Ranking.Expanded wholePartText.Text = $"{wholePart}"; fractionPartText.Text = $"{separator}{fractionPart}"; - - } [BackgroundDependencyLoader] @@ -118,7 +114,7 @@ namespace osu.Game.Screens.Ranking.Expanded t.AddText(wholePartText = new OsuSpriteText(), s => { s.Colour = Color4.Black; - s.Font = s.Font.With(size:14); + s.Font = s.Font.With(size: 14); s.UseFullGlyphHeight = false; }); t.AddText(fractionPartText = new OsuSpriteText(), s => From 713344ebadc752b16c83bab92331af3c5850be25 Mon Sep 17 00:00:00 2001 From: Denrage Date: Fri, 23 Apr 2021 10:31:49 +0200 Subject: [PATCH 036/134] Reorganize methods --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 214 ++++++++++---------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index b499423412..cb5a276a5d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -323,6 +323,48 @@ namespace osu.Game.Screens.Select starRatingDisplay.StarDifficulty = valueChanged.NewValue ?? new StarDifficulty(); } + private void refreshModInformation(ValueChangedEvent> modsChangedEvent) + { + settingChangeTracker?.Dispose(); + settingChangeTracker = new ModSettingChangeTracker(modsChangedEvent.NewValue); + settingChangeTracker.SettingChanged += _ => refreshBPMLabel(modsChangedEvent.NewValue); + refreshBPMLabel(modsChangedEvent.NewValue); + } + + private void setMetadata(string source) + { + ArtistLabel.Text = artistBinding.Value; + TitleLabel.Text = string.IsNullOrEmpty(source) ? titleBinding.Value : source + " — " + titleBinding.Value; + } + + private void addInfoLabels() + { + if (beatmap.Beatmap?.HitObjects?.Any() != true) + return; + + infoLabelContainer.Children = new Drawable[] + { + new InfoLabel(new BeatmapStatistic + { + Name = "Length", + CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Length), + Content = TimeSpan.FromMilliseconds(beatmap.BeatmapInfo.Length).ToString(@"m\:ss"), + }), + bpmLabelContainer = new Container + { + AutoSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(20, 0), + Children = getRulesetInfoLabels() + } + }; + + mods.BindValueChanged(refreshModInformation, true); + } + private InfoLabel[] getRulesetInfoLabels() { try @@ -377,48 +419,6 @@ namespace osu.Game.Screens.Select }); } - private void setMetadata(string source) - { - ArtistLabel.Text = artistBinding.Value; - TitleLabel.Text = string.IsNullOrEmpty(source) ? titleBinding.Value : source + " — " + titleBinding.Value; - } - - private void addInfoLabels() - { - if (beatmap.Beatmap?.HitObjects?.Any() != true) - return; - - infoLabelContainer.Children = new Drawable[] - { - new InfoLabel(new BeatmapStatistic - { - Name = "Length", - CreateIcon = () => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Length), - Content = TimeSpan.FromMilliseconds(beatmap.BeatmapInfo.Length).ToString(@"m\:ss"), - }), - bpmLabelContainer = new Container - { - AutoSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(20, 0), - Children = getRulesetInfoLabels() - } - }; - - mods.BindValueChanged(refreshModInformation, true); - } - - private void refreshModInformation(ValueChangedEvent> modsChangedEvent) - { - settingChangeTracker?.Dispose(); - settingChangeTracker = new ModSettingChangeTracker(modsChangedEvent.NewValue); - settingChangeTracker.SettingChanged += _ => refreshBPMLabel(modsChangedEvent.NewValue); - refreshBPMLabel(modsChangedEvent.NewValue); - } - private OsuSpriteText[] getMapper(BeatmapMetadata metadata) { if (string.IsNullOrEmpty(metadata.Author?.Username)) @@ -439,6 +439,71 @@ namespace osu.Game.Screens.Select }; } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + settingChangeTracker?.Dispose(); + } + + public class InfoLabel : Container, IHasTooltip + { + public string TooltipText { get; } + + public InfoLabel(BeatmapStatistic statistic) + { + TooltipText = statistic.Name; + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(20), + Children = new[] + { + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"441288"), + Icon = FontAwesome.Solid.Square, + Rotation = 45, + }, + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"f7dd55"), + Icon = FontAwesome.Regular.Circle, + Size = new Vector2(0.8f) + }, + statistic.CreateIcon().With(i => + { + i.Anchor = Anchor.Centre; + i.Origin = Anchor.Centre; + i.RelativeSizeAxes = Axes.Both; + i.Colour = Color4Extensions.FromHex(@"f7dd55"); + i.Size = new Vector2(0.64f); + }), + } + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Colour = new Color4(255, 221, 85, 255), + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), + Margin = new MarginPadding { Left = 30 }, + Text = statistic.Content, + } + }; + } + } + private class DifficultyColourBar : Container { [Resolved] @@ -501,71 +566,6 @@ namespace osu.Game.Screens.Select cancellationTokenSource?.Cancel(); } } - - public class InfoLabel : Container, IHasTooltip - { - public string TooltipText { get; } - - public InfoLabel(BeatmapStatistic statistic) - { - TooltipText = statistic.Name; - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] - { - new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(20), - Children = new[] - { - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"441288"), - Icon = FontAwesome.Solid.Square, - Rotation = 45, - }, - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"f7dd55"), - Icon = FontAwesome.Regular.Circle, - Size = new Vector2(0.8f) - }, - statistic.CreateIcon().With(i => - { - i.Anchor = Anchor.Centre; - i.Origin = Anchor.Centre; - i.RelativeSizeAxes = Axes.Both; - i.Colour = Color4Extensions.FromHex(@"f7dd55"); - i.Size = new Vector2(0.64f); - }), - } - }, - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Colour = new Color4(255, 221, 85, 255), - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), - Margin = new MarginPadding { Left = 30 }, - Text = statistic.Content, - } - }; - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - settingChangeTracker?.Dispose(); - } } } } From 7e3a611f95cf9a1ec5503d692bc919c6dc6fb71c Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 24 Apr 2021 16:23:52 +0800 Subject: [PATCH 037/134] Add snap color option for osu!mania --- .../ManiaPlacementBlueprintTestScene.cs | 12 +++ .../ManiaSelectionBlueprintTestScene.cs | 12 +++ .../TestSceneHoldNotePlacementBlueprint.cs | 2 +- .../TestSceneHoldNoteSelectionBlueprint.cs | 2 +- .../Editor/TestSceneManiaHitObjectComposer.cs | 7 +- .../Editor/TestSceneNotePlacementBlueprint.cs | 2 +- .../Editor/TestSceneNoteSelectionBlueprint.cs | 2 +- .../ManiaInputTestScene.cs | 13 +++ .../Mods/TestSceneManiaModPerfect.cs | 4 +- .../Skinning/ManiaSkinnableTestScene.cs | 12 +++ .../Skinning/TestSceneHoldNote.cs | 2 +- .../Skinning/TestSceneNote.cs | 2 +- .../TestSceneAutoGeneration.cs | 24 +++--- .../TestSceneColumn.cs | 4 +- .../TestSceneHoldNoteInput.cs | 75 +++++++++--------- .../TestSceneNotes.cs | 17 +++- .../TestSceneOutOfOrderHits.cs | 10 +-- .../TestSceneStage.cs | 4 +- .../Beatmaps/ManiaBeatmapConverter.cs | 4 +- .../Legacy/DistanceObjectPatternGenerator.cs | 4 +- .../Legacy/EndTimeObjectPatternGenerator.cs | 4 +- .../Legacy/HitObjectPatternGenerator.cs | 2 +- .../ManiaRulesetConfigManager.cs | 4 +- .../Blueprints/HoldNotePlacementBlueprint.cs | 5 +- .../Edit/Blueprints/NotePlacementBlueprint.cs | 5 +- .../Edit/HoldNoteCompositionTool.cs | 7 +- .../Edit/ManiaHitObjectComposer.cs | 4 +- .../Edit/NoteCompositionTool.cs | 8 +- .../ManiaSettingsSubsection.cs | 5 ++ .../Mods/ManiaModInvert.cs | 2 +- .../Objects/Drawables/DrawableNote.cs | 30 +++++++ osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 11 ++- osu.Game.Rulesets.Mania/Objects/Note.cs | 79 +++++++++++++++++++ osu.Game.Rulesets.Mania/Objects/TailNote.cs | 5 ++ .../UI/DrawableManiaRuleset.cs | 5 ++ osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs | 11 +++ .../TestSceneManageCollectionsDialog.cs | 12 +-- 37 files changed, 314 insertions(+), 99 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index ece523e84c..8e94d6bbb6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -4,10 +4,12 @@ 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; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; @@ -28,6 +30,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Cached(typeof(IScrollingInfo))] private IScrollingInfo scrollingInfo; + [Cached] + protected readonly Bindable configColourCode = new Bindable(); + protected ManiaPlacementBlueprintTestScene() { scrollingInfo = ((ScrollingTestContainer)HitObjectContainer).ScrollingInfo; @@ -41,6 +46,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); + } + protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) { var time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position); diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 176fbba921..453f8e36e6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -2,8 +2,10 @@ // 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.Timing; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; using osuTK.Graphics; @@ -15,6 +17,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Cached(Type = typeof(IAdjustableClock))] private readonly IAdjustableClock clock = new StopwatchClock(); + [Cached] + protected readonly Bindable configColourCode = new Bindable(); + protected ManiaSelectionBlueprintTestScene() { Add(new Column(0) @@ -26,6 +31,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); + } + public ManiaPlayfield Playfield => null; } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs index 87c74a12cf..eb36e19048 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public class TestSceneHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHoldNote((HoldNote)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(); + protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(null); } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs index 24f4c6858e..9674985d09 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public TestSceneHoldNoteSelectionBlueprint() { - var holdNote = new HoldNote { Column = 0, Duration = 1000 }; + var holdNote = new HoldNote(null) { Column = 0, Duration = 1000 }; holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); base.Content.Child = content = new ScrollingTestContainer(ScrollingDirection.Down) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs index aaf96c63a6..1f3f4842c7 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs @@ -159,7 +159,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor AddStep("setup beatmap", () => { composer.EditorBeatmap.Clear(); - composer.EditorBeatmap.Add(new HoldNote + composer.EditorBeatmap.Add(new HoldNote(Beatmap.Value.Beatmap) { Column = 1, EndTime = 200 @@ -201,9 +201,10 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public TestComposer() { + var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 4 }); InternalChildren = new Drawable[] { - EditorBeatmap = new EditorBeatmap(new ManiaBeatmap(new StageDefinition { Columns = 4 })) + EditorBeatmap = new EditorBeatmap(beatmap) { BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo } }, @@ -211,7 +212,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }; for (int i = 0; i < 10; i++) - EditorBeatmap.Add(new Note { StartTime = 125 * i }); + EditorBeatmap.Add(new Note(beatmap) { StartTime = 125 * i }); } } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs index 36c34a8fb9..08a22ea28e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs @@ -55,6 +55,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor private Note getNote() => this.ChildrenOfType().FirstOrDefault()?.HitObject; protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableNote((Note)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint(); + protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint(null); } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs index 0e47a12a8e..caf89599be 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public TestSceneNoteSelectionBlueprint() { - var note = new Note { Column = 0 }; + var note = new Note(null) { Column = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); DrawableNote drawableObject; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index 9049bb3a82..ea7432f3a7 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -1,15 +1,21 @@ // 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.Framework.Input.Bindings; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { public abstract class ManiaInputTestScene : OsuTestScene { + [Cached] + protected readonly Bindable configColourCode = new Bindable(); private readonly Container content; protected override Container Content => content ?? base.Content; @@ -18,6 +24,13 @@ namespace osu.Game.Rulesets.Mania.Tests base.Content.Add(content = new LocalInputManager(keys)); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); + } + private class LocalInputManager : ManiaInputManager { public LocalInputManager(int variant) diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs index 2e3b21aed7..23d0e82439 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs @@ -19,10 +19,10 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods [TestCase(false)] [TestCase(true)] - public void TestNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Note { StartTime = 1000 }), shouldMiss); + public void TestNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Note(Beatmap.Value.Beatmap) { StartTime = 1000 }), shouldMiss); [TestCase(false)] [TestCase(true)] - public void TestHoldNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HoldNote { StartTime = 1000, EndTime = 3000 }), shouldMiss); + public void TestHoldNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HoldNote(Beatmap.Value.Beatmap) { StartTime = 1000, EndTime = 3000 }), shouldMiss); } } diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index 1d84a2dfcb..3b19386da6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -7,6 +7,8 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling.Algorithms; using osu.Game.Tests.Visual; @@ -24,6 +26,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning [Cached(Type = typeof(IScrollingInfo))] private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); + [Cached] + protected readonly Bindable configColourCode = new Bindable(); + protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset(); protected ManiaSkinnableTestScene() @@ -38,6 +43,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning }); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); + } + [Test] public void TestScrollingDown() { diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs index e88ff8e2ac..e13d0bbd7f 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning protected override DrawableManiaHitObject CreateHitObject() { - var note = new HoldNote { Duration = 1000 }; + var note = new HoldNote(Beatmap.Value.Beatmap) { Duration = 1000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new DrawableHoldNote(note); diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs index bc3bdf0bcb..eac288872a 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning { protected override DrawableManiaHitObject CreateHitObject() { - var note = new Note(); + var note = new Note(Beatmap.Value.Beatmap); note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new DrawableNote(note); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index cffec3dfd5..b2b9d607c6 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Tests // | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 }); - beatmap.HitObjects.Add(new Note { StartTime = 1000 }); + beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 1000 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Mania.Tests // | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 }); - beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); + beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -69,8 +69,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new Note { StartTime = 1000 }); - beatmap.HitObjects.Add(new Note { StartTime = 1000, Column = 1 }); + beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 1000 }); + beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 1000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -91,8 +91,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); - beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000, Column = 1 }); + beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000 }); + beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -114,8 +114,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new Note { StartTime = 1000 }); - beatmap.HitObjects.Add(new Note { StartTime = 2000, Column = 1 }); + beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 1000 }); + beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 2000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -141,8 +141,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); - beatmap.HitObjects.Add(new HoldNote { StartTime = 2000, Duration = 2000, Column = 1 }); + beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000 }); + beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 2000, Duration = 2000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -168,8 +168,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); - beatmap.HitObjects.Add(new Note { StartTime = 3000, Column = 1 }); + beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000 }); + beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 3000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs index d9b1ad22fa..59da73a540 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Mania.Tests { for (int i = 0; i < columns.Count; i++) { - var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; + var obj = new Note(null) { Column = i, StartTime = Time.Current + 2000 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); columns[i].Add(new DrawableNote(obj)); @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Tests { for (int i = 0; i < columns.Count; i++) { - var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; + var obj = new HoldNote(null) { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); columns[i].Add(new DrawableHoldNote(obj)); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 668487f673..c92fe03483 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -249,21 +249,6 @@ namespace osu.Game.Rulesets.Mania.Tests var beatmap = new Beatmap { - HitObjects = - { - new HoldNote - { - StartTime = 1000, - Duration = 500, - Column = 0, - }, - new HoldNote - { - StartTime = 1000 + 500 + windows.WindowFor(HitResult.Miss) + 10, - Duration = 500, - Column = 0, - }, - }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty @@ -274,6 +259,20 @@ namespace osu.Game.Rulesets.Mania.Tests Ruleset = new ManiaRuleset().RulesetInfo }, }; + beatmap.HitObjects = new List { + new HoldNote(beatmap) + { + StartTime = 1000, + Duration = 500, + Column = 0, + }, + new HoldNote(beatmap) + { + StartTime = 1000 + 500 + windows.WindowFor(HitResult.Miss) + 10, + Duration = 500, + Column = 0, + }, + }; performTest(new List { @@ -297,21 +296,21 @@ namespace osu.Game.Rulesets.Mania.Tests var beatmap = new Beatmap { - HitObjects = - { - new HoldNote - { - StartTime = time_head, - Duration = time_tail - time_head, - Column = 0, - } - }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty { SliderTickRate = tick_rate }, Ruleset = new ManiaRuleset().RulesetInfo }, }; + beatmap.HitObjects = new List + { + new HoldNote(beatmap) + { + StartTime = time_head, + Duration = time_tail - time_head, + Column = 0, + } + }; performTest(new List { @@ -329,17 +328,17 @@ namespace osu.Game.Rulesets.Mania.Tests { var beatmap = new Beatmap { - HitObjects = + BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }, + }; + beatmap.HitObjects = new List { - new HoldNote + new HoldNote(beatmap) { StartTime = 1000, Duration = 0, Column = 0, }, - }, - BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }, - }; + }; performTest(new List { @@ -374,21 +373,21 @@ namespace osu.Game.Rulesets.Mania.Tests { beatmap = new Beatmap { - HitObjects = - { - new HoldNote - { - StartTime = time_head, - Duration = time_tail - time_head, - Column = 0, - } - }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 4 }, Ruleset = new ManiaRuleset().RulesetInfo }, }; + beatmap.HitObjects = new List + { + new HoldNote(beatmap) + { + StartTime = time_head, + Duration = time_tail - time_head, + Column = 0, + } + }; beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f }); } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 706268e478..3660895347 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -15,8 +15,10 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI.Scrolling; @@ -29,6 +31,10 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestSceneNotes : OsuTestScene { + + [Cached] + protected readonly Bindable configColourCode = new Bindable(); + [Test] public void TestVariousNotes() { @@ -63,9 +69,16 @@ namespace osu.Game.Rulesets.Mania.Tests AddAssert("hold note 2 facing upwards", () => verifyAnchors(holdNote2, Anchor.y0)); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); + } + private Drawable createNoteDisplay(ScrollingDirection direction, int identifier, out DrawableNote hitObject) { - var note = new Note { StartTime = 0 }; + var note = new Note(null) { StartTime = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) @@ -80,7 +93,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createHoldNoteDisplay(ScrollingDirection direction, int identifier, out DrawableHoldNote hitObject) { - var note = new HoldNote { StartTime = 0, Duration = 5000 }; + var note = new HoldNote(null) { StartTime = 0, Duration = 5000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs index 18891f8c58..65195fdd3f 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Mania.Tests { double time = 1000 + i * 100; - objects.Add(new Note { StartTime = time }); + objects.Add(new Note(Beatmap.Value.Beatmap) { StartTime = time }); // don't hit the first note if (i > 0) @@ -60,12 +60,12 @@ namespace osu.Game.Rulesets.Mania.Tests { var objects = new List { - new HoldNote + new HoldNote(Beatmap.Value.Beatmap) { StartTime = 1000, EndTime = 1010, }, - new HoldNote + new HoldNote(Beatmap.Value.Beatmap) { StartTime = 1020, EndTime = 1030 @@ -83,12 +83,12 @@ namespace osu.Game.Rulesets.Mania.Tests { var objects = new List { - new HoldNote + new HoldNote(Beatmap.Value.Beatmap) { StartTime = 1000, EndTime = 1010, }, - new HoldNote + new HoldNote(Beatmap.Value.Beatmap) { StartTime = 1020, EndTime = 1030 diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 7376a90f17..777163cca7 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Tests { for (int i = 0; i < stage.Columns.Count; i++) { - var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; + var obj = new Note(null) { Column = i, StartTime = Time.Current + 2000 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); stage.Add(new DrawableNote(obj)); @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Tests { for (int i = 0; i < stage.Columns.Count; i++) { - var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; + var obj = new HoldNote(null) { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); stage.Add(new DrawableHoldNote(obj)); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 26393c8edb..5f03c93d55 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -247,7 +247,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps if (HitObject is IHasDuration endTimeData) { - pattern.Add(new HoldNote + pattern.Add(new HoldNote(Beatmap) { StartTime = HitObject.StartTime, Duration = endTimeData.Duration, @@ -258,7 +258,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps } else if (HitObject is IHasXPosition) { - pattern.Add(new Note + pattern.Add(new Note(Beatmap) { StartTime = HitObject.StartTime, Samples = HitObject.Samples, diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 26e5d381e2..a936878a38 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -512,7 +512,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (startTime == endTime) { - newObject = new Note + newObject = new Note(Beatmap) { StartTime = startTime, Samples = sampleInfoListAt(startTime), @@ -521,7 +521,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } else { - newObject = new HoldNote + newObject = new HoldNote(Beatmap) { StartTime = startTime, Duration = endTime - startTime, diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index f816a70ab3..9422146803 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (holdNote) { - newObject = new HoldNote + newObject = new HoldNote(Beatmap) { StartTime = HitObject.StartTime, Duration = endTime - HitObject.StartTime, @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } else { - newObject = new Note + newObject = new Note(Beatmap) { StartTime = HitObject.StartTime, Samples = HitObject.Samples, diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 54c37e9742..bbb4d4b466 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -441,7 +441,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// The column to add the note to. private void addToPattern(Pattern pattern, int column) { - pattern.Add(new Note + pattern.Add(new Note(Beatmap) { StartTime = HitObject.StartTime, Samples = HitObject.Samples, diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index 39d0f4bae4..292d494d88 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Mania.Configuration SetDefault(ManiaRulesetSetting.ScrollTime, 1500.0, DrawableManiaRuleset.MIN_TIME_RANGE, DrawableManiaRuleset.MAX_TIME_RANGE, 5); SetDefault(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); + SetDefault(ManiaRulesetSetting.ColourCode, ManiaColourCode.Off); } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings @@ -34,6 +35,7 @@ namespace osu.Game.Rulesets.Mania.Configuration public enum ManiaRulesetSetting { ScrollTime, - ScrollDirection + ScrollDirection, + ColourCode } } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 093a8da24f..b3902524a0 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; @@ -23,8 +24,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } - public HoldNotePlacementBlueprint() - : base(new HoldNote()) + public HoldNotePlacementBlueprint(IBeatmap beatmap) + : base(new HoldNote(beatmap)) { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index 3db89c8ae6..cc0ef5181a 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Input.Events; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; @@ -14,8 +15,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { private readonly EditNotePiece piece; - public NotePlacementBlueprint() - : base(new Note()) + public NotePlacementBlueprint(IBeatmap beatmap) + : base(new Note(beatmap)) { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs index a5f10ed436..696278de4d 100644 --- a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs @@ -5,19 +5,22 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Edit.Blueprints; namespace osu.Game.Rulesets.Mania.Edit { public class HoldNoteCompositionTool : HitObjectCompositionTool { - public HoldNoteCompositionTool() + private ManiaBeatmap Beatmap; + public HoldNoteCompositionTool(ManiaBeatmap beatmap) : base("Hold") { + Beatmap = beatmap; } public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Sliders); - public override PlacementBlueprint CreatePlacementBlueprint() => new HoldNotePlacementBlueprint(); + public override PlacementBlueprint CreatePlacementBlueprint() => new HoldNotePlacementBlueprint(Beatmap); } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index d9570bf8be..0defeb026d 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -93,8 +93,8 @@ namespace osu.Game.Rulesets.Mania.Edit protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] { - new NoteCompositionTool(), - new HoldNoteCompositionTool() + new NoteCompositionTool(drawableRuleset.Beatmap), + new HoldNoteCompositionTool(drawableRuleset.Beatmap) }; protected override void UpdateAfterChildren() diff --git a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs index 9f54152596..c77c3722c6 100644 --- a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; @@ -12,13 +13,16 @@ namespace osu.Game.Rulesets.Mania.Edit { public class NoteCompositionTool : HitObjectCompositionTool { - public NoteCompositionTool() + private ManiaBeatmap Beatmap; + + public NoteCompositionTool(ManiaBeatmap beatmap) : base(nameof(Note)) { + Beatmap = beatmap; } public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Circles); - public override PlacementBlueprint CreatePlacementBlueprint() => new NotePlacementBlueprint(); + public override PlacementBlueprint CreatePlacementBlueprint() => new NotePlacementBlueprint(Beatmap); } } diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index de77af8306..d46076d3bc 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -37,6 +37,11 @@ namespace osu.Game.Rulesets.Mania Current = config.GetBindable(ManiaRulesetSetting.ScrollTime), KeyboardStep = 5 }, + new SettingsEnumDropdown + { + LabelText = "Colour-coded notes", + Current = config.GetBindable(ManiaRulesetSetting.ColourCode), + } }; } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs index 1ea45c295c..11310c6642 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Mods // Decrease the duration by at most a 1/4 beat to ensure there's no instantaneous notes. duration = Math.Max(duration / 2, duration - beatLength / 4); - newColumnObjects.Add(new HoldNote + newColumnObjects.Add(new HoldNote(maniaBeatmap) { Column = column.Key, StartTime = locations[i].startTime, diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index b512986ccb..436e0923c4 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -2,12 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Skinning.Default; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Screens.Edit; using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Objects.Drawables @@ -17,6 +21,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public class DrawableNote : DrawableManiaHitObject, IKeyBindingHandler { + [Resolved] + private OsuColour colours { get; set; } + + [Resolved] + private Bindable configColourCode { get; set; } + protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note; private readonly Drawable headPiece; @@ -34,6 +44,26 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } + protected override void LoadComplete() + { + base.LoadComplete(); + + HitObject.SnapBindable.BindValueChanged(snap => UpdateSnapColour(configColourCode.Value, snap.NewValue), true); + configColourCode.BindValueChanged(colourCode => UpdateSnapColour(colourCode.NewValue, HitObject.Snap)); + } + + private void UpdateSnapColour(ManiaColourCode colourCode, int snap) + { + if (colourCode == ManiaColourCode.On) + { + Colour = BindableBeatDivisor.GetColourFor(HitObject.Snap, colours); + } + else + { + Colour = Colour4.White; + } + } + protected override void OnDirectionChanged(ValueChangedEvent e) { base.OnDirectionChanged(e); diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 6cc7ff92d3..bf0631170a 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class HoldNote : ManiaHitObject, IHasDuration { + public IBeatmap Beatmap; + public double EndTime { get => StartTime + Duration; @@ -84,6 +86,11 @@ namespace osu.Game.Rulesets.Mania.Objects /// private double tickSpacing = 50; + public HoldNote(IBeatmap beatmap) : base() + { + Beatmap = beatmap; + } + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -98,14 +105,14 @@ namespace osu.Game.Rulesets.Mania.Objects createTicks(cancellationToken); - AddNested(Head = new Note + AddNested(Head = new Note(Beatmap) { StartTime = StartTime, Column = Column, Samples = GetNodeSamples(0), }); - AddNested(Tail = new TailNote + AddNested(Tail = new TailNote(Beatmap) { StartTime = EndTime, Column = Column, diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 0035960c63..6ee0232c5b 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,6 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using osu.Framework.Bindables; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; @@ -12,5 +17,79 @@ namespace osu.Game.Rulesets.Mania.Objects public class Note : ManiaHitObject { public override Judgement CreateJudgement() => new ManiaJudgement(); + + private IBeatmap Beatmap; + + public readonly Bindable SnapBindable = new Bindable(); + + public int Snap + { + get => SnapBindable.Value; + set => SnapBindable.Value = value; + } + + public Note(IBeatmap beatmap) : base() + { + Beatmap = beatmap; + this.StartTimeBindable.BindValueChanged(_ => SnapToBeatmap(), true); + } + + private void SnapToBeatmap() + { + if (Beatmap != null) + { + TimingControlPoint currentTimingPoint = Beatmap.ControlPointInfo.TimingPointAt(StartTime); + int timeSignature = (int)currentTimingPoint.TimeSignature; + double startTime = currentTimingPoint.Time; + double secondsPerFourCounts = currentTimingPoint.BeatLength * 4; + + double offset = startTime % secondsPerFourCounts; + double snapResult = StartTime % secondsPerFourCounts - offset; + + if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 4.0)) + { + Snap = 1; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 8.0)) + { + Snap = 2; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 12.0)) + { + Snap = 3; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 16.0)) + { + Snap = 4; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 24.0)) + { + Snap = 6; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 32.0)) + { + Snap = 8; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 48.0)) + { + Snap = 12; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 64.0)) + { + Snap = 16; + } + else + { + Snap = 0; + } + } + } + + private const double LENIENCY_MS = 1.0; + private static bool AlmostDivisibleBy(double dividend, double divisor) + { + double remainder = Math.Abs(dividend) % divisor; + return Precision.AlmostEquals(remainder, 0, LENIENCY_MS) || Precision.AlmostEquals(remainder - divisor, 0, LENIENCY_MS); + } } } diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index 5a30fd6a12..bc56408691 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; @@ -8,6 +9,10 @@ namespace osu.Game.Rulesets.Mania.Objects { public class TailNote : Note { + public TailNote(IBeatmap beatmap) : base(beatmap) + { + } + public override Judgement CreateJudgement() => new ManiaJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 4ee060e91e..dc9c525cb0 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -51,6 +51,9 @@ namespace osu.Game.Rulesets.Mania.UI protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config; + [Cached] + protected readonly Bindable configColourCode = new Bindable(); + public ScrollVisualisationMethod ScrollMethod { get => scrollMethod; @@ -104,6 +107,8 @@ namespace osu.Game.Rulesets.Mania.UI configDirection.BindValueChanged(direction => Direction.Value = (ScrollingDirection)direction.NewValue, true); Config.BindWith(ManiaRulesetSetting.ScrollTime, configTimeRange); + + Config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); } protected override void AdjustScrollSpeed(int amount) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs b/osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs new file mode 100644 index 0000000000..91b637b71d --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs @@ -0,0 +1,11 @@ +// 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.Rulesets.Mania.UI +{ + public enum ManiaColourCode + { + Off, + On + } +} diff --git a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs index eca857f9e5..d8d419bceb 100644 --- a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs +++ b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs @@ -140,12 +140,12 @@ namespace osu.Game.Tests.Visual.Collections AddStep("add dropdown", () => { Add(new CollectionFilterDropdown - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.X, - Width = 0.4f, - } + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.X, + Width = 0.4f, + } ); }); AddStep("add two collections with same name", () => manager.Collections.AddRange(new[] From 59ae5ab913f74d75677576e10d3b3a9484a713a7 Mon Sep 17 00:00:00 2001 From: Denrage Date: Sat, 24 Apr 2021 13:25:29 +0200 Subject: [PATCH 038/134] Added transition in StarRatingDisplay --- .../Ranking/Expanded/StarRatingDisplay.cs | 112 +++++++++--------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index bfc336a677..748f58e430 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -27,9 +26,8 @@ namespace osu.Game.Screens.Ranking.Expanded private OsuColour colours { get; set; } private CircularContainer colorContainer; - private OsuSpriteText wholePartText; - private OsuSpriteText fractionPartText; private StarDifficulty starDifficulty; + private FillFlowContainer foregroundContainer; public StarDifficulty StarDifficulty { @@ -52,23 +50,15 @@ namespace osu.Game.Screens.Ranking.Expanded private void setDifficulty(StarDifficulty difficulty) { - var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); - string wholePart = starRatingParts[0]; - string fractionPart = starRatingParts[1]; - string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; + colorContainer.FadeColour(getDifficultyColour(difficulty), 250); - ColourInfo backgroundColour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); - - colorContainer.Colour = backgroundColour; - - wholePartText.Text = $"{wholePart}"; - fractionPartText.Text = $"{separator}{fractionPart}"; + foregroundContainer.Expire(); + foregroundContainer = null; + AddInternal(foregroundContainer = createForegroundContainer(difficulty)); } [BackgroundDependencyLoader] - private void load(BeatmapDifficultyCache difficultyCache) + private void load() { AutoSizeAxes = Axes.Both; @@ -78,6 +68,7 @@ namespace osu.Game.Screens.Ranking.Expanded { RelativeSizeAxes = Axes.Both, Masking = true, + Colour = getDifficultyColour(starDifficulty), Children = new Drawable[] { new Box @@ -86,49 +77,64 @@ namespace osu.Game.Screens.Ranking.Expanded }, } }, - new FillFlowContainer + foregroundContainer = createForegroundContainer(starDifficulty), + }; + } + + private ColourInfo getDifficultyColour(StarDifficulty difficulty) + { + return difficulty.DifficultyRating == DifficultyRating.ExpertPlus + ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) + : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); + } + + private FillFlowContainer createForegroundContainer(StarDifficulty difficulty) + { + var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); + string wholePart = starRatingParts[0]; + string fractionPart = starRatingParts[1]; + string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; + + return new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 8, Vertical = 4 }, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(2, 0), + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 8, Vertical = 4 }, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(2, 0), - Children = new Drawable[] + new SpriteIcon { - new SpriteIcon + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(7), + Icon = FontAwesome.Solid.Star, + Colour = Color4.Black + }, + new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + TextAnchor = Anchor.BottomLeft, + }.With(t => + { + t.AddText($"{wholePart}", s => { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(7), - Icon = FontAwesome.Solid.Star, - Colour = Color4.Black - }, - new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 14); + s.UseFullGlyphHeight = false; + }); + t.AddText($"{separator}{fractionPart}", s => { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - TextAnchor = Anchor.BottomLeft, - }.With(t => - { - t.AddText(wholePartText = new OsuSpriteText(), s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); - t.AddText(fractionPartText = new OsuSpriteText(), s => - { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); - }), - } + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 7); + s.UseFullGlyphHeight = false; + }); + }), } }; - - setDifficulty(starDifficulty); } } } From f9905ebe68352f19f6fafa981369da2a4a4faeba Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 24 Apr 2021 19:30:16 +0800 Subject: [PATCH 039/134] Remove beatmap argument in Note --- .../ManiaPlacementBlueprintTestScene.cs | 12 --- .../ManiaSelectionBlueprintTestScene.cs | 12 --- .../TestSceneHoldNotePlacementBlueprint.cs | 2 +- .../TestSceneHoldNoteSelectionBlueprint.cs | 2 +- .../Editor/TestSceneManiaHitObjectComposer.cs | 7 +- .../Editor/TestSceneNotePlacementBlueprint.cs | 2 +- .../Editor/TestSceneNoteSelectionBlueprint.cs | 2 +- .../ManiaInputTestScene.cs | 13 ---- .../Mods/TestSceneManiaModPerfect.cs | 4 +- .../Skinning/ManiaSkinnableTestScene.cs | 12 --- .../Skinning/TestSceneHoldNote.cs | 2 +- .../Skinning/TestSceneNote.cs | 2 +- .../TestSceneAutoGeneration.cs | 24 +++--- .../TestSceneColumn.cs | 4 +- .../TestSceneHoldNoteInput.cs | 75 ++++++++++--------- .../TestSceneNotes.cs | 17 +---- .../TestSceneOutOfOrderHits.cs | 10 +-- .../TestSceneStage.cs | 4 +- .../Beatmaps/ManiaBeatmapConverter.cs | 4 +- .../Legacy/DistanceObjectPatternGenerator.cs | 4 +- .../Legacy/EndTimeObjectPatternGenerator.cs | 4 +- .../Legacy/HitObjectPatternGenerator.cs | 2 +- .../Blueprints/HoldNotePlacementBlueprint.cs | 5 +- .../Edit/Blueprints/NotePlacementBlueprint.cs | 5 +- .../Edit/HoldNoteCompositionTool.cs | 7 +- .../Edit/ManiaHitObjectComposer.cs | 4 +- .../Edit/NoteCompositionTool.cs | 8 +- .../Mods/ManiaModInvert.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 11 +-- osu.Game.Rulesets.Mania/Objects/Note.cs | 3 +- osu.Game.Rulesets.Mania/Objects/TailNote.cs | 5 -- .../TestSceneManageCollectionsDialog.cs | 12 +-- 32 files changed, 99 insertions(+), 183 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index 8e94d6bbb6..ece523e84c 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -4,12 +4,10 @@ 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; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; @@ -30,9 +28,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Cached(typeof(IScrollingInfo))] private IScrollingInfo scrollingInfo; - [Cached] - protected readonly Bindable configColourCode = new Bindable(); - protected ManiaPlacementBlueprintTestScene() { scrollingInfo = ((ScrollingTestContainer)HitObjectContainer).ScrollingInfo; @@ -46,13 +41,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); - } - protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) { var time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position); diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 453f8e36e6..176fbba921 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -2,10 +2,8 @@ // 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.Timing; -using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; using osuTK.Graphics; @@ -17,9 +15,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Cached(Type = typeof(IAdjustableClock))] private readonly IAdjustableClock clock = new StopwatchClock(); - [Cached] - protected readonly Bindable configColourCode = new Bindable(); - protected ManiaSelectionBlueprintTestScene() { Add(new Column(0) @@ -31,13 +26,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); - } - public ManiaPlayfield Playfield => null; } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs index eb36e19048..87c74a12cf 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public class TestSceneHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestScene { protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHoldNote((HoldNote)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(null); + protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs index 9674985d09..24f4c6858e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public TestSceneHoldNoteSelectionBlueprint() { - var holdNote = new HoldNote(null) { Column = 0, Duration = 1000 }; + var holdNote = new HoldNote { Column = 0, Duration = 1000 }; holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); base.Content.Child = content = new ScrollingTestContainer(ScrollingDirection.Down) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs index 1f3f4842c7..aaf96c63a6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs @@ -159,7 +159,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor AddStep("setup beatmap", () => { composer.EditorBeatmap.Clear(); - composer.EditorBeatmap.Add(new HoldNote(Beatmap.Value.Beatmap) + composer.EditorBeatmap.Add(new HoldNote { Column = 1, EndTime = 200 @@ -201,10 +201,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public TestComposer() { - var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 4 }); InternalChildren = new Drawable[] { - EditorBeatmap = new EditorBeatmap(beatmap) + EditorBeatmap = new EditorBeatmap(new ManiaBeatmap(new StageDefinition { Columns = 4 })) { BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo } }, @@ -212,7 +211,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }; for (int i = 0; i < 10; i++) - EditorBeatmap.Add(new Note(beatmap) { StartTime = 125 * i }); + EditorBeatmap.Add(new Note { StartTime = 125 * i }); } } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs index 08a22ea28e..36c34a8fb9 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs @@ -55,6 +55,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor private Note getNote() => this.ChildrenOfType().FirstOrDefault()?.HitObject; protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableNote((Note)hitObject); - protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint(null); + protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs index caf89599be..0e47a12a8e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public TestSceneNoteSelectionBlueprint() { - var note = new Note(null) { Column = 0 }; + var note = new Note { Column = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); DrawableNote drawableObject; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index ea7432f3a7..9049bb3a82 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -1,21 +1,15 @@ // 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.Framework.Input.Bindings; -using osu.Game.Rulesets.Mania.Configuration; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { public abstract class ManiaInputTestScene : OsuTestScene { - [Cached] - protected readonly Bindable configColourCode = new Bindable(); private readonly Container content; protected override Container Content => content ?? base.Content; @@ -24,13 +18,6 @@ namespace osu.Game.Rulesets.Mania.Tests base.Content.Add(content = new LocalInputManager(keys)); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); - } - private class LocalInputManager : ManiaInputManager { public LocalInputManager(int variant) diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs index 23d0e82439..2e3b21aed7 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs @@ -19,10 +19,10 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods [TestCase(false)] [TestCase(true)] - public void TestNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Note(Beatmap.Value.Beatmap) { StartTime = 1000 }), shouldMiss); + public void TestNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Note { StartTime = 1000 }), shouldMiss); [TestCase(false)] [TestCase(true)] - public void TestHoldNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HoldNote(Beatmap.Value.Beatmap) { StartTime = 1000, EndTime = 3000 }), shouldMiss); + public void TestHoldNote(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new HoldNote { StartTime = 1000, EndTime = 3000 }), shouldMiss); } } diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index 3b19386da6..1d84a2dfcb 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -7,8 +7,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Mania.Configuration; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling.Algorithms; using osu.Game.Tests.Visual; @@ -26,9 +24,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning [Cached(Type = typeof(IScrollingInfo))] private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); - [Cached] - protected readonly Bindable configColourCode = new Bindable(); - protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset(); protected ManiaSkinnableTestScene() @@ -43,13 +38,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning }); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); - } - [Test] public void TestScrollingDown() { diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs index e13d0bbd7f..e88ff8e2ac 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning protected override DrawableManiaHitObject CreateHitObject() { - var note = new HoldNote(Beatmap.Value.Beatmap) { Duration = 1000 }; + var note = new HoldNote { Duration = 1000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new DrawableHoldNote(note); diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs index eac288872a..bc3bdf0bcb 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning { protected override DrawableManiaHitObject CreateHitObject() { - var note = new Note(Beatmap.Value.Beatmap); + var note = new Note(); note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new DrawableNote(note); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index b2b9d607c6..cffec3dfd5 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Tests // | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 }); - beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 1000 }); + beatmap.HitObjects.Add(new Note { StartTime = 1000 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Mania.Tests // | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 }); - beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000 }); + beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -69,8 +69,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 1000 }); - beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 1000, Column = 1 }); + beatmap.HitObjects.Add(new Note { StartTime = 1000 }); + beatmap.HitObjects.Add(new Note { StartTime = 1000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -91,8 +91,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000 }); - beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000, Column = 1 }); + beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); + beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -114,8 +114,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 1000 }); - beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 2000, Column = 1 }); + beatmap.HitObjects.Add(new Note { StartTime = 1000 }); + beatmap.HitObjects.Add(new Note { StartTime = 2000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -141,8 +141,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000 }); - beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 2000, Duration = 2000, Column = 1 }); + beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); + beatmap.HitObjects.Add(new HoldNote { StartTime = 2000, Duration = 2000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); @@ -168,8 +168,8 @@ namespace osu.Game.Rulesets.Mania.Tests // | | | var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 2 }); - beatmap.HitObjects.Add(new HoldNote(beatmap) { StartTime = 1000, Duration = 2000 }); - beatmap.HitObjects.Add(new Note(beatmap) { StartTime = 3000, Column = 1 }); + beatmap.HitObjects.Add(new HoldNote { StartTime = 1000, Duration = 2000 }); + beatmap.HitObjects.Add(new Note { StartTime = 3000, Column = 1 }); var generated = new ManiaAutoGenerator(beatmap).Generate(); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs index 59da73a540..d9b1ad22fa 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Mania.Tests { for (int i = 0; i < columns.Count; i++) { - var obj = new Note(null) { Column = i, StartTime = Time.Current + 2000 }; + var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); columns[i].Add(new DrawableNote(obj)); @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Tests { for (int i = 0; i < columns.Count; i++) { - var obj = new HoldNote(null) { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; + var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); columns[i].Add(new DrawableHoldNote(obj)); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index c92fe03483..668487f673 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -249,6 +249,21 @@ namespace osu.Game.Rulesets.Mania.Tests var beatmap = new Beatmap { + HitObjects = + { + new HoldNote + { + StartTime = 1000, + Duration = 500, + Column = 0, + }, + new HoldNote + { + StartTime = 1000 + 500 + windows.WindowFor(HitResult.Miss) + 10, + Duration = 500, + Column = 0, + }, + }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty @@ -259,20 +274,6 @@ namespace osu.Game.Rulesets.Mania.Tests Ruleset = new ManiaRuleset().RulesetInfo }, }; - beatmap.HitObjects = new List { - new HoldNote(beatmap) - { - StartTime = 1000, - Duration = 500, - Column = 0, - }, - new HoldNote(beatmap) - { - StartTime = 1000 + 500 + windows.WindowFor(HitResult.Miss) + 10, - Duration = 500, - Column = 0, - }, - }; performTest(new List { @@ -296,21 +297,21 @@ namespace osu.Game.Rulesets.Mania.Tests var beatmap = new Beatmap { + HitObjects = + { + new HoldNote + { + StartTime = time_head, + Duration = time_tail - time_head, + Column = 0, + } + }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty { SliderTickRate = tick_rate }, Ruleset = new ManiaRuleset().RulesetInfo }, }; - beatmap.HitObjects = new List - { - new HoldNote(beatmap) - { - StartTime = time_head, - Duration = time_tail - time_head, - Column = 0, - } - }; performTest(new List { @@ -328,17 +329,17 @@ namespace osu.Game.Rulesets.Mania.Tests { var beatmap = new Beatmap { - BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }, - }; - beatmap.HitObjects = new List + HitObjects = { - new HoldNote(beatmap) + new HoldNote { StartTime = 1000, Duration = 0, Column = 0, }, - }; + }, + BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }, + }; performTest(new List { @@ -373,21 +374,21 @@ namespace osu.Game.Rulesets.Mania.Tests { beatmap = new Beatmap { + HitObjects = + { + new HoldNote + { + StartTime = time_head, + Duration = time_tail - time_head, + Column = 0, + } + }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 4 }, Ruleset = new ManiaRuleset().RulesetInfo }, }; - beatmap.HitObjects = new List - { - new HoldNote(beatmap) - { - StartTime = time_head, - Duration = time_tail - time_head, - Column = 0, - } - }; beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f }); } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 3660895347..706268e478 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -15,10 +15,8 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI.Scrolling; @@ -31,10 +29,6 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestSceneNotes : OsuTestScene { - - [Cached] - protected readonly Bindable configColourCode = new Bindable(); - [Test] public void TestVariousNotes() { @@ -69,16 +63,9 @@ namespace osu.Game.Rulesets.Mania.Tests AddAssert("hold note 2 facing upwards", () => verifyAnchors(holdNote2, Anchor.y0)); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); - } - private Drawable createNoteDisplay(ScrollingDirection direction, int identifier, out DrawableNote hitObject) { - var note = new Note(null) { StartTime = 0 }; + var note = new Note { StartTime = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) @@ -93,7 +80,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createHoldNoteDisplay(ScrollingDirection direction, int identifier, out DrawableHoldNote hitObject) { - var note = new HoldNote(null) { StartTime = 0, Duration = 5000 }; + var note = new HoldNote { StartTime = 0, Duration = 5000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs index 65195fdd3f..18891f8c58 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Mania.Tests { double time = 1000 + i * 100; - objects.Add(new Note(Beatmap.Value.Beatmap) { StartTime = time }); + objects.Add(new Note { StartTime = time }); // don't hit the first note if (i > 0) @@ -60,12 +60,12 @@ namespace osu.Game.Rulesets.Mania.Tests { var objects = new List { - new HoldNote(Beatmap.Value.Beatmap) + new HoldNote { StartTime = 1000, EndTime = 1010, }, - new HoldNote(Beatmap.Value.Beatmap) + new HoldNote { StartTime = 1020, EndTime = 1030 @@ -83,12 +83,12 @@ namespace osu.Game.Rulesets.Mania.Tests { var objects = new List { - new HoldNote(Beatmap.Value.Beatmap) + new HoldNote { StartTime = 1000, EndTime = 1010, }, - new HoldNote(Beatmap.Value.Beatmap) + new HoldNote { StartTime = 1020, EndTime = 1030 diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 777163cca7..7376a90f17 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Tests { for (int i = 0; i < stage.Columns.Count; i++) { - var obj = new Note(null) { Column = i, StartTime = Time.Current + 2000 }; + var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); stage.Add(new DrawableNote(obj)); @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Tests { for (int i = 0; i < stage.Columns.Count; i++) { - var obj = new HoldNote(null) { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; + var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); stage.Add(new DrawableHoldNote(obj)); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 5f03c93d55..26393c8edb 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -247,7 +247,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps if (HitObject is IHasDuration endTimeData) { - pattern.Add(new HoldNote(Beatmap) + pattern.Add(new HoldNote { StartTime = HitObject.StartTime, Duration = endTimeData.Duration, @@ -258,7 +258,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps } else if (HitObject is IHasXPosition) { - pattern.Add(new Note(Beatmap) + pattern.Add(new Note { StartTime = HitObject.StartTime, Samples = HitObject.Samples, diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index a936878a38..26e5d381e2 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -512,7 +512,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (startTime == endTime) { - newObject = new Note(Beatmap) + newObject = new Note { StartTime = startTime, Samples = sampleInfoListAt(startTime), @@ -521,7 +521,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } else { - newObject = new HoldNote(Beatmap) + newObject = new HoldNote { StartTime = startTime, Duration = endTime - startTime, diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 9422146803..f816a70ab3 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (holdNote) { - newObject = new HoldNote(Beatmap) + newObject = new HoldNote { StartTime = HitObject.StartTime, Duration = endTime - HitObject.StartTime, @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } else { - newObject = new Note(Beatmap) + newObject = new Note { StartTime = HitObject.StartTime, Samples = HitObject.Samples, diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index bbb4d4b466..54c37e9742 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -441,7 +441,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// The column to add the note to. private void addToPattern(Pattern pattern, int column) { - pattern.Add(new Note(Beatmap) + pattern.Add(new Note { StartTime = HitObject.StartTime, Samples = HitObject.Samples, diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index b3902524a0..093a8da24f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -5,7 +5,6 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; @@ -24,8 +23,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } - public HoldNotePlacementBlueprint(IBeatmap beatmap) - : base(new HoldNote(beatmap)) + public HoldNotePlacementBlueprint() + : base(new HoldNote()) { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index cc0ef5181a..3db89c8ae6 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using osu.Framework.Input.Events; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; @@ -15,8 +14,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { private readonly EditNotePiece piece; - public NotePlacementBlueprint(IBeatmap beatmap) - : base(new Note(beatmap)) + public NotePlacementBlueprint() + : base(new Note()) { RelativeSizeAxes = Axes.Both; diff --git a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs index 696278de4d..a5f10ed436 100644 --- a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs @@ -5,22 +5,19 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; -using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Edit.Blueprints; namespace osu.Game.Rulesets.Mania.Edit { public class HoldNoteCompositionTool : HitObjectCompositionTool { - private ManiaBeatmap Beatmap; - public HoldNoteCompositionTool(ManiaBeatmap beatmap) + public HoldNoteCompositionTool() : base("Hold") { - Beatmap = beatmap; } public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Sliders); - public override PlacementBlueprint CreatePlacementBlueprint() => new HoldNotePlacementBlueprint(Beatmap); + public override PlacementBlueprint CreatePlacementBlueprint() => new HoldNotePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 0defeb026d..d9570bf8be 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -93,8 +93,8 @@ namespace osu.Game.Rulesets.Mania.Edit protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] { - new NoteCompositionTool(drawableRuleset.Beatmap), - new HoldNoteCompositionTool(drawableRuleset.Beatmap) + new NoteCompositionTool(), + new HoldNoteCompositionTool() }; protected override void UpdateAfterChildren() diff --git a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs index c77c3722c6..9f54152596 100644 --- a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; -using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; @@ -13,16 +12,13 @@ namespace osu.Game.Rulesets.Mania.Edit { public class NoteCompositionTool : HitObjectCompositionTool { - private ManiaBeatmap Beatmap; - - public NoteCompositionTool(ManiaBeatmap beatmap) + public NoteCompositionTool() : base(nameof(Note)) { - Beatmap = beatmap; } public override Drawable CreateIcon() => new BeatmapStatisticIcon(BeatmapStatisticsIconType.Circles); - public override PlacementBlueprint CreatePlacementBlueprint() => new NotePlacementBlueprint(Beatmap); + public override PlacementBlueprint CreatePlacementBlueprint() => new NotePlacementBlueprint(); } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs index 11310c6642..1ea45c295c 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Mods // Decrease the duration by at most a 1/4 beat to ensure there's no instantaneous notes. duration = Math.Max(duration / 2, duration - beatLength / 4); - newColumnObjects.Add(new HoldNote(maniaBeatmap) + newColumnObjects.Add(new HoldNote { Column = column.Key, StartTime = locations[i].startTime, diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index bf0631170a..6cc7ff92d3 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class HoldNote : ManiaHitObject, IHasDuration { - public IBeatmap Beatmap; - public double EndTime { get => StartTime + Duration; @@ -86,11 +84,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// private double tickSpacing = 50; - public HoldNote(IBeatmap beatmap) : base() - { - Beatmap = beatmap; - } - protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -105,14 +98,14 @@ namespace osu.Game.Rulesets.Mania.Objects createTicks(cancellationToken); - AddNested(Head = new Note(Beatmap) + AddNested(Head = new Note { StartTime = StartTime, Column = Column, Samples = GetNodeSamples(0), }); - AddNested(Tail = new TailNote(Beatmap) + AddNested(Tail = new TailNote { StartTime = EndTime, Column = Column, diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 6ee0232c5b..36f32c78af 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -28,9 +28,8 @@ namespace osu.Game.Rulesets.Mania.Objects set => SnapBindable.Value = value; } - public Note(IBeatmap beatmap) : base() + public Note() { - Beatmap = beatmap; this.StartTimeBindable.BindValueChanged(_ => SnapToBeatmap(), true); } diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index bc56408691..5a30fd6a12 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; @@ -9,10 +8,6 @@ namespace osu.Game.Rulesets.Mania.Objects { public class TailNote : Note { - public TailNote(IBeatmap beatmap) : base(beatmap) - { - } - public override Judgement CreateJudgement() => new ManiaJudgement(); } } diff --git a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs index d8d419bceb..eca857f9e5 100644 --- a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs +++ b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs @@ -140,12 +140,12 @@ namespace osu.Game.Tests.Visual.Collections AddStep("add dropdown", () => { Add(new CollectionFilterDropdown - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.X, - Width = 0.4f, - } + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.X, + Width = 0.4f, + } ); }); AddStep("add two collections with same name", () => manager.Collections.AddRange(new[] From d6d81fb8e5a55db4f58aa4cc41d729f3e0ec3f27 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 24 Apr 2021 19:53:21 +0800 Subject: [PATCH 040/134] Move color snap logic from Note to DrawableNote --- .../Objects/Drawables/DrawableNote.cs | 102 +++++++++++++++--- osu.Game.Rulesets.Mania/Objects/Note.cs | 78 -------------- .../UI/DrawableManiaRuleset.cs | 5 + 3 files changed, 93 insertions(+), 92 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 436e0923c4..3b2a9feee2 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,12 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Framework.Utils; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; @@ -27,10 +31,21 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables [Resolved] private Bindable configColourCode { get; set; } + [Resolved(canBeNull: true)] + private ManiaBeatmap beatmap { get; set; } + protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note; private readonly Drawable headPiece; + public readonly Bindable SnapBindable = new Bindable(); + + public int Snap + { + get => SnapBindable.Value; + set => SnapBindable.Value = value; + } + public DrawableNote(Note hitObject) : base(hitObject) { @@ -48,20 +63,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { base.LoadComplete(); - HitObject.SnapBindable.BindValueChanged(snap => UpdateSnapColour(configColourCode.Value, snap.NewValue), true); - configColourCode.BindValueChanged(colourCode => UpdateSnapColour(colourCode.NewValue, HitObject.Snap)); - } + HitObject.StartTimeBindable.BindValueChanged(_ => SnapToBeatmap(), true); - private void UpdateSnapColour(ManiaColourCode colourCode, int snap) - { - if (colourCode == ManiaColourCode.On) - { - Colour = BindableBeatDivisor.GetColourFor(HitObject.Snap, colours); - } - else - { - Colour = Colour4.White; - } + SnapBindable.BindValueChanged(snap => UpdateSnapColour(configColourCode.Value, snap.NewValue), true); + configColourCode.BindValueChanged(colourCode => UpdateSnapColour(colourCode.NewValue, Snap)); } protected override void OnDirectionChanged(ValueChangedEvent e) @@ -103,5 +108,74 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public virtual void OnReleased(ManiaAction action) { } + private void SnapToBeatmap() + { + if (beatmap != null) + { + TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(HitObject.StartTime); + int timeSignature = (int)currentTimingPoint.TimeSignature; + double startTime = currentTimingPoint.Time; + double secondsPerFourCounts = currentTimingPoint.BeatLength * 4; + + double offset = startTime % secondsPerFourCounts; + double snapResult = HitObject.StartTime % secondsPerFourCounts - offset; + + if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 4.0)) + { + Snap = 1; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 8.0)) + { + Snap = 2; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 12.0)) + { + Snap = 3; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 16.0)) + { + Snap = 4; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 24.0)) + { + Snap = 6; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 32.0)) + { + Snap = 8; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 48.0)) + { + Snap = 12; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 64.0)) + { + Snap = 16; + } + else + { + Snap = 0; + } + } + } + + private const double LENIENCY_MS = 1.0; + private static bool AlmostDivisibleBy(double dividend, double divisor) + { + double remainder = Math.Abs(dividend) % divisor; + return Precision.AlmostEquals(remainder, 0, LENIENCY_MS) || Precision.AlmostEquals(remainder - divisor, 0, LENIENCY_MS); + } + + private void UpdateSnapColour(ManiaColourCode colourCode, int snap) + { + if (colourCode == ManiaColourCode.On) + { + Colour = BindableBeatDivisor.GetColourFor(Snap, colours); + } + else + { + Colour = Colour4.White; + } + } } -} +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 36f32c78af..0035960c63 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,11 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using osu.Framework.Bindables; -using osu.Framework.Utils; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; @@ -17,78 +12,5 @@ namespace osu.Game.Rulesets.Mania.Objects public class Note : ManiaHitObject { public override Judgement CreateJudgement() => new ManiaJudgement(); - - private IBeatmap Beatmap; - - public readonly Bindable SnapBindable = new Bindable(); - - public int Snap - { - get => SnapBindable.Value; - set => SnapBindable.Value = value; - } - - public Note() - { - this.StartTimeBindable.BindValueChanged(_ => SnapToBeatmap(), true); - } - - private void SnapToBeatmap() - { - if (Beatmap != null) - { - TimingControlPoint currentTimingPoint = Beatmap.ControlPointInfo.TimingPointAt(StartTime); - int timeSignature = (int)currentTimingPoint.TimeSignature; - double startTime = currentTimingPoint.Time; - double secondsPerFourCounts = currentTimingPoint.BeatLength * 4; - - double offset = startTime % secondsPerFourCounts; - double snapResult = StartTime % secondsPerFourCounts - offset; - - if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 4.0)) - { - Snap = 1; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 8.0)) - { - Snap = 2; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 12.0)) - { - Snap = 3; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 16.0)) - { - Snap = 4; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 24.0)) - { - Snap = 6; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 32.0)) - { - Snap = 8; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 48.0)) - { - Snap = 12; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 64.0)) - { - Snap = 16; - } - else - { - Snap = 0; - } - } - } - - private const double LENIENCY_MS = 1.0; - private static bool AlmostDivisibleBy(double dividend, double divisor) - { - double remainder = Math.Abs(dividend) % divisor; - return Precision.AlmostEquals(remainder, 0, LENIENCY_MS) || Precision.AlmostEquals(remainder - divisor, 0, LENIENCY_MS); - } } } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index dc9c525cb0..850d4800cd 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -45,6 +45,9 @@ namespace osu.Game.Rulesets.Mania.UI public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap; + [Cached(typeof(ManiaBeatmap))] + private ManiaBeatmap CachedBeatmap { get; } + public IEnumerable BarLines; protected override bool RelativeScaleBeatLengths => true; @@ -80,6 +83,8 @@ namespace osu.Game.Rulesets.Mania.UI : base(ruleset, beatmap, mods) { BarLines = new BarLineGenerator(Beatmap).BarLines; + + CachedBeatmap = Beatmap; } [BackgroundDependencyLoader] From a8b401522bf561d5a2d49567ec99a2048e56586a Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 24 Apr 2021 20:39:22 +0800 Subject: [PATCH 041/134] Remove ManiaColourCode in favor for boolean --- .../Configuration/ManiaRulesetConfigManager.cs | 2 +- osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs | 4 ++-- .../Objects/Drawables/DrawableNote.cs | 6 +++--- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs | 11 ----------- 5 files changed, 7 insertions(+), 18 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index 292d494d88..f37937a736 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Configuration SetDefault(ManiaRulesetSetting.ScrollTime, 1500.0, DrawableManiaRuleset.MIN_TIME_RANGE, DrawableManiaRuleset.MAX_TIME_RANGE, 5); SetDefault(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); - SetDefault(ManiaRulesetSetting.ColourCode, ManiaColourCode.Off); + SetDefault(ManiaRulesetSetting.ColourCode, false); } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index d46076d3bc..c0c587f67c 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -37,10 +37,10 @@ namespace osu.Game.Rulesets.Mania Current = config.GetBindable(ManiaRulesetSetting.ScrollTime), KeyboardStep = 5 }, - new SettingsEnumDropdown + new SettingsCheckbox { LabelText = "Colour-coded notes", - Current = config.GetBindable(ManiaRulesetSetting.ColourCode), + Current = config.GetBindable(ManiaRulesetSetting.ColourCode), } }; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 3b2a9feee2..7cda70f2af 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private OsuColour colours { get; set; } [Resolved] - private Bindable configColourCode { get; set; } + private Bindable configColourCode { get; set; } [Resolved(canBeNull: true)] private ManiaBeatmap beatmap { get; set; } @@ -166,9 +166,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return Precision.AlmostEquals(remainder, 0, LENIENCY_MS) || Precision.AlmostEquals(remainder - divisor, 0, LENIENCY_MS); } - private void UpdateSnapColour(ManiaColourCode colourCode, int snap) + private void UpdateSnapColour(bool colourCode, int snap) { - if (colourCode == ManiaColourCode.On) + if (colourCode) { Colour = BindableBeatDivisor.GetColourFor(Snap, colours); } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 850d4800cd..94830adc33 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.UI protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config; [Cached] - protected readonly Bindable configColourCode = new Bindable(); + protected readonly Bindable configColourCode = new Bindable(); public ScrollVisualisationMethod ScrollMethod { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs b/osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs deleted file mode 100644 index 91b637b71d..0000000000 --- a/osu.Game.Rulesets.Mania/UI/ManiaColourCode.cs +++ /dev/null @@ -1,11 +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.Rulesets.Mania.UI -{ - public enum ManiaColourCode - { - Off, - On - } -} From 91bf0d422d88fe519834cbe01771a20cc5a379d8 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 24 Apr 2021 20:40:30 +0800 Subject: [PATCH 042/134] Rename ColourCode to ColourCodedNotes --- .../Configuration/ManiaRulesetConfigManager.cs | 4 ++-- osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index f37937a736..87a4689689 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Configuration SetDefault(ManiaRulesetSetting.ScrollTime, 1500.0, DrawableManiaRuleset.MIN_TIME_RANGE, DrawableManiaRuleset.MAX_TIME_RANGE, 5); SetDefault(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); - SetDefault(ManiaRulesetSetting.ColourCode, false); + SetDefault(ManiaRulesetSetting.ColourCodedNotes, false); } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings @@ -36,6 +36,6 @@ namespace osu.Game.Rulesets.Mania.Configuration { ScrollTime, ScrollDirection, - ColourCode + ColourCodedNotes } } diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index c0c587f67c..552c793096 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Mania new SettingsCheckbox { LabelText = "Colour-coded notes", - Current = config.GetBindable(ManiaRulesetSetting.ColourCode), + Current = config.GetBindable(ManiaRulesetSetting.ColourCodedNotes), } }; } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 94830adc33..60e9613b71 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.Mania.UI Config.BindWith(ManiaRulesetSetting.ScrollTime, configTimeRange); - Config.BindWith(ManiaRulesetSetting.ColourCode, configColourCode); + Config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCode); } protected override void AdjustScrollSpeed(int amount) From 3103fd8343efa3d811605ffae382da0734097dd2 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 24 Apr 2021 20:54:05 +0800 Subject: [PATCH 043/134] Move snapping logic into SnapFinder --- .../Objects/Drawables/DrawableNote.cs | 68 +---------------- .../UI/DrawableManiaRuleset.cs | 7 +- osu.Game.Rulesets.Mania/Utils/SnapFinder.cs | 75 +++++++++++++++++++ 3 files changed, 83 insertions(+), 67 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Utils/SnapFinder.cs diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 7cda70f2af..998d9e625e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -7,12 +7,9 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; -using osu.Framework.Utils; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Skinning.Default; -using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mania.Utils; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; @@ -31,8 +28,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables [Resolved] private Bindable configColourCode { get; set; } - [Resolved(canBeNull: true)] - private ManiaBeatmap beatmap { get; set; } + [Resolved] + private SnapFinder snapFinder { get; set; } protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note; @@ -63,7 +60,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { base.LoadComplete(); - HitObject.StartTimeBindable.BindValueChanged(_ => SnapToBeatmap(), true); + HitObject.StartTimeBindable.BindValueChanged(_ => Snap = snapFinder.FindSnap(HitObject), true); SnapBindable.BindValueChanged(snap => UpdateSnapColour(configColourCode.Value, snap.NewValue), true); configColourCode.BindValueChanged(colourCode => UpdateSnapColour(colourCode.NewValue, Snap)); @@ -108,63 +105,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public virtual void OnReleased(ManiaAction action) { } - private void SnapToBeatmap() - { - if (beatmap != null) - { - TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(HitObject.StartTime); - int timeSignature = (int)currentTimingPoint.TimeSignature; - double startTime = currentTimingPoint.Time; - double secondsPerFourCounts = currentTimingPoint.BeatLength * 4; - - double offset = startTime % secondsPerFourCounts; - double snapResult = HitObject.StartTime % secondsPerFourCounts - offset; - - if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 4.0)) - { - Snap = 1; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 8.0)) - { - Snap = 2; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 12.0)) - { - Snap = 3; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 16.0)) - { - Snap = 4; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 24.0)) - { - Snap = 6; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 32.0)) - { - Snap = 8; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 48.0)) - { - Snap = 12; - } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 64.0)) - { - Snap = 16; - } - else - { - Snap = 0; - } - } - } - - private const double LENIENCY_MS = 1.0; - private static bool AlmostDivisibleBy(double dividend, double divisor) - { - double remainder = Math.Abs(dividend) % divisor; - return Precision.AlmostEquals(remainder, 0, LENIENCY_MS) || Precision.AlmostEquals(remainder - divisor, 0, LENIENCY_MS); - } private void UpdateSnapColour(bool colourCode, int snap) { diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 60e9613b71..99fb32f81f 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -20,6 +20,7 @@ using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Rulesets.Mania.Utils; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -45,8 +46,8 @@ namespace osu.Game.Rulesets.Mania.UI public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap; - [Cached(typeof(ManiaBeatmap))] - private ManiaBeatmap CachedBeatmap { get; } + [Cached] + private SnapFinder snapFinder { get; set; } public IEnumerable BarLines; @@ -84,7 +85,7 @@ namespace osu.Game.Rulesets.Mania.UI { BarLines = new BarLineGenerator(Beatmap).BarLines; - CachedBeatmap = Beatmap; + snapFinder = new SnapFinder(Beatmap); } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs b/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs new file mode 100644 index 0000000000..01a9339552 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Utils; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Mania.Utils +{ + public class SnapFinder + { + private ManiaBeatmap beatmap; + public SnapFinder(ManiaBeatmap beatmap) + { + this.beatmap = beatmap; + } + + public int FindSnap(HitObject hitObject) + { + TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); + int timeSignature = (int)currentTimingPoint.TimeSignature; + double startTime = currentTimingPoint.Time; + double secondsPerFourCounts = currentTimingPoint.BeatLength * 4; + + double offset = startTime % secondsPerFourCounts; + double snapResult = hitObject.StartTime % secondsPerFourCounts - offset; + + if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 4.0)) + { + return 1; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 8.0)) + { + return 2; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 12.0)) + { + return 3; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 16.0)) + { + return 4; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 24.0)) + { + return 6; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 32.0)) + { + return 8; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 48.0)) + { + return 12; + } + else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 64.0)) + { + return 16; + } + else + { + return 0; + } + } + + private const double LENIENCY_MS = 1.0; + private static bool AlmostDivisibleBy(double dividend, double divisor) + { + double remainder = Math.Abs(dividend) % divisor; + return Precision.AlmostEquals(remainder, 0, LENIENCY_MS) || Precision.AlmostEquals(remainder - divisor, 0, LENIENCY_MS); + } + } +} From 8b01082cbb3c257bd69ba6fb95cd173bce79f854 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 24 Apr 2021 21:07:17 +0800 Subject: [PATCH 044/134] Fix visual tests missing dependency for ColourCodedNotes --- .../Editor/ManiaPlacementBlueprintTestScene.cs | 12 ++++++++++++ .../Editor/ManiaSelectionBlueprintTestScene.cs | 12 ++++++++++++ .../ManiaInputTestScene.cs | 13 +++++++++++++ .../Skinning/ManiaSkinnableTestScene.cs | 11 +++++++++++ osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs | 11 +++++++++++ .../Objects/Drawables/DrawableNote.cs | 13 ++++++++----- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 4 ++-- 7 files changed, 69 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index ece523e84c..8a605a7ca3 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -4,10 +4,12 @@ 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; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; @@ -28,6 +30,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Cached(typeof(IScrollingInfo))] private IScrollingInfo scrollingInfo; + [Cached] + protected readonly Bindable configColourCodedNotes = new Bindable(); + protected ManiaPlacementBlueprintTestScene() { scrollingInfo = ((ScrollingTestContainer)HitObjectContainer).ScrollingInfo; @@ -41,6 +46,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + } + protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) { var time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position); diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 176fbba921..854d0fb14e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -2,8 +2,10 @@ // 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.Timing; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; using osuTK.Graphics; @@ -15,6 +17,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Cached(Type = typeof(IAdjustableClock))] private readonly IAdjustableClock clock = new StopwatchClock(); + [Cached] + protected readonly Bindable configColourCodedNotes = new Bindable(); + protected ManiaSelectionBlueprintTestScene() { Add(new Column(0) @@ -26,6 +31,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + } + public ManiaPlayfield Playfield => null; } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index 9049bb3a82..f54d90016c 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -1,9 +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.Framework.Input.Bindings; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests @@ -13,11 +16,21 @@ namespace osu.Game.Rulesets.Mania.Tests private readonly Container content; protected override Container Content => content ?? base.Content; + [Cached] + protected readonly Bindable configColourCodedNotes = new Bindable(); + protected ManiaInputTestScene(int keys) { base.Content.Add(content = new LocalInputManager(keys)); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + } + private class LocalInputManager : ManiaInputManager { public LocalInputManager(int variant) diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index 1d84a2dfcb..05f07bad12 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling.Algorithms; using osu.Game.Tests.Visual; @@ -24,6 +25,9 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning [Cached(Type = typeof(IScrollingInfo))] private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); + [Cached] + protected readonly Bindable configColourCodedNotes = new Bindable(); + protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset(); protected ManiaSkinnableTestScene() @@ -38,6 +42,13 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning }); } + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + } + [Test] public void TestScrollingDown() { diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 706268e478..9828db7687 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -15,6 +15,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; @@ -29,6 +30,16 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestSceneNotes : OsuTestScene { + [Cached] + protected readonly Bindable configColourCodedNotes = new Bindable(); + + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + } + [Test] public void TestVariousNotes() { diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 998d9e625e..cfae01f5f2 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -26,9 +26,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private OsuColour colours { get; set; } [Resolved] - private Bindable configColourCode { get; set; } + private Bindable configColourCodedNotes { get; set; } - [Resolved] + [Resolved(canBeNull: true)] private SnapFinder snapFinder { get; set; } protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note; @@ -60,10 +60,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { base.LoadComplete(); - HitObject.StartTimeBindable.BindValueChanged(_ => Snap = snapFinder.FindSnap(HitObject), true); + if (snapFinder != null) + { + HitObject.StartTimeBindable.BindValueChanged(_ => Snap = snapFinder.FindSnap(HitObject), true); - SnapBindable.BindValueChanged(snap => UpdateSnapColour(configColourCode.Value, snap.NewValue), true); - configColourCode.BindValueChanged(colourCode => UpdateSnapColour(colourCode.NewValue, Snap)); + SnapBindable.BindValueChanged(snap => UpdateSnapColour(configColourCodedNotes.Value, snap.NewValue), true); + configColourCodedNotes.BindValueChanged(colourCode => UpdateSnapColour(colourCode.NewValue, Snap)); + } } protected override void OnDirectionChanged(ValueChangedEvent e) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 99fb32f81f..818d6429e4 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.UI protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config; [Cached] - protected readonly Bindable configColourCode = new Bindable(); + protected readonly Bindable configColourCodedNotes = new Bindable(); public ScrollVisualisationMethod ScrollMethod { @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.UI Config.BindWith(ManiaRulesetSetting.ScrollTime, configTimeRange); - Config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCode); + Config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); } protected override void AdjustScrollSpeed(int amount) From bedabc1ddf673aa94d7a38414cb0c710a4f9d4bb Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 24 Apr 2021 22:12:07 +0800 Subject: [PATCH 045/134] Fix cake errors --- .../ManiaPlacementBlueprintTestScene.cs | 4 +-- .../ManiaSelectionBlueprintTestScene.cs | 4 +-- .../ManiaInputTestScene.cs | 4 +-- .../Skinning/ManiaSkinnableTestScene.cs | 4 +-- .../TestSceneNotes.cs | 4 +-- .../Objects/Drawables/DrawableNote.cs | 7 +++-- .../UI/DrawableManiaRuleset.cs | 4 +-- osu.Game.Rulesets.Mania/Utils/SnapFinder.cs | 27 ++++++++++--------- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index 8a605a7ca3..c04b875245 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor private IScrollingInfo scrollingInfo; [Cached] - protected readonly Bindable configColourCodedNotes = new Bindable(); + protected readonly Bindable ConfigColourCodedNotes = new Bindable(); protected ManiaPlacementBlueprintTestScene() { @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor private void load(RulesetConfigCache configCache) { var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); } protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 854d0fb14e..1c11dc397e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor private readonly IAdjustableClock clock = new StopwatchClock(); [Cached] - protected readonly Bindable configColourCodedNotes = new Bindable(); + protected readonly Bindable ConfigColourCodedNotes = new Bindable(); protected ManiaSelectionBlueprintTestScene() { @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor private void load(RulesetConfigCache configCache) { var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); } public ManiaPlayfield Playfield => null; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index f54d90016c..2b2db8aa96 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Tests protected override Container Content => content ?? base.Content; [Cached] - protected readonly Bindable configColourCodedNotes = new Bindable(); + protected readonly Bindable ConfigColourCodedNotes = new Bindable(); protected ManiaInputTestScene(int keys) { @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.Tests private void load(RulesetConfigCache configCache) { var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); } private class LocalInputManager : ManiaInputManager diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index 05f07bad12..941d01a1d6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); [Cached] - protected readonly Bindable configColourCodedNotes = new Bindable(); + protected readonly Bindable ConfigColourCodedNotes = new Bindable(); protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset(); @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning private void load(RulesetConfigCache configCache) { var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); } [Test] diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 9828db7687..1d053688a2 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -31,13 +31,13 @@ namespace osu.Game.Rulesets.Mania.Tests public class TestSceneNotes : OsuTestScene { [Cached] - protected readonly Bindable configColourCodedNotes = new Bindable(); + protected readonly Bindable ConfigColourCodedNotes = new Bindable(); [BackgroundDependencyLoader] private void load(RulesetConfigCache configCache) { var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); } [Test] diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index cfae01f5f2..04c4b06c88 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -64,8 +63,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { HitObject.StartTimeBindable.BindValueChanged(_ => Snap = snapFinder.FindSnap(HitObject), true); - SnapBindable.BindValueChanged(snap => UpdateSnapColour(configColourCodedNotes.Value, snap.NewValue), true); - configColourCodedNotes.BindValueChanged(colourCode => UpdateSnapColour(colourCode.NewValue, Snap)); + SnapBindable.BindValueChanged(snap => updateSnapColour(configColourCodedNotes.Value, snap.NewValue), true); + configColourCodedNotes.BindValueChanged(colourCode => updateSnapColour(colourCode.NewValue, Snap)); } } @@ -109,7 +108,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { } - private void UpdateSnapColour(bool colourCode, int snap) + private void updateSnapColour(bool colourCode, int snap) { if (colourCode) { diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 818d6429e4..17535c9bc9 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.UI protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config; [Cached] - protected readonly Bindable configColourCodedNotes = new Bindable(); + protected readonly Bindable ConfigColourCodedNotes = new Bindable(); public ScrollVisualisationMethod ScrollMethod { @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.UI Config.BindWith(ManiaRulesetSetting.ScrollTime, configTimeRange); - Config.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + Config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); } protected override void AdjustScrollSpeed(int amount) diff --git a/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs b/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs index 01a9339552..83df0eb756 100644 --- a/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs +++ b/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs @@ -11,7 +11,8 @@ namespace osu.Game.Rulesets.Mania.Utils { public class SnapFinder { - private ManiaBeatmap beatmap; + private readonly ManiaBeatmap beatmap; + public SnapFinder(ManiaBeatmap beatmap) { this.beatmap = beatmap; @@ -20,42 +21,41 @@ namespace osu.Game.Rulesets.Mania.Utils public int FindSnap(HitObject hitObject) { TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); - int timeSignature = (int)currentTimingPoint.TimeSignature; double startTime = currentTimingPoint.Time; double secondsPerFourCounts = currentTimingPoint.BeatLength * 4; double offset = startTime % secondsPerFourCounts; double snapResult = hitObject.StartTime % secondsPerFourCounts - offset; - if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 4.0)) + if (almostDivisibleBy(snapResult, secondsPerFourCounts / 4.0)) { return 1; } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 8.0)) + else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 8.0)) { return 2; } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 12.0)) + else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 12.0)) { return 3; } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 16.0)) + else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 16.0)) { return 4; } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 24.0)) + else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 24.0)) { return 6; } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 32.0)) + else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 32.0)) { return 8; } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 48.0)) + else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 48.0)) { return 12; } - else if (AlmostDivisibleBy(snapResult, secondsPerFourCounts / 64.0)) + else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 64.0)) { return 16; } @@ -65,11 +65,12 @@ namespace osu.Game.Rulesets.Mania.Utils } } - private const double LENIENCY_MS = 1.0; - private static bool AlmostDivisibleBy(double dividend, double divisor) + private const double leniency_ms = 1.0; + + private static bool almostDivisibleBy(double dividend, double divisor) { double remainder = Math.Abs(dividend) % divisor; - return Precision.AlmostEquals(remainder, 0, LENIENCY_MS) || Precision.AlmostEquals(remainder - divisor, 0, LENIENCY_MS); + return Precision.AlmostEquals(remainder, 0, leniency_ms) || Precision.AlmostEquals(remainder - divisor, 0, leniency_ms); } } } From 46c44c576d2c27218da69f4493d61ebffd8ab895 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 18 Apr 2021 19:16:20 -0700 Subject: [PATCH 046/134] Fix beatmap info download button content not scaling on mouse down --- .../Buttons/HeaderDownloadButton.cs | 66 ++++++++----------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index cffff86a64..6d27342049 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -47,52 +47,44 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { FillFlowContainer textSprites; - AddRangeInternal(new Drawable[] + AddInternal(shakeContainer = new ShakeContainer { - shakeContainer = new ShakeContainer + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 5, + Child = button = new HeaderButton { RelativeSizeAxes = Axes.Both }, + }); + + button.AddRange(new Drawable[] + { + new Container { - Depth = -1, + Padding = new MarginPadding { Horizontal = 10 }, RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 5, Children = new Drawable[] { - button = new HeaderButton { RelativeSizeAxes = Axes.Both }, - new Container + textSprites = new FillFlowContainer { - // cannot nest inside here due to the structure of button (putting things in its own content). - // requires framework fix. - Padding = new MarginPadding { Horizontal = 10 }, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - textSprites = new FillFlowContainer - { - Depth = -1, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - AutoSizeDuration = 500, - AutoSizeEasing = Easing.OutQuint, - Direction = FillDirection.Vertical, - }, - new SpriteIcon - { - Depth = -1, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Icon = FontAwesome.Solid.Download, - Size = new Vector2(18), - }, - } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + AutoSizeDuration = 500, + AutoSizeEasing = Easing.OutQuint, + Direction = FillDirection.Vertical, }, - new DownloadProgressBar(BeatmapSet.Value) + new SpriteIcon { - Depth = -2, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Icon = FontAwesome.Solid.Download, + Size = new Vector2(18), }, - }, + } + }, + new DownloadProgressBar(BeatmapSet.Value) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, }, }); From c9967f7b7486d5744aba911a144110811b76ef04 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 24 Apr 2021 08:37:37 -0700 Subject: [PATCH 047/134] Fix button being recreated on importing state --- osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index a61640a02e..85ed3f8767 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -268,11 +268,13 @@ namespace osu.Game.Overlays.BeatmapSet break; case DownloadState.Downloading: - case DownloadState.Importing: // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); break; + case DownloadState.Importing: + break; + default: downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); if (BeatmapSet.Value.OnlineInfo.HasVideo) From eaac4fe6c7b76bfef30d37bd7f15b6eb8d0cdccc Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sun, 25 Apr 2021 06:38:15 +0800 Subject: [PATCH 048/134] Simplify FindSnap method --- osu.Game.Rulesets.Mania/Utils/SnapFinder.cs | 49 ++++----------------- 1 file changed, 9 insertions(+), 40 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs b/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs index 83df0eb756..ed3bd4af05 100644 --- a/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs +++ b/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs @@ -18,51 +18,20 @@ namespace osu.Game.Rulesets.Mania.Utils this.beatmap = beatmap; } + private readonly static int[] snaps = { 1, 2, 3, 4, 6, 8, 12, 16 }; + public int FindSnap(HitObject hitObject) { TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); - double startTime = currentTimingPoint.Time; - double secondsPerFourCounts = currentTimingPoint.BeatLength * 4; + double snapResult = (hitObject.StartTime - currentTimingPoint.Time) % (currentTimingPoint.BeatLength * 4); - double offset = startTime % secondsPerFourCounts; - double snapResult = hitObject.StartTime % secondsPerFourCounts - offset; + foreach (var snap in snaps) + { + if (almostDivisibleBy(snapResult, currentTimingPoint.BeatLength / (double)snap)) + return snap; + } - if (almostDivisibleBy(snapResult, secondsPerFourCounts / 4.0)) - { - return 1; - } - else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 8.0)) - { - return 2; - } - else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 12.0)) - { - return 3; - } - else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 16.0)) - { - return 4; - } - else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 24.0)) - { - return 6; - } - else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 32.0)) - { - return 8; - } - else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 48.0)) - { - return 12; - } - else if (almostDivisibleBy(snapResult, secondsPerFourCounts / 64.0)) - { - return 16; - } - else - { - return 0; - } + return 0; } private const double leniency_ms = 1.0; From e0ca44c908754b2766ac5dccce2d4d93ae2dacb0 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sun, 25 Apr 2021 07:34:17 +0800 Subject: [PATCH 049/134] Move SnapFinder from mania ruleset to osu.Game --- .../Objects/Drawables/DrawableNote.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 -- .../Utils => osu.Game/Rulesets/Objects}/SnapFinder.cs | 9 ++++----- 3 files changed, 5 insertions(+), 8 deletions(-) rename {osu.Game.Rulesets.Mania/Utils => osu.Game/Rulesets/Objects}/SnapFinder.cs (85%) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 04c4b06c88..2a363606ab 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Skinning.Default; -using osu.Game.Rulesets.Mania.Utils; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 17535c9bc9..c1b61aaf31 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -20,7 +20,6 @@ using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; -using osu.Game.Rulesets.Mania.Utils; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -84,7 +83,6 @@ namespace osu.Game.Rulesets.Mania.UI : base(ruleset, beatmap, mods) { BarLines = new BarLineGenerator(Beatmap).BarLines; - snapFinder = new SnapFinder(Beatmap); } diff --git a/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs b/osu.Game/Rulesets/Objects/SnapFinder.cs similarity index 85% rename from osu.Game.Rulesets.Mania/Utils/SnapFinder.cs rename to osu.Game/Rulesets/Objects/SnapFinder.cs index ed3bd4af05..eb8f4110a2 100644 --- a/osu.Game.Rulesets.Mania/Utils/SnapFinder.cs +++ b/osu.Game/Rulesets/Objects/SnapFinder.cs @@ -3,17 +3,16 @@ using System; using osu.Framework.Utils; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Objects; -namespace osu.Game.Rulesets.Mania.Utils +namespace osu.Game.Rulesets.Objects { public class SnapFinder { - private readonly ManiaBeatmap beatmap; + private readonly IBeatmap beatmap; - public SnapFinder(ManiaBeatmap beatmap) + public SnapFinder(IBeatmap beatmap) { this.beatmap = beatmap; } From d3db19c3ce9e0b8992be15684d9ffe3214965246 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sun, 25 Apr 2021 07:44:26 +0800 Subject: [PATCH 050/134] Simplify DrawableNote --- .../Objects/Drawables/DrawableNote.cs | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 2a363606ab..c364b395e1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Skinning.Default; @@ -34,13 +35,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private readonly Drawable headPiece; - public readonly Bindable SnapBindable = new Bindable(); - - public int Snap - { - get => SnapBindable.Value; - set => SnapBindable.Value = value; - } + private readonly Bindable Snap = new Bindable(); public DrawableNote(Note hitObject) : base(hitObject) @@ -61,10 +56,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (snapFinder != null) { - HitObject.StartTimeBindable.BindValueChanged(_ => Snap = snapFinder.FindSnap(HitObject), true); + HitObject.StartTimeBindable.BindValueChanged(_ => Snap.Value = snapFinder.FindSnap(HitObject), true); - SnapBindable.BindValueChanged(snap => updateSnapColour(configColourCodedNotes.Value, snap.NewValue), true); - configColourCodedNotes.BindValueChanged(colourCode => updateSnapColour(colourCode.NewValue, Snap)); + Snap.BindValueChanged(_ => updateSnapColour(), true); + configColourCodedNotes.BindValueChanged(_ => updateSnapColour()); } } @@ -106,18 +101,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public virtual void OnReleased(ManiaAction action) { - } + } - private void updateSnapColour(bool colourCode, int snap) + private void updateSnapColour() { - if (colourCode) - { - Colour = BindableBeatDivisor.GetColourFor(Snap, colours); - } - else - { - Colour = Colour4.White; - } + Colour = configColourCodedNotes.Value + ? (ColourInfo)BindableBeatDivisor.GetColourFor(Snap.Value, colours) + : (ColourInfo)Colour4.White; } } } \ No newline at end of file From 8b9d2a6cff41601d51f4a184ee08a5869479ffb7 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sun, 25 Apr 2021 08:32:21 +0800 Subject: [PATCH 051/134] Remove caching for ConfigColourCodedNotes --- .../Editor/ManiaPlacementBlueprintTestScene.cs | 12 ------------ .../Editor/ManiaSelectionBlueprintTestScene.cs | 12 ------------ .../ManiaInputTestScene.cs | 13 ------------- .../Skinning/ManiaSkinnableTestScene.cs | 11 ----------- osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs | 11 ----------- .../Objects/Drawables/DrawableNote.cs | 9 +++++++-- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 5 ----- 7 files changed, 7 insertions(+), 66 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index c04b875245..ece523e84c 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -4,12 +4,10 @@ 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; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; @@ -30,9 +28,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Cached(typeof(IScrollingInfo))] private IScrollingInfo scrollingInfo; - [Cached] - protected readonly Bindable ConfigColourCodedNotes = new Bindable(); - protected ManiaPlacementBlueprintTestScene() { scrollingInfo = ((ScrollingTestContainer)HitObjectContainer).ScrollingInfo; @@ -46,13 +41,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); - } - protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint) { var time = column.TimeAtScreenSpacePosition(InputManager.CurrentState.Mouse.Position); diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 1c11dc397e..176fbba921 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -2,10 +2,8 @@ // 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.Timing; -using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; using osuTK.Graphics; @@ -17,9 +15,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor [Cached(Type = typeof(IAdjustableClock))] private readonly IAdjustableClock clock = new StopwatchClock(); - [Cached] - protected readonly Bindable ConfigColourCodedNotes = new Bindable(); - protected ManiaSelectionBlueprintTestScene() { Add(new Column(0) @@ -31,13 +26,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor }); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); - } - public ManiaPlayfield Playfield => null; } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index 2b2db8aa96..9049bb3a82 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -1,12 +1,9 @@ // 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.Framework.Input.Bindings; -using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests @@ -16,21 +13,11 @@ namespace osu.Game.Rulesets.Mania.Tests private readonly Container content; protected override Container Content => content ?? base.Content; - [Cached] - protected readonly Bindable ConfigColourCodedNotes = new Bindable(); - protected ManiaInputTestScene(int keys) { base.Content.Add(content = new LocalInputManager(keys)); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); - } - private class LocalInputManager : ManiaInputManager { public LocalInputManager(int variant) diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index 941d01a1d6..1d84a2dfcb 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -7,7 +7,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling.Algorithms; using osu.Game.Tests.Visual; @@ -25,9 +24,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning [Cached(Type = typeof(IScrollingInfo))] private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); - [Cached] - protected readonly Bindable ConfigColourCodedNotes = new Bindable(); - protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset(); protected ManiaSkinnableTestScene() @@ -42,13 +38,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning }); } - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); - } - [Test] public void TestScrollingDown() { diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 1d053688a2..706268e478 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -15,7 +15,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; @@ -30,16 +29,6 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestSceneNotes : OsuTestScene { - [Cached] - protected readonly Bindable ConfigColourCodedNotes = new Bindable(); - - [BackgroundDependencyLoader] - private void load(RulesetConfigCache configCache) - { - var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); - } - [Test] public void TestVariousNotes() { diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index c364b395e1..09dd0da5ac 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Input.Bindings; using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; @@ -25,8 +26,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables [Resolved] private OsuColour colours { get; set; } - [Resolved] - private Bindable configColourCodedNotes { get; set; } + [Resolved(canBeNull: true)] + private ManiaRulesetConfigManager config { get; set; } + + private readonly Bindable configColourCodedNotes = new Bindable(); [Resolved(canBeNull: true)] private SnapFinder snapFinder { get; set; } @@ -56,6 +59,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (snapFinder != null) { + config?.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + HitObject.StartTimeBindable.BindValueChanged(_ => Snap.Value = snapFinder.FindSnap(HitObject), true); Snap.BindValueChanged(_ => updateSnapColour(), true); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index c1b61aaf31..174727cc2d 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -54,9 +54,6 @@ namespace osu.Game.Rulesets.Mania.UI protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config; - [Cached] - protected readonly Bindable ConfigColourCodedNotes = new Bindable(); - public ScrollVisualisationMethod ScrollMethod { get => scrollMethod; @@ -111,8 +108,6 @@ namespace osu.Game.Rulesets.Mania.UI configDirection.BindValueChanged(direction => Direction.Value = (ScrollingDirection)direction.NewValue, true); Config.BindWith(ManiaRulesetSetting.ScrollTime, configTimeRange); - - Config.BindWith(ManiaRulesetSetting.ColourCodedNotes, ConfigColourCodedNotes); } protected override void AdjustScrollSpeed(int amount) From 1f48378ce72b4036601eb09d0a6090ba51434d38 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sun, 25 Apr 2021 08:53:45 +0800 Subject: [PATCH 052/134] Add xmldoc to SnapFinder --- osu.Game/Rulesets/Objects/SnapFinder.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Rulesets/Objects/SnapFinder.cs b/osu.Game/Rulesets/Objects/SnapFinder.cs index eb8f4110a2..f915d41305 100644 --- a/osu.Game/Rulesets/Objects/SnapFinder.cs +++ b/osu.Game/Rulesets/Objects/SnapFinder.cs @@ -8,10 +8,17 @@ using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Rulesets.Objects { + /// + /// Used to find the lowest beat divisor that a aligns to in an + /// public class SnapFinder { private readonly IBeatmap beatmap; + /// + /// Creates a new SnapFinder instance. + /// + /// The beatmap to align to when evaulating. public SnapFinder(IBeatmap beatmap) { this.beatmap = beatmap; @@ -19,6 +26,10 @@ namespace osu.Game.Rulesets.Objects private readonly static int[] snaps = { 1, 2, 3, 4, 6, 8, 12, 16 }; + /// + /// Finds the lowest beat divisor that the given HitObject aligns to. + /// + /// The to evaluate. public int FindSnap(HitObject hitObject) { TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); From 211bff6a8f09d8379b1574dfb80d97b76e318ae3 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sun, 25 Apr 2021 09:21:25 +0800 Subject: [PATCH 053/134] Fix cake errors --- .../Objects/Drawables/DrawableNote.cs | 10 +++++----- osu.Game/Rulesets/Objects/SnapFinder.cs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 09dd0da5ac..9f30221fde 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private readonly Drawable headPiece; - private readonly Bindable Snap = new Bindable(); + private readonly Bindable snap = new Bindable(); public DrawableNote(Note hitObject) : base(hitObject) @@ -61,9 +61,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { config?.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); - HitObject.StartTimeBindable.BindValueChanged(_ => Snap.Value = snapFinder.FindSnap(HitObject), true); + HitObject.StartTimeBindable.BindValueChanged(_ => snap.Value = snapFinder.FindSnap(HitObject), true); - Snap.BindValueChanged(_ => updateSnapColour(), true); + snap.BindValueChanged(_ => updateSnapColour(), true); configColourCodedNotes.BindValueChanged(_ => updateSnapColour()); } } @@ -106,12 +106,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public virtual void OnReleased(ManiaAction action) { - } + } private void updateSnapColour() { Colour = configColourCodedNotes.Value - ? (ColourInfo)BindableBeatDivisor.GetColourFor(Snap.Value, colours) + ? (ColourInfo)BindableBeatDivisor.GetColourFor(snap.Value, colours) : (ColourInfo)Colour4.White; } } diff --git a/osu.Game/Rulesets/Objects/SnapFinder.cs b/osu.Game/Rulesets/Objects/SnapFinder.cs index f915d41305..3bc1d5cfb7 100644 --- a/osu.Game/Rulesets/Objects/SnapFinder.cs +++ b/osu.Game/Rulesets/Objects/SnapFinder.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Objects this.beatmap = beatmap; } - private readonly static int[] snaps = { 1, 2, 3, 4, 6, 8, 12, 16 }; + private static readonly int[] snaps = { 1, 2, 3, 4, 6, 8, 12, 16 }; /// /// Finds the lowest beat divisor that the given HitObject aligns to. @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects foreach (var snap in snaps) { - if (almostDivisibleBy(snapResult, currentTimingPoint.BeatLength / (double)snap)) + if (almostDivisibleBy(snapResult, currentTimingPoint.BeatLength / snap)) return snap; } From f9e228d6bfb4e94ded823da5ceb6434c09db6b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Apr 2021 17:40:23 +0200 Subject: [PATCH 054/134] Use null-permitting BDL to reduce number of fields --- .../Objects/Drawables/DrawableNote.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 9f30221fde..52e343ba25 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -26,14 +26,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables [Resolved] private OsuColour colours { get; set; } - [Resolved(canBeNull: true)] - private ManiaRulesetConfigManager config { get; set; } - private readonly Bindable configColourCodedNotes = new Bindable(); - [Resolved(canBeNull: true)] - private SnapFinder snapFinder { get; set; } - protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note; private readonly Drawable headPiece; @@ -53,13 +47,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } - protected override void LoadComplete() + [BackgroundDependencyLoader(true)] + private void load(ManiaRulesetConfigManager rulesetConfig, SnapFinder snapFinder) { - base.LoadComplete(); - if (snapFinder != null) { - config?.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + rulesetConfig?.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); HitObject.StartTimeBindable.BindValueChanged(_ => snap.Value = snapFinder.FindSnap(HitObject), true); @@ -115,4 +108,4 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables : (ColourInfo)Colour4.White; } } -} \ No newline at end of file +} From afb67726f0057525b975bbd7b51d6e156e3316a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Apr 2021 17:40:49 +0200 Subject: [PATCH 055/134] Reduce casting --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 52e343ba25..a5749408af 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Configuration; @@ -15,6 +14,7 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; using osu.Game.Skinning; +using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -104,8 +104,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private void updateSnapColour() { Colour = configColourCodedNotes.Value - ? (ColourInfo)BindableBeatDivisor.GetColourFor(snap.Value, colours) - : (ColourInfo)Colour4.White; + ? BindableBeatDivisor.GetColourFor(snap.Value, colours) + : Color4.White; } } } From e14255f39548b250d5c276663f4765cbc41d2596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Apr 2021 17:42:56 +0200 Subject: [PATCH 056/134] Rename {Snap -> BeatDivisor}Finder --- .../Objects/Drawables/DrawableNote.cs | 6 +++--- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 4 ++-- .../{SnapFinder.cs => BeatDivisorFinder.cs} | 14 +++++++------- 3 files changed, 12 insertions(+), 12 deletions(-) rename osu.Game/Rulesets/Objects/{SnapFinder.cs => BeatDivisorFinder.cs} (77%) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index a5749408af..2d2fba0ad5 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -48,13 +48,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } [BackgroundDependencyLoader(true)] - private void load(ManiaRulesetConfigManager rulesetConfig, SnapFinder snapFinder) + private void load(ManiaRulesetConfigManager rulesetConfig, BeatDivisorFinder beatDivisorFinder) { - if (snapFinder != null) + if (beatDivisorFinder != null) { rulesetConfig?.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); - HitObject.StartTimeBindable.BindValueChanged(_ => snap.Value = snapFinder.FindSnap(HitObject), true); + HitObject.StartTimeBindable.BindValueChanged(_ => snap.Value = beatDivisorFinder.FindDivisor(HitObject), true); snap.BindValueChanged(_ => updateSnapColour(), true); configColourCodedNotes.BindValueChanged(_ => updateSnapColour()); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 174727cc2d..0177c01240 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Mania.UI public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap; [Cached] - private SnapFinder snapFinder { get; set; } + private BeatDivisorFinder beatDivisorFinder { get; set; } public IEnumerable BarLines; @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Mania.UI : base(ruleset, beatmap, mods) { BarLines = new BarLineGenerator(Beatmap).BarLines; - snapFinder = new SnapFinder(Beatmap); + beatDivisorFinder = new BeatDivisorFinder(Beatmap); } [BackgroundDependencyLoader] diff --git a/osu.Game/Rulesets/Objects/SnapFinder.cs b/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs similarity index 77% rename from osu.Game/Rulesets/Objects/SnapFinder.cs rename to osu.Game/Rulesets/Objects/BeatDivisorFinder.cs index 3bc1d5cfb7..29b271a7e7 100644 --- a/osu.Game/Rulesets/Objects/SnapFinder.cs +++ b/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs @@ -9,17 +9,17 @@ using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Rulesets.Objects { /// - /// Used to find the lowest beat divisor that a aligns to in an + /// Used to find the lowest beat divisor that a aligns to in an . /// - public class SnapFinder + public class BeatDivisorFinder { private readonly IBeatmap beatmap; /// - /// Creates a new SnapFinder instance. + /// Creates a new instance. /// - /// The beatmap to align to when evaulating. - public SnapFinder(IBeatmap beatmap) + /// The beatmap to use when calculating beat divisor alignment. + public BeatDivisorFinder(IBeatmap beatmap) { this.beatmap = beatmap; } @@ -27,10 +27,10 @@ namespace osu.Game.Rulesets.Objects private static readonly int[] snaps = { 1, 2, 3, 4, 6, 8, 12, 16 }; /// - /// Finds the lowest beat divisor that the given HitObject aligns to. + /// Finds the lowest beat divisor that the given aligns to. /// /// The to evaluate. - public int FindSnap(HitObject hitObject) + public int FindDivisor(HitObject hitObject) { TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); double snapResult = (hitObject.StartTime - currentTimingPoint.Time) % (currentTimingPoint.BeatLength * 4); From 33a5c156a1e79e3ffe22f7199e9348f8f42b2464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Apr 2021 17:52:11 +0200 Subject: [PATCH 057/134] Use existing snap list from BindableBeatDivisor --- osu.Game/Rulesets/Objects/BeatDivisorFinder.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs b/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs index 29b271a7e7..63a4ff2d34 100644 --- a/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs +++ b/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Objects { @@ -24,8 +25,6 @@ namespace osu.Game.Rulesets.Objects this.beatmap = beatmap; } - private static readonly int[] snaps = { 1, 2, 3, 4, 6, 8, 12, 16 }; - /// /// Finds the lowest beat divisor that the given aligns to. /// @@ -35,10 +34,10 @@ namespace osu.Game.Rulesets.Objects TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); double snapResult = (hitObject.StartTime - currentTimingPoint.Time) % (currentTimingPoint.BeatLength * 4); - foreach (var snap in snaps) + foreach (var divisor in BindableBeatDivisor.VALID_DIVISORS) { - if (almostDivisibleBy(snapResult, currentTimingPoint.BeatLength / snap)) - return snap; + if (almostDivisibleBy(snapResult, currentTimingPoint.BeatLength / divisor)) + return divisor; } return 0; From 8bb1fcd39b29b55b693d9540777f96ecb0d8d3c6 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Mon, 26 Apr 2021 07:07:32 +0800 Subject: [PATCH 058/134] Add tests for BeatDivisorFinder --- osu.Game.Tests/NonVisual/BeatDivisorFinder.cs | 116 ++++++++++++++++++ .../Rulesets/Objects/BeatDivisorFinder.cs | 3 +- 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/NonVisual/BeatDivisorFinder.cs diff --git a/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs b/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs new file mode 100644 index 0000000000..742f5790d6 --- /dev/null +++ b/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs @@ -0,0 +1,116 @@ +// 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 NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Tests.NonVisual +{ + public class BeatDivisorFinderTest + { + [Test] + public void TestFindDivisor() + { + const int beatLength = 1000; + + var beatmap = new Beatmap + { + HitObjects = new List + { + new HitObject { StartTime = -beatLength / 3 }, + new HitObject { StartTime = 0 }, + new HitObject { StartTime = beatLength / 16 }, + new HitObject { StartTime = beatLength / 12 }, + new HitObject { StartTime = beatLength / 8 }, + new HitObject { StartTime = beatLength / 6 }, + new HitObject { StartTime = beatLength / 4 }, + new HitObject { StartTime = beatLength / 3 }, + new HitObject { StartTime = beatLength / 2 }, + new HitObject { StartTime = beatLength }, + new HitObject { StartTime = beatLength + beatLength / 7 } + }, + ControlPointInfo = new ControlPointInfo() + }; + + beatmap.ControlPointInfo.Add(0, new TimingControlPoint() + { + TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, + BeatLength = beatLength + }); + + var beatDivisorFinder = new BeatDivisorFinder(beatmap); + + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[0]), 3); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[1]), 1); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[2]), 16); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[3]), 12); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[4]), 8); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[5]), 6); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[6]), 4); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[7]), 3); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[8]), 2); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[9]), 1); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[10]), 0); + } + + [Test] + public void TestFindDivisorWithTempoChanges() + { + const int firstBeatLength = 1000; + const int secondBeatLength = 700; + const int thirdBeatLength = 200; + + const int firstBeatLengthStart = 0; + const int secondBeatLengthStart = 1000; + const int thirdBeatLengthStart = 2000; + + var beatmap = new Beatmap + { + HitObjects = new List + { + new HitObject { StartTime = firstBeatLengthStart }, + new HitObject { StartTime = firstBeatLengthStart + firstBeatLength / 2 }, + new HitObject { StartTime = secondBeatLengthStart }, + new HitObject { StartTime = secondBeatLengthStart + secondBeatLength / 2 }, + new HitObject { StartTime = thirdBeatLengthStart }, + new HitObject { StartTime = thirdBeatLengthStart + thirdBeatLength / 2 }, + }, + ControlPointInfo = new ControlPointInfo() + }; + + var firstTimingControlPoint = new TimingControlPoint() + { + TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, + BeatLength = firstBeatLength + }; + + var secondTimingControlPoint = new TimingControlPoint() + { + TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, + BeatLength = secondBeatLength + }; + + var thirdTimingControlPoint = new TimingControlPoint() + { + TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, + BeatLength = thirdBeatLength + }; + + beatmap.ControlPointInfo.Add(firstBeatLengthStart, firstTimingControlPoint); + beatmap.ControlPointInfo.Add(secondBeatLengthStart, secondTimingControlPoint); + beatmap.ControlPointInfo.Add(thirdBeatLengthStart, thirdTimingControlPoint); + + var beatDivisorFinder = new BeatDivisorFinder(beatmap); + + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[0]), 1); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[1]), 2); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[2]), 1); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[3]), 2); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[4]), 1); + Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[5]), 2); + } + } +} diff --git a/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs b/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs index 63a4ff2d34..1479b22942 100644 --- a/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs +++ b/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs @@ -27,12 +27,13 @@ namespace osu.Game.Rulesets.Objects /// /// Finds the lowest beat divisor that the given aligns to. + /// Returns 0 if it does not align to any divisor. /// /// The to evaluate. public int FindDivisor(HitObject hitObject) { TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); - double snapResult = (hitObject.StartTime - currentTimingPoint.Time) % (currentTimingPoint.BeatLength * 4); + double snapResult = hitObject.StartTime - currentTimingPoint.Time; foreach (var divisor in BindableBeatDivisor.VALID_DIVISORS) { From 58ebec48037499b162fb5045c767812a22f82fb5 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Mon, 26 Apr 2021 19:00:40 +0800 Subject: [PATCH 059/134] Move BindValueChanged hooks to LoadComplete() --- .../Objects/Drawables/DrawableNote.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 2d2fba0ad5..49536080ab 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -26,6 +26,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables [Resolved] private OsuColour colours { get; set; } + [Resolved] + private BeatDivisorFinder beatDivisorFinder { get; set; } + private readonly Bindable configColourCodedNotes = new Bindable(); protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note; @@ -48,17 +51,20 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } [BackgroundDependencyLoader(true)] - private void load(ManiaRulesetConfigManager rulesetConfig, BeatDivisorFinder beatDivisorFinder) + private void load(ManiaRulesetConfigManager rulesetConfig) + { + rulesetConfig?.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + } + + protected override void LoadComplete() { if (beatDivisorFinder != null) { - rulesetConfig?.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); - HitObject.StartTimeBindable.BindValueChanged(_ => snap.Value = beatDivisorFinder.FindDivisor(HitObject), true); - - snap.BindValueChanged(_ => updateSnapColour(), true); - configColourCodedNotes.BindValueChanged(_ => updateSnapColour()); } + + snap.BindValueChanged(_ => updateSnapColour()); + configColourCodedNotes.BindValueChanged(_ => updateSnapColour(), true); } protected override void OnDirectionChanged(ValueChangedEvent e) From 559d403abec8046cd8331fbc45523676ae2452f0 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Mon, 26 Apr 2021 19:05:12 +0800 Subject: [PATCH 060/134] Rename ColourCodedNotes to TimingBasedNoteColouring --- .../Configuration/ManiaRulesetConfigManager.cs | 4 ++-- osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs | 4 ++-- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index 87a4689689..ac8168dfc9 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Configuration SetDefault(ManiaRulesetSetting.ScrollTime, 1500.0, DrawableManiaRuleset.MIN_TIME_RANGE, DrawableManiaRuleset.MAX_TIME_RANGE, 5); SetDefault(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); - SetDefault(ManiaRulesetSetting.ColourCodedNotes, false); + SetDefault(ManiaRulesetSetting.TimingBasedNoteColouring, false); } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings @@ -36,6 +36,6 @@ namespace osu.Game.Rulesets.Mania.Configuration { ScrollTime, ScrollDirection, - ColourCodedNotes + TimingBasedNoteColouring } } diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index 552c793096..1c89d9cd00 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -39,8 +39,8 @@ namespace osu.Game.Rulesets.Mania }, new SettingsCheckbox { - LabelText = "Colour-coded notes", - Current = config.GetBindable(ManiaRulesetSetting.ColourCodedNotes), + LabelText = "Timing-based note colouring", + Current = config.GetBindable(ManiaRulesetSetting.TimingBasedNoteColouring), } }; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 49536080ab..102cd485dc 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables [Resolved] private BeatDivisorFinder beatDivisorFinder { get; set; } - private readonly Bindable configColourCodedNotes = new Bindable(); + private readonly Bindable configTimingBasedNoteColouring = new Bindable(); protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note; @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables [BackgroundDependencyLoader(true)] private void load(ManiaRulesetConfigManager rulesetConfig) { - rulesetConfig?.BindWith(ManiaRulesetSetting.ColourCodedNotes, configColourCodedNotes); + rulesetConfig?.BindWith(ManiaRulesetSetting.TimingBasedNoteColouring, configTimingBasedNoteColouring); } protected override void LoadComplete() @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } snap.BindValueChanged(_ => updateSnapColour()); - configColourCodedNotes.BindValueChanged(_ => updateSnapColour(), true); + configTimingBasedNoteColouring.BindValueChanged(_ => updateSnapColour(), true); } protected override void OnDirectionChanged(ValueChangedEvent e) @@ -109,7 +109,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private void updateSnapColour() { - Colour = configColourCodedNotes.Value + Colour = configTimingBasedNoteColouring.Value ? BindableBeatDivisor.GetColourFor(snap.Value, colours) : Color4.White; } From c4d28110d641c9d121d88e4559c783cfc2094218 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Tue, 27 Apr 2021 19:02:57 +0800 Subject: [PATCH 061/134] Add visual tests for timing based note coloring --- .../TestSceneTimingBasedNoteColouring.cs | 88 +++++++++++++++++++ .../Objects/Drawables/DrawableNote.cs | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs new file mode 100644 index 0000000000..3a9ddb6a9d --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs @@ -0,0 +1,88 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Tests.Visual; +using osu.Framework.Timing; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Framework.Bindables; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestSceneTimingBasedNoteColouring : OsuTestScene + { + [Resolved] + private RulesetConfigCache configCache { get; set; } + private readonly Bindable configTimingBasedNoteColouring = new Bindable(); + + protected override void LoadComplete() + { + const int beatLength = 500; + + var ruleset = new ManiaRuleset(); + + var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 }) + { + HitObjects = { + new Note { StartTime = 0 }, + new Note { StartTime = beatLength / 16 }, + new Note { StartTime = beatLength / 12 }, + new Note { StartTime = beatLength / 8 }, + new Note { StartTime = beatLength / 6 }, + new Note { StartTime = beatLength / 4 }, + new Note { StartTime = beatLength / 3 }, + new Note { StartTime = beatLength / 2 }, + new Note { StartTime = beatLength } + }, + ControlPointInfo = new ControlPointInfo(), + BeatmapInfo = + { + BaseDifficulty = new BeatmapDifficulty + { + SliderTickRate = 4, + OverallDifficulty = 10, + }, + Ruleset = ruleset.RulesetInfo + }, + }; + + foreach (var note in beatmap.HitObjects) + { + note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + } + + beatmap.ControlPointInfo.Add(0, new TimingControlPoint() + { + TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, + BeatLength = beatLength + } + ); + + Child = new Container + { + Clock = new FramedClock(new ManualClock()), + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new[] + { + ruleset.CreateDrawableRulesetWith(beatmap) + } + }; + + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.TimingBasedNoteColouring, configTimingBasedNoteColouring); + + AddStep("Enable", () => configTimingBasedNoteColouring.Value = true); + AddStep("Disable", () => configTimingBasedNoteColouring.Value = false); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 102cd485dc..942a32936c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables [Resolved] private OsuColour colours { get; set; } - [Resolved] + [Resolved(canBeNull: true)] private BeatDivisorFinder beatDivisorFinder { get; set; } private readonly Bindable configTimingBasedNoteColouring = new Bindable(); From 4752a0201ad2373c2bfefb9ae8328e5de8609298 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Tue, 27 Apr 2021 19:25:46 +0800 Subject: [PATCH 062/134] Fix cake errors --- .../TestSceneTimingBasedNoteColouring.cs | 26 +++--- osu.Game.Tests/NonVisual/BeatDivisorFinder.cs | 90 +++++++++---------- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs index 3a9ddb6a9d..5cfd7ff389 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs @@ -21,26 +21,28 @@ namespace osu.Game.Rulesets.Mania.Tests { [Resolved] private RulesetConfigCache configCache { get; set; } + private readonly Bindable configTimingBasedNoteColouring = new Bindable(); protected override void LoadComplete() { - const int beatLength = 500; + const double beat_length = 500; var ruleset = new ManiaRuleset(); var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 1 }) { - HitObjects = { + HitObjects = + { new Note { StartTime = 0 }, - new Note { StartTime = beatLength / 16 }, - new Note { StartTime = beatLength / 12 }, - new Note { StartTime = beatLength / 8 }, - new Note { StartTime = beatLength / 6 }, - new Note { StartTime = beatLength / 4 }, - new Note { StartTime = beatLength / 3 }, - new Note { StartTime = beatLength / 2 }, - new Note { StartTime = beatLength } + new Note { StartTime = beat_length / 16 }, + new Note { StartTime = beat_length / 12 }, + new Note { StartTime = beat_length / 8 }, + new Note { StartTime = beat_length / 6 }, + new Note { StartTime = beat_length / 4 }, + new Note { StartTime = beat_length / 3 }, + new Note { StartTime = beat_length / 2 }, + new Note { StartTime = beat_length } }, ControlPointInfo = new ControlPointInfo(), BeatmapInfo = @@ -59,10 +61,10 @@ namespace osu.Game.Rulesets.Mania.Tests note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); } - beatmap.ControlPointInfo.Add(0, new TimingControlPoint() + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = beatLength + BeatLength = beat_length } ); diff --git a/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs b/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs index 742f5790d6..720d8e8ecd 100644 --- a/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs +++ b/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs @@ -14,32 +14,32 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestFindDivisor() { - const int beatLength = 1000; + const double beat_length = 1000; var beatmap = new Beatmap { HitObjects = new List { - new HitObject { StartTime = -beatLength / 3 }, + new HitObject { StartTime = -beat_length / 3 }, new HitObject { StartTime = 0 }, - new HitObject { StartTime = beatLength / 16 }, - new HitObject { StartTime = beatLength / 12 }, - new HitObject { StartTime = beatLength / 8 }, - new HitObject { StartTime = beatLength / 6 }, - new HitObject { StartTime = beatLength / 4 }, - new HitObject { StartTime = beatLength / 3 }, - new HitObject { StartTime = beatLength / 2 }, - new HitObject { StartTime = beatLength }, - new HitObject { StartTime = beatLength + beatLength / 7 } + new HitObject { StartTime = beat_length / 16 }, + new HitObject { StartTime = beat_length / 12 }, + new HitObject { StartTime = beat_length / 8 }, + new HitObject { StartTime = beat_length / 6 }, + new HitObject { StartTime = beat_length / 4 }, + new HitObject { StartTime = beat_length / 3 }, + new HitObject { StartTime = beat_length / 2 }, + new HitObject { StartTime = beat_length }, + new HitObject { StartTime = beat_length + beat_length / 7 } }, ControlPointInfo = new ControlPointInfo() }; - beatmap.ControlPointInfo.Add(0, new TimingControlPoint() - { - TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = beatLength - }); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint + { + TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, + BeatLength = beat_length + }); var beatDivisorFinder = new BeatDivisorFinder(beatmap); @@ -59,49 +59,49 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestFindDivisorWithTempoChanges() { - const int firstBeatLength = 1000; - const int secondBeatLength = 700; - const int thirdBeatLength = 200; + const double first_beat_length = 1000; + const double second_beat_length = 700; + const double third_beat_length = 200; - const int firstBeatLengthStart = 0; - const int secondBeatLengthStart = 1000; - const int thirdBeatLengthStart = 2000; + const double first_beat_length_start = 0; + const double second_beat_length_start = 1000; + const double third_beat_length_start = 2000; var beatmap = new Beatmap { HitObjects = new List { - new HitObject { StartTime = firstBeatLengthStart }, - new HitObject { StartTime = firstBeatLengthStart + firstBeatLength / 2 }, - new HitObject { StartTime = secondBeatLengthStart }, - new HitObject { StartTime = secondBeatLengthStart + secondBeatLength / 2 }, - new HitObject { StartTime = thirdBeatLengthStart }, - new HitObject { StartTime = thirdBeatLengthStart + thirdBeatLength / 2 }, + new HitObject { StartTime = first_beat_length_start }, + new HitObject { StartTime = first_beat_length_start + first_beat_length / 2 }, + new HitObject { StartTime = second_beat_length_start }, + new HitObject { StartTime = second_beat_length_start + second_beat_length / 2 }, + new HitObject { StartTime = third_beat_length_start }, + new HitObject { StartTime = third_beat_length_start + third_beat_length / 2 }, }, ControlPointInfo = new ControlPointInfo() }; - var firstTimingControlPoint = new TimingControlPoint() + var firstTimingControlPoint = new TimingControlPoint { TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = firstBeatLength - }; - - var secondTimingControlPoint = new TimingControlPoint() - { - TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = secondBeatLength - }; - - var thirdTimingControlPoint = new TimingControlPoint() - { - TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = thirdBeatLength + BeatLength = first_beat_length }; - beatmap.ControlPointInfo.Add(firstBeatLengthStart, firstTimingControlPoint); - beatmap.ControlPointInfo.Add(secondBeatLengthStart, secondTimingControlPoint); - beatmap.ControlPointInfo.Add(thirdBeatLengthStart, thirdTimingControlPoint); + var secondTimingControlPoint = new TimingControlPoint + { + TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, + BeatLength = second_beat_length + }; + + var thirdTimingControlPoint = new TimingControlPoint + { + TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, + BeatLength = third_beat_length + }; + + beatmap.ControlPointInfo.Add(first_beat_length_start, firstTimingControlPoint); + beatmap.ControlPointInfo.Add(second_beat_length_start, secondTimingControlPoint); + beatmap.ControlPointInfo.Add(third_beat_length_start, thirdTimingControlPoint); var beatDivisorFinder = new BeatDivisorFinder(beatmap); From 243605728d5f167680caa5bbb0dee1225960075d Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 28 Apr 2021 11:44:05 -0700 Subject: [PATCH 063/134] Fix approved maps not displaying pp column on score table --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index b598b7d97f..3e95d125de 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -59,8 +59,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores var scoreInfos = value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToList(); var topScore = scoreInfos.First(); + var status = topScore.Beatmap?.Status; + var showPerformanceColumn = status == BeatmapSetOnlineStatus.Ranked || status == BeatmapSetOnlineStatus.Approved; - scoreTable.DisplayScores(scoreInfos, topScore.Beatmap?.Status == BeatmapSetOnlineStatus.Ranked); + scoreTable.DisplayScores(scoreInfos, showPerformanceColumn); scoreTable.Show(); var userScore = value.UserScore; From cfbf95b4331c777a5dbd109fb57b3e5f76e2fc93 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 29 Apr 2021 14:11:35 -0700 Subject: [PATCH 064/134] Add HasPerformancePoints extension method --- ...tOnlineStatus.cs => BeatmapSetOnlineStatusExtensions.cs} | 6 ++++++ osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 4 +--- .../Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) rename osu.Game/Beatmaps/{BeatmapSetOnlineStatus.cs => BeatmapSetOnlineStatusExtensions.cs} (61%) diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs b/osu.Game/Beatmaps/BeatmapSetOnlineStatusExtensions.cs similarity index 61% rename from osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs rename to osu.Game/Beatmaps/BeatmapSetOnlineStatusExtensions.cs index 5864975a2e..1de641f4f1 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineStatusExtensions.cs @@ -3,6 +3,12 @@ namespace osu.Game.Beatmaps { + public static class BeatmapSetOnlineStatusExtensions + { + public static bool HasPerformancePoints(this BeatmapSetOnlineStatus status) + => status == BeatmapSetOnlineStatus.Ranked || status == BeatmapSetOnlineStatus.Approved; + } + public enum BeatmapSetOnlineStatus { None = -3, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 3e95d125de..8786cf0e63 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -59,10 +59,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores var scoreInfos = value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToList(); var topScore = scoreInfos.First(); - var status = topScore.Beatmap?.Status; - var showPerformanceColumn = status == BeatmapSetOnlineStatus.Ranked || status == BeatmapSetOnlineStatus.Approved; - scoreTable.DisplayScores(scoreInfos, showPerformanceColumn); + scoreTable.DisplayScores(scoreInfos, topScore.Beatmap?.Status.HasPerformancePoints() ?? false); scoreTable.Show(); var userScore = value.UserScore; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 5cb834b510..57df54d851 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -111,7 +111,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores accuracyColumn.Text = value.DisplayAccuracy; maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; - ppColumn.Alpha = value.Beatmap?.Status == BeatmapSetOnlineStatus.Ranked ? 1 : 0; + + ppColumn.Alpha = value.Beatmap?.Status.HasPerformancePoints() ?? false ? 1 : 0; ppColumn.Text = $@"{value.PP:N0}"; statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn); From 9952a5bfdb25c5130d1fe1462b5578a860d1880c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 29 Apr 2021 14:24:29 -0700 Subject: [PATCH 065/134] Revert "Fix button being recreated on importing state" This reverts commit c9967f7b7486d5744aba911a144110811b76ef04. --- osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index 85ed3f8767..a61640a02e 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -268,13 +268,11 @@ namespace osu.Game.Overlays.BeatmapSet break; case DownloadState.Downloading: + case DownloadState.Importing: // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); break; - case DownloadState.Importing: - break; - default: downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); if (BeatmapSet.Value.OnlineInfo.HasVideo) From 25e0fb1cf9de0e01d8225f97f737cadf43390572 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Apr 2021 01:59:59 +0300 Subject: [PATCH 066/134] Refactor OsuModBarrelRoll to allow it's usage by other rulesets --- .../Mods/OsuModBarrelRoll.cs | 40 ++------------ osu.Game/Rulesets/Mods/ModBarrelRoll.cs | 52 +++++++++++++++++++ 2 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/ModBarrelRoll.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs index 37ba401d42..f63edbd99f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs @@ -2,52 +2,18 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Framework.Bindables; -using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.UI; -using osu.Game.Rulesets.UI; using osuTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModBarrelRoll : Mod, IUpdatableByPlayfield, IApplicableToDrawableRuleset, IApplicableToDrawableHitObjects + public class OsuModBarrelRoll : ModBarrelRoll, IApplicableToDrawableHitObjects { - private float currentRotation; - - [SettingSource("Roll speed", "Rotations per minute")] - public BindableNumber SpinSpeed { get; } = new BindableDouble(0.5) - { - MinValue = 0.02, - MaxValue = 12, - Precision = 0.01, - }; - - [SettingSource("Direction", "The direction of rotation")] - public Bindable Direction { get; } = new Bindable(RotationDirection.Clockwise); - - public override string Name => "Barrel Roll"; - public override string Acronym => "BR"; - public override string Description => "The whole playfield is on a wheel!"; - public override double ScoreMultiplier => 1; - - public override string SettingDescription => $"{SpinSpeed.Value} rpm {Direction.Value.GetDescription().ToLowerInvariant()}"; - - public void Update(Playfield playfield) - { - playfield.Rotation = currentRotation = (Direction.Value == RotationDirection.Counterclockwise ? -1 : 1) * 360 * (float)(playfield.Time.Current / 60000 * SpinSpeed.Value); - } - - public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) - { - // scale the playfield to allow all hitobjects to stay within the visible region. - drawableRuleset.Playfield.Scale = new Vector2(OsuPlayfield.BASE_SIZE.Y / OsuPlayfield.BASE_SIZE.X); - } + protected override Vector2 PlayfieldScale => new Vector2(OsuPlayfield.BASE_SIZE.Y / OsuPlayfield.BASE_SIZE.X); public void ApplyToDrawableHitObjects(IEnumerable drawables) { @@ -58,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods switch (d) { case DrawableHitCircle circle: - circle.CirclePiece.Rotation = -currentRotation; + circle.CirclePiece.Rotation = -CurrentRotation; break; } }; diff --git a/osu.Game/Rulesets/Mods/ModBarrelRoll.cs b/osu.Game/Rulesets/Mods/ModBarrelRoll.cs new file mode 100644 index 0000000000..d9424563c5 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModBarrelRoll.cs @@ -0,0 +1,52 @@ +// 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.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Game.Configuration; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; +using osuTK; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModBarrelRoll : Mod, IUpdatableByPlayfield, IApplicableToDrawableRuleset + where TObject : HitObject + { + protected float CurrentRotation { get; private set; } + + [SettingSource("Roll speed", "Rotations per minute")] + public BindableNumber SpinSpeed { get; } = new BindableDouble(0.5) + { + MinValue = 0.02, + MaxValue = 12, + Precision = 0.01, + }; + + [SettingSource("Direction", "The direction of rotation")] + public Bindable Direction { get; } = new Bindable(RotationDirection.Clockwise); + + public override string Name => "Barrel Roll"; + public override string Acronym => "BR"; + public override string Description => "The whole playfield is on a wheel!"; + public override double ScoreMultiplier => 1; + + public override string SettingDescription => $"{SpinSpeed.Value} rpm {Direction.Value.GetDescription().ToLowerInvariant()}"; + + /// + /// Used to allow all hitobjects to stay within the visible region. + /// + protected abstract Vector2 PlayfieldScale { get; } + + public void Update(Playfield playfield) + { + playfield.Rotation = CurrentRotation = (Direction.Value == RotationDirection.Counterclockwise ? -1 : 1) * 360 * (float)(playfield.Time.Current / 60000 * SpinSpeed.Value); + } + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + drawableRuleset.Playfield.Scale = PlayfieldScale; + } + } +} From 7bf3498e2add11f5b3590b2d76df409efce1e06d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Apr 2021 02:49:19 +0300 Subject: [PATCH 067/134] Calculate playfield scale locally --- osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs | 4 ---- osu.Game/Rulesets/Mods/ModBarrelRoll.cs | 13 +++++++------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs index f63edbd99f..9ae9653e9b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs @@ -6,15 +6,11 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Osu.UI; -using osuTK; namespace osu.Game.Rulesets.Osu.Mods { public class OsuModBarrelRoll : ModBarrelRoll, IApplicableToDrawableHitObjects { - protected override Vector2 PlayfieldScale => new Vector2(OsuPlayfield.BASE_SIZE.Y / OsuPlayfield.BASE_SIZE.X); - public void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var d in drawables) diff --git a/osu.Game/Rulesets/Mods/ModBarrelRoll.cs b/osu.Game/Rulesets/Mods/ModBarrelRoll.cs index d9424563c5..4c28c730ec 100644 --- a/osu.Game/Rulesets/Mods/ModBarrelRoll.cs +++ b/osu.Game/Rulesets/Mods/ModBarrelRoll.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; @@ -34,11 +35,6 @@ namespace osu.Game.Rulesets.Mods public override string SettingDescription => $"{SpinSpeed.Value} rpm {Direction.Value.GetDescription().ToLowerInvariant()}"; - /// - /// Used to allow all hitobjects to stay within the visible region. - /// - protected abstract Vector2 PlayfieldScale { get; } - public void Update(Playfield playfield) { playfield.Rotation = CurrentRotation = (Direction.Value == RotationDirection.Counterclockwise ? -1 : 1) * 360 * (float)(playfield.Time.Current / 60000 * SpinSpeed.Value); @@ -46,7 +42,12 @@ namespace osu.Game.Rulesets.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - drawableRuleset.Playfield.Scale = PlayfieldScale; + // scale the playfield to allow all hitobjects to stay within the visible region. + + var playfieldSize = drawableRuleset.Playfield.DrawSize; + var minSide = MathF.Min(playfieldSize.X, playfieldSize.Y); + var maxSide = MathF.Max(playfieldSize.X, playfieldSize.Y); + drawableRuleset.Playfield.Scale = new Vector2(minSide / maxSide); } } } From e69ec91c072c7f4edac21eb944307a1999c8c485 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Apr 2021 11:25:39 +0900 Subject: [PATCH 068/134] Add xmldoc for `CurrentRotation` --- osu.Game/Rulesets/Mods/ModBarrelRoll.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Mods/ModBarrelRoll.cs b/osu.Game/Rulesets/Mods/ModBarrelRoll.cs index 4c28c730ec..0d344b5269 100644 --- a/osu.Game/Rulesets/Mods/ModBarrelRoll.cs +++ b/osu.Game/Rulesets/Mods/ModBarrelRoll.cs @@ -15,6 +15,10 @@ namespace osu.Game.Rulesets.Mods public abstract class ModBarrelRoll : Mod, IUpdatableByPlayfield, IApplicableToDrawableRuleset where TObject : HitObject { + /// + /// The current angle of rotation being applied by this mod. + /// Generally should be used to apply inverse rotation to elements which should not be rotated. + /// protected float CurrentRotation { get; private set; } [SettingSource("Roll speed", "Rotations per minute")] From e4f895b49046948816dc3f260ba399aad816f153 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Apr 2021 14:48:37 +0900 Subject: [PATCH 069/134] Fix editor buttons inheriting from `TriangleButton` when they have no need to --- .../Edit/Components/RadioButtons/DrawableRadioButton.cs | 4 +--- .../Edit/Components/TernaryButtons/DrawableTernaryButton.cs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs index 0cf7b83f3b..1f608d28fd 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Components.RadioButtons { - public class DrawableRadioButton : TriangleButton + public class DrawableRadioButton : OsuButton { /// /// Invoked when this has been selected. @@ -49,8 +49,6 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons selectedBackgroundColour = colours.BlueDark; selectedBubbleColour = selectedBackgroundColour.Lighten(0.5f); - Triangles.Alpha = 0; - Content.EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, diff --git a/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs b/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs index c72fff5c91..c43561eaa7 100644 --- a/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs +++ b/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Components.TernaryButtons { - internal class DrawableTernaryButton : TriangleButton + internal class DrawableTernaryButton : OsuButton { private Color4 defaultBackgroundColour; private Color4 defaultBubbleColour; @@ -43,8 +43,6 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons selectedBackgroundColour = colours.BlueDark; selectedBubbleColour = selectedBackgroundColour.Lighten(0.5f); - Triangles.Alpha = 0; - Content.EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, From 786ab163f622c0770c2b63a27e54db958881f499 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 30 Apr 2021 12:40:16 -0700 Subject: [PATCH 070/134] Rename extension and move to bottom of file --- ...StatusExtensions.cs => BeatmapSetOnlineStatus.cs} | 12 ++++++------ .../Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 +- .../BeatmapSet/Scores/TopScoreStatisticsSection.cs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game/Beatmaps/{BeatmapSetOnlineStatusExtensions.cs => BeatmapSetOnlineStatus.cs} (86%) diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineStatusExtensions.cs b/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs similarity index 86% rename from osu.Game/Beatmaps/BeatmapSetOnlineStatusExtensions.cs rename to osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs index 1de641f4f1..ae5a44cfcd 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineStatusExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs @@ -3,12 +3,6 @@ namespace osu.Game.Beatmaps { - public static class BeatmapSetOnlineStatusExtensions - { - public static bool HasPerformancePoints(this BeatmapSetOnlineStatus status) - => status == BeatmapSetOnlineStatus.Ranked || status == BeatmapSetOnlineStatus.Approved; - } - public enum BeatmapSetOnlineStatus { None = -3, @@ -20,4 +14,10 @@ namespace osu.Game.Beatmaps Qualified = 3, Loved = 4, } + + public static class BeatmapSetOnlineStatusExtensions + { + public static bool GrantsPerformancePoints(this BeatmapSetOnlineStatus status) + => status == BeatmapSetOnlineStatus.Ranked || status == BeatmapSetOnlineStatus.Approved; + } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 8786cf0e63..e9733bad20 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores var scoreInfos = value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToList(); var topScore = scoreInfos.First(); - scoreTable.DisplayScores(scoreInfos, topScore.Beatmap?.Status.HasPerformancePoints() ?? false); + scoreTable.DisplayScores(scoreInfos, topScore.Beatmap?.Status.GrantsPerformancePoints() ?? false); scoreTable.Show(); var userScore = value.UserScore; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 57df54d851..a4b58e74a6 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -112,7 +112,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores accuracyColumn.Text = value.DisplayAccuracy; maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; - ppColumn.Alpha = value.Beatmap?.Status.HasPerformancePoints() ?? false ? 1 : 0; + ppColumn.Alpha = value.Beatmap?.Status.GrantsPerformancePoints() ?? false ? 1 : 0; ppColumn.Text = $@"{value.PP:N0}"; statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn); From fdf8c129474893b46e7e76b6cc1c19f835c82bcc Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 1 May 2021 11:57:47 +0800 Subject: [PATCH 071/134] Replace BeatDivisorFinder with GetClosestBeatDivisor --- .../Objects/Drawables/DrawableNote.cs | 13 +- .../UI/DrawableManiaRuleset.cs | 6 +- osu.Game.Tests/NonVisual/BeatDivisorFinder.cs | 116 ------------------ .../Rulesets/Objects/BeatDivisorFinder.cs | 55 --------- 4 files changed, 12 insertions(+), 178 deletions(-) delete mode 100644 osu.Game.Tests/NonVisual/BeatDivisorFinder.cs delete mode 100644 osu.Game/Rulesets/Objects/BeatDivisorFinder.cs diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 942a32936c..d67c360301 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -6,10 +6,10 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Skinning.Default; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private OsuColour colours { get; set; } [Resolved(canBeNull: true)] - private BeatDivisorFinder beatDivisorFinder { get; set; } + private IBeatmap beatmap { get; set; } private readonly Bindable configTimingBasedNoteColouring = new Bindable(); @@ -58,9 +58,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void LoadComplete() { - if (beatDivisorFinder != null) + if (beatmap != null) { - HitObject.StartTimeBindable.BindValueChanged(_ => snap.Value = beatDivisorFinder.FindDivisor(HitObject), true); + HitObject.StartTimeBindable.BindValueChanged(startTime => + { + snap.Value = beatmap.ControlPointInfo.GetClosestBeatDivisor(startTime.NewValue); + }, + true + ); } snap.BindValueChanged(_ => updateSnapColour()); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 0177c01240..536d7b39b7 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -45,8 +45,8 @@ namespace osu.Game.Rulesets.Mania.UI public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap; - [Cached] - private BeatDivisorFinder beatDivisorFinder { get; set; } + [Cached(typeof(IBeatmap))] + private ManiaBeatmap cachedBeatmap { get; set; } public IEnumerable BarLines; @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Mania.UI : base(ruleset, beatmap, mods) { BarLines = new BarLineGenerator(Beatmap).BarLines; - beatDivisorFinder = new BeatDivisorFinder(Beatmap); + cachedBeatmap = Beatmap; } [BackgroundDependencyLoader] diff --git a/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs b/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs deleted file mode 100644 index 720d8e8ecd..0000000000 --- a/osu.Game.Tests/NonVisual/BeatDivisorFinder.cs +++ /dev/null @@ -1,116 +0,0 @@ -// 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 NUnit.Framework; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects; - -namespace osu.Game.Tests.NonVisual -{ - public class BeatDivisorFinderTest - { - [Test] - public void TestFindDivisor() - { - const double beat_length = 1000; - - var beatmap = new Beatmap - { - HitObjects = new List - { - new HitObject { StartTime = -beat_length / 3 }, - new HitObject { StartTime = 0 }, - new HitObject { StartTime = beat_length / 16 }, - new HitObject { StartTime = beat_length / 12 }, - new HitObject { StartTime = beat_length / 8 }, - new HitObject { StartTime = beat_length / 6 }, - new HitObject { StartTime = beat_length / 4 }, - new HitObject { StartTime = beat_length / 3 }, - new HitObject { StartTime = beat_length / 2 }, - new HitObject { StartTime = beat_length }, - new HitObject { StartTime = beat_length + beat_length / 7 } - }, - ControlPointInfo = new ControlPointInfo() - }; - - beatmap.ControlPointInfo.Add(0, new TimingControlPoint - { - TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = beat_length - }); - - var beatDivisorFinder = new BeatDivisorFinder(beatmap); - - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[0]), 3); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[1]), 1); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[2]), 16); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[3]), 12); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[4]), 8); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[5]), 6); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[6]), 4); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[7]), 3); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[8]), 2); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[9]), 1); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[10]), 0); - } - - [Test] - public void TestFindDivisorWithTempoChanges() - { - const double first_beat_length = 1000; - const double second_beat_length = 700; - const double third_beat_length = 200; - - const double first_beat_length_start = 0; - const double second_beat_length_start = 1000; - const double third_beat_length_start = 2000; - - var beatmap = new Beatmap - { - HitObjects = new List - { - new HitObject { StartTime = first_beat_length_start }, - new HitObject { StartTime = first_beat_length_start + first_beat_length / 2 }, - new HitObject { StartTime = second_beat_length_start }, - new HitObject { StartTime = second_beat_length_start + second_beat_length / 2 }, - new HitObject { StartTime = third_beat_length_start }, - new HitObject { StartTime = third_beat_length_start + third_beat_length / 2 }, - }, - ControlPointInfo = new ControlPointInfo() - }; - - var firstTimingControlPoint = new TimingControlPoint - { - TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = first_beat_length - }; - - var secondTimingControlPoint = new TimingControlPoint - { - TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = second_beat_length - }; - - var thirdTimingControlPoint = new TimingControlPoint - { - TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = third_beat_length - }; - - beatmap.ControlPointInfo.Add(first_beat_length_start, firstTimingControlPoint); - beatmap.ControlPointInfo.Add(second_beat_length_start, secondTimingControlPoint); - beatmap.ControlPointInfo.Add(third_beat_length_start, thirdTimingControlPoint); - - var beatDivisorFinder = new BeatDivisorFinder(beatmap); - - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[0]), 1); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[1]), 2); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[2]), 1); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[3]), 2); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[4]), 1); - Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[5]), 2); - } - } -} diff --git a/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs b/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs deleted file mode 100644 index 1479b22942..0000000000 --- a/osu.Game/Rulesets/Objects/BeatDivisorFinder.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Utils; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Screens.Edit; - -namespace osu.Game.Rulesets.Objects -{ - /// - /// Used to find the lowest beat divisor that a aligns to in an . - /// - public class BeatDivisorFinder - { - private readonly IBeatmap beatmap; - - /// - /// Creates a new instance. - /// - /// The beatmap to use when calculating beat divisor alignment. - public BeatDivisorFinder(IBeatmap beatmap) - { - this.beatmap = beatmap; - } - - /// - /// Finds the lowest beat divisor that the given aligns to. - /// Returns 0 if it does not align to any divisor. - /// - /// The to evaluate. - public int FindDivisor(HitObject hitObject) - { - TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); - double snapResult = hitObject.StartTime - currentTimingPoint.Time; - - foreach (var divisor in BindableBeatDivisor.VALID_DIVISORS) - { - if (almostDivisibleBy(snapResult, currentTimingPoint.BeatLength / divisor)) - return divisor; - } - - return 0; - } - - private const double leniency_ms = 1.0; - - private static bool almostDivisibleBy(double dividend, double divisor) - { - double remainder = Math.Abs(dividend) % divisor; - return Precision.AlmostEquals(remainder, 0, leniency_ms) || Precision.AlmostEquals(remainder - divisor, 0, leniency_ms); - } - } -} From 0d077b7a5deb9a5ec4f44c5a8335cb063080062b Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 1 May 2021 14:13:42 +0800 Subject: [PATCH 072/134] Fix GetClosestBeatDivisor returning the wrong divisor --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index e47d48edcf..d3a4b635f5 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -7,6 +7,7 @@ using System.Linq; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Framework.Lists; +using osu.Framework.Utils; using osu.Game.Screens.Edit; namespace osu.Game.Beatmaps.ControlPoints @@ -195,7 +196,7 @@ namespace osu.Game.Beatmaps.ControlPoints { double distanceFromSnap = Math.Abs(time - getClosestSnappedTime(timingPoint, time, divisor)); - if (distanceFromSnap < closestTime) + if (Precision.DefinitelyBigger(closestTime, distanceFromSnap)) { closestDivisor = divisor; closestTime = distanceFromSnap; From 0b06c5bcb198aec5a587fa45e035ef76d0665116 Mon Sep 17 00:00:00 2001 From: Justus Franklin Tumacder Date: Sat, 1 May 2021 15:00:18 +0800 Subject: [PATCH 073/134] Remove unneeded test data --- .../TestSceneTimingBasedNoteColouring.cs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs index 5cfd7ff389..e14ad92842 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs @@ -45,15 +45,7 @@ namespace osu.Game.Rulesets.Mania.Tests new Note { StartTime = beat_length } }, ControlPointInfo = new ControlPointInfo(), - BeatmapInfo = - { - BaseDifficulty = new BeatmapDifficulty - { - SliderTickRate = 4, - OverallDifficulty = 10, - }, - Ruleset = ruleset.RulesetInfo - }, + BeatmapInfo = { Ruleset = ruleset.RulesetInfo }, }; foreach (var note in beatmap.HitObjects) @@ -62,11 +54,9 @@ namespace osu.Game.Rulesets.Mania.Tests } beatmap.ControlPointInfo.Add(0, new TimingControlPoint - { - TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple, - BeatLength = beat_length - } - ); + { + BeatLength = beat_length + }); Child = new Container { From db815f793038ca0c0f58a7a70d831a4ff21d8b63 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 May 2021 20:39:10 +0900 Subject: [PATCH 074/134] Tidy up implementation in `DrawableNote` --- .../Objects/Drawables/DrawableNote.cs | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index d67c360301..36565e14aa 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -35,8 +35,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private readonly Drawable headPiece; - private readonly Bindable snap = new Bindable(); - public DrawableNote(Note hitObject) : base(hitObject) { @@ -58,17 +56,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void LoadComplete() { - if (beatmap != null) - { - HitObject.StartTimeBindable.BindValueChanged(startTime => - { - snap.Value = beatmap.ControlPointInfo.GetClosestBeatDivisor(startTime.NewValue); - }, - true - ); - } - - snap.BindValueChanged(_ => updateSnapColour()); + HitObject.StartTimeBindable.BindValueChanged(_ => updateSnapColour()); configTimingBasedNoteColouring.BindValueChanged(_ => updateSnapColour(), true); } @@ -114,9 +102,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private void updateSnapColour() { - Colour = configTimingBasedNoteColouring.Value - ? BindableBeatDivisor.GetColourFor(snap.Value, colours) - : Color4.White; + if (beatmap == null) return; + + int snapDivisor = beatmap.ControlPointInfo.GetClosestBeatDivisor(HitObject.StartTime); + + Colour = configTimingBasedNoteColouring.Value ? BindableBeatDivisor.GetColourFor(snapDivisor, colours) : Color4.White; } } } From a551958eeb413e7e4a4b34b72cc8ed53b14f6d5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 May 2021 21:32:45 +0900 Subject: [PATCH 075/134] Move caching of `IBeatmap` to base `DrawableRuleset` --- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 4 ---- osu.Game/Rulesets/UI/DrawableRuleset.cs | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 536d7b39b7..4ee060e91e 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -45,9 +45,6 @@ namespace osu.Game.Rulesets.Mania.UI public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap; - [Cached(typeof(IBeatmap))] - private ManiaBeatmap cachedBeatmap { get; set; } - public IEnumerable BarLines; protected override bool RelativeScaleBeatLengths => true; @@ -80,7 +77,6 @@ namespace osu.Game.Rulesets.Mania.UI : base(ruleset, beatmap, mods) { BarLines = new BarLineGenerator(Beatmap).BarLines; - cachedBeatmap = Beatmap; } [BackgroundDependencyLoader] diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index ca27e6b21a..a2dade2627 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -85,6 +85,7 @@ namespace osu.Game.Rulesets.UI /// /// The beatmap. /// + [Cached(typeof(IBeatmap))] public readonly Beatmap Beatmap; public override IEnumerable Objects => Beatmap.HitObjects; From 137be5dc971b6f6fddc300ac9dafc0512a38295f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 1 May 2021 14:14:07 -0700 Subject: [PATCH 076/134] Use equality operator instead of null coalescing Co-Authored-By: Salman Ahmed --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 +- .../Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index e9733bad20..aff48919b4 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores var scoreInfos = value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToList(); var topScore = scoreInfos.First(); - scoreTable.DisplayScores(scoreInfos, topScore.Beatmap?.Status.GrantsPerformancePoints() ?? false); + scoreTable.DisplayScores(scoreInfos, topScore.Beatmap?.Status.GrantsPerformancePoints() == true); scoreTable.Show(); var userScore = value.UserScore; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index a4b58e74a6..262f321598 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -112,7 +112,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores accuracyColumn.Text = value.DisplayAccuracy; maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; - ppColumn.Alpha = value.Beatmap?.Status.GrantsPerformancePoints() ?? false ? 1 : 0; + ppColumn.Alpha = value.Beatmap?.Status.GrantsPerformancePoints() == true ? 1 : 0; ppColumn.Text = $@"{value.PP:N0}"; statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn); From 07fe99025f9e2493e86a91ac078c509675b010d2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 1 May 2021 15:05:12 +0300 Subject: [PATCH 077/134] Use bounding box of blueprint for computing selection box area --- .../Screens/Edit/Compose/Components/SelectionHandler.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index cb3424a250..c11c20df2a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; @@ -332,8 +333,9 @@ namespace osu.Game.Screens.Edit.Compose.Components foreach (var blueprint in selectedBlueprints) { - topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(blueprint.SelectionQuad.TopLeft)); - bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(blueprint.SelectionQuad.BottomRight)); + var blueprintRect = blueprint.SelectionQuad.AABBFloat; + topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(blueprintRect.TopLeft)); + bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(blueprintRect.BottomRight)); } topLeft -= new Vector2(5); From 0aa17e7c955b93e4b0b2283279ebdd16fcf9e7c7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 2 May 2021 02:51:06 +0300 Subject: [PATCH 078/134] Rewrite selection box computation logic with `RectangleF`'s helper methods --- .../Compose/Components/SelectionHandler.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index c11c20df2a..8335ece236 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -328,21 +328,15 @@ namespace osu.Game.Screens.Edit.Compose.Components return; // Move the rectangle to cover the items - var topLeft = new Vector2(float.MaxValue, float.MaxValue); - var bottomRight = new Vector2(float.MinValue, float.MinValue); + RectangleF selectionRect = ToLocalSpace(selectedBlueprints.First().SelectionQuad).AABBFloat; - foreach (var blueprint in selectedBlueprints) - { - var blueprintRect = blueprint.SelectionQuad.AABBFloat; - topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(blueprintRect.TopLeft)); - bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(blueprintRect.BottomRight)); - } + foreach (var blueprint in selectedBlueprints.Skip(1)) + selectionRect = RectangleF.Union(selectionRect, ToLocalSpace(blueprint.SelectionQuad).AABBFloat); - topLeft -= new Vector2(5); - bottomRight += new Vector2(5); + selectionRect = selectionRect.Inflate(5f); - content.Size = bottomRight - topLeft; - content.Position = topLeft; + content.Position = selectionRect.Location; + content.Size = selectionRect.Size; } #endregion From b83aa0bd76e59007e7e8063aefe34bc16ed58841 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 2 May 2021 06:21:14 +0300 Subject: [PATCH 079/134] Avoid LINQ in update --- .../Screens/Edit/Compose/Components/SelectionHandler.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 8335ece236..917cbca4e1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -328,10 +328,10 @@ namespace osu.Game.Screens.Edit.Compose.Components return; // Move the rectangle to cover the items - RectangleF selectionRect = ToLocalSpace(selectedBlueprints.First().SelectionQuad).AABBFloat; + RectangleF selectionRect = ToLocalSpace(selectedBlueprints[0].SelectionQuad).AABBFloat; - foreach (var blueprint in selectedBlueprints.Skip(1)) - selectionRect = RectangleF.Union(selectionRect, ToLocalSpace(blueprint.SelectionQuad).AABBFloat); + for (int i = 1; i < selectedBlueprints.Count; i++) + selectionRect = RectangleF.Union(selectionRect, ToLocalSpace(selectedBlueprints[i].SelectionQuad).AABBFloat); selectionRect = selectionRect.Inflate(5f); From 3aa18e19c93272515a293946b4b468deea3fb1e8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 2 May 2021 11:30:44 +0300 Subject: [PATCH 080/134] Revert "Bump Humanizer from 2.8.26 to 2.9.9" This reverts commit 1e7feff49d57fc2f0575a8a423083e0ff9a44d65. --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b25e462453..1e0eabfff7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -19,7 +19,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index bbf0f6046c..e26e727e69 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -89,7 +89,7 @@ - + From 59cb5f4679aab9b861fa3ca0b2c6ed473b22d330 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 24 Apr 2021 09:26:43 -0700 Subject: [PATCH 081/134] Get recent count from api instead --- .../Profile/Sections/Ranks/PaginatedScoreContainer.cs | 6 +++--- osu.Game/Users/User.cs | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 53f6d375ca..9ac9040a98 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -39,6 +39,9 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks case ScoreType.Firsts: return user.ScoresFirstCount; + case ScoreType.Recent: + return user.ScoresRecentCount; + default: return 0; } @@ -50,9 +53,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks drawableItemIndex = 0; base.OnItemsReceived(items); - - if (type == ScoreType.Recent) - SetCount(items.Count); } protected override APIRequest> CreateRequest() => diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 74ffb7c457..beb41c3b06 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -147,6 +147,9 @@ namespace osu.Game.Users [JsonProperty(@"scores_first_count")] public int ScoresFirstCount; + [JsonProperty(@"scores_recent_count")] + public int ScoresRecentCount; + [JsonProperty(@"beatmap_playcounts_count")] public int BeatmapPlaycountsCount; From 3e74d61dab44ea25341aebd79cd02fe6792c1a05 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 24 Apr 2021 09:27:32 -0700 Subject: [PATCH 082/134] Add best count from api --- .../Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs | 3 +++ osu.Game/Users/User.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 9ac9040a98..d06e0c87fc 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -36,6 +36,9 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { switch (type) { + case ScoreType.Best: + return user.ScoresBestCount; + case ScoreType.Firsts: return user.ScoresFirstCount; diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index beb41c3b06..2e04693e82 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -144,6 +144,9 @@ namespace osu.Game.Users [JsonProperty(@"unranked_beatmapset_count")] public int UnrankedBeatmapsetCount; + [JsonProperty(@"scores_best_count")] + public int ScoresBestCount; + [JsonProperty(@"scores_first_count")] public int ScoresFirstCount; From cc056088bdf0cbf988f7b8185addbedd669ebb95 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 2 May 2021 14:31:06 -0700 Subject: [PATCH 083/134] Update profile subsections to use counters instead of missing text in line with web --- .../Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs | 2 +- .../Historical/PaginatedMostPlayedBeatmapContainer.cs | 2 +- osu.Game/Overlays/Profile/Sections/HistoricalSection.cs | 2 +- .../Overlays/Profile/Sections/PaginatedProfileSubsection.cs | 4 ++-- .../Profile/Sections/Ranks/PaginatedScoreContainer.cs | 4 ++-- osu.Game/Overlays/Profile/Sections/RanksSection.cs | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 780d7ea986..fe9c710bcc 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps private readonly BeatmapSetType type; public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string headerText) - : base(user, headerText, "", CounterVisibilityState.AlwaysVisible) + : base(user, headerText) { this.type = type; ItemsPerPage = 6; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index e5bb1f8008..eeb14e5e4f 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical public class PaginatedMostPlayedBeatmapContainer : PaginatedProfileSubsection { public PaginatedMostPlayedBeatmapContainer(Bindable user) - : base(user, "Most Played Beatmaps", "No records. :(", CounterVisibilityState.AlwaysVisible) + : base(user, "Most Played Beatmaps") { ItemsPerPage = 5; } diff --git a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs index 6e2b9873cf..4fbb7fc7d7 100644 --- a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs +++ b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Profile.Sections { new PlayHistorySubsection(User), new PaginatedMostPlayedBeatmapContainer(User), - new PaginatedScoreContainer(ScoreType.Recent, User, "Recent Plays (24h)", CounterVisibilityState.VisibleWhenZero), + new PaginatedScoreContainer(ScoreType.Recent, User, "Recent Plays (24h)"), new ReplaysSubsection(User) }; } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs index 51e5622f68..e237b43b2e 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs @@ -38,8 +38,8 @@ namespace osu.Game.Overlays.Profile.Sections private OsuSpriteText missing; private readonly string missingText; - protected PaginatedProfileSubsection(Bindable user, string headerText = "", string missingText = "", CounterVisibilityState counterVisibilityState = CounterVisibilityState.AlwaysHidden) - : base(user, headerText, counterVisibilityState) + protected PaginatedProfileSubsection(Bindable user, string headerText = "", string missingText = "") + : base(user, headerText, CounterVisibilityState.AlwaysVisible) { this.missingText = missingText; } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index d06e0c87fc..720cd4a3db 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -18,8 +18,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { private readonly ScoreType type; - public PaginatedScoreContainer(ScoreType type, Bindable user, string headerText, CounterVisibilityState counterVisibilityState, string missingText = "") - : base(user, headerText, missingText, counterVisibilityState) + public PaginatedScoreContainer(ScoreType type, Bindable user, string headerText) + : base(user, headerText) { this.type = type; diff --git a/osu.Game/Overlays/Profile/Sections/RanksSection.cs b/osu.Game/Overlays/Profile/Sections/RanksSection.cs index e41e414893..33f7c2f71a 100644 --- a/osu.Game/Overlays/Profile/Sections/RanksSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RanksSection.cs @@ -16,8 +16,8 @@ namespace osu.Game.Overlays.Profile.Sections { Children = new[] { - new PaginatedScoreContainer(ScoreType.Best, User, "Best Performance", CounterVisibilityState.AlwaysHidden, "No performance records. :("), - new PaginatedScoreContainer(ScoreType.Firsts, User, "First Place Ranks", CounterVisibilityState.AlwaysVisible) + new PaginatedScoreContainer(ScoreType.Best, User, "Best Performance"), + new PaginatedScoreContainer(ScoreType.Firsts, User, "First Place Ranks") }; } } From b2130fc600d8cff184ba6e51bc3ef7dbeed2f44c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 3 May 2021 01:56:32 +0300 Subject: [PATCH 084/134] Fix replay frames sort instability --- osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 0f25a45177..d6c9b9c6d9 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -4,7 +4,7 @@ #nullable enable using System; -using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; using osu.Game.Input.Handlers; using osu.Game.Replays; @@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Replays { // TODO: This replay frame ordering should be enforced on the Replay type. // Currently, the ordering can be broken if the frames are added after this construction. - replay.Frames.Sort((x, y) => x.Time.CompareTo(y.Time)); + replay.Frames = replay.Frames.OrderBy(f => f.Time).ToList(); this.replay = replay; currentFrameIndex = -1; From 943c497397245fdf1924860b951c89940e3b235e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 3 May 2021 02:02:14 +0300 Subject: [PATCH 085/134] Return back removed using --- osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index d6c9b9c6d9..bc8994bbe5 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -4,6 +4,7 @@ #nullable enable using System; +using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using osu.Game.Input.Handlers; From 8c9cfb63013df07e0942e07fdb10918299cc034d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 14:28:35 +0900 Subject: [PATCH 086/134] Remove unsafe access to Composer.HitObjects --- .../Edit/Compose/Components/EditorBlueprintContainer.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs index 2a605f75d8..29dfff0e96 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs @@ -34,13 +34,6 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - // For non-pooled rulesets, hitobjects are already present in the playfield which allows the blueprints to be loaded in the async context. - if (Composer != null) - { - foreach (var obj in Composer.HitObjects) - AddBlueprintFor(obj.HitObject); - } - selectedHitObjects.BindTo(Beatmap.SelectedHitObjects); selectedHitObjects.CollectionChanged += (selectedObjects, args) => { From f3b305bbe62f4501579cd36ca6e77c188fb344ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 14:58:23 +0900 Subject: [PATCH 087/134] Rename and improve xmldoc of `SkinEditorOverlay` --- osu.Game/OsuGame.cs | 4 ++-- .../{SkinEditorContainer.cs => SkinEditorOverlay.cs} | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) rename osu.Game/Skinning/Editor/{SkinEditorContainer.cs => SkinEditorOverlay.cs} (91%) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 77fb9c3b63..d031a8e7fa 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -688,7 +688,7 @@ namespace osu.Game var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); - loadComponentSingleFile(skinEditor = new SkinEditorContainer(screenContainer), overlayContent.Add); + loadComponentSingleFile(skinEditor = new SkinEditorOverlay(screenContainer), overlayContent.Add); loadComponentSingleFile(new LoginOverlay { @@ -946,7 +946,7 @@ namespace osu.Game private ScalingContainer screenContainer; - private SkinEditorContainer skinEditor; + private SkinEditorOverlay skinEditor; protected override bool OnExiting() { diff --git a/osu.Game/Skinning/Editor/SkinEditorContainer.cs b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs similarity index 91% rename from osu.Game/Skinning/Editor/SkinEditorContainer.cs rename to osu.Game/Skinning/Editor/SkinEditorOverlay.cs index adb1abefd1..06c6dffb60 100644 --- a/osu.Game/Skinning/Editor/SkinEditorContainer.cs +++ b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs @@ -13,9 +13,10 @@ using osu.Game.Input.Bindings; namespace osu.Game.Skinning.Editor { /// - /// A container which handles loading a skin editor on user request. + /// A container which handles loading a skin editor on user request for a specified target. + /// This also handles the scaling / positioning adjustment of the target. /// - public class SkinEditorContainer : CompositeDrawable, IKeyBindingHandler + public class SkinEditorOverlay : CompositeDrawable, IKeyBindingHandler { private readonly ScalingContainer target; private SkinEditor skinEditor; @@ -25,7 +26,7 @@ namespace osu.Game.Skinning.Editor [Resolved] private OsuColour colours { get; set; } - public SkinEditorContainer(ScalingContainer target) + public SkinEditorOverlay(ScalingContainer target) { this.target = target; RelativeSizeAxes = Axes.Both; From 3dd4b7b746ab72532ec0e5db0777edcce99afc6f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:08:34 +0900 Subject: [PATCH 088/134] Fix use of non-existent word in `OsuFocusedOverlayContainer` xmldoc --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index e168f265dd..c0518247a9 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -28,7 +28,7 @@ namespace osu.Game.Graphics.Containers protected override bool BlockNonPositionalInput => true; /// - /// Temporary to allow for overlays in the main screen content to not dim theirselves. + /// Temporary to allow for overlays in the main screen content to not dim themselves. /// Should be eventually replaced by dimming which is aware of the target dim container (traverse parent for certain interface type?). /// protected virtual bool DimMainContent => true; From 01984de9c7ce603e063f914942775d55fe8793e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:13:32 +0900 Subject: [PATCH 089/134] Use existing `GetStateFromSelection` helper function --- .../Compose/Components/EditorSelectionHandler.cs | 11 ----------- .../Edit/Compose/Components/SelectionHandler.cs | 11 +++++++++++ osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 14 +------------- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 0fc305dcc4..6ab4ca8267 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -108,17 +108,6 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - /// - /// Given a selection target and a function of truth, retrieve the correct ternary state for display. - /// - protected TernaryState GetStateFromSelection(IEnumerable selection, Func func) - { - if (selection.Any(func)) - return selection.All(func) ? TernaryState.True : TernaryState.Indeterminate; - - return TernaryState.False; - } - #endregion #region Ternary state changes diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index cb3424a250..c0dbc5e7db 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -268,6 +268,17 @@ namespace osu.Game.Screens.Edit.Compose.Components DeleteSelected(); } + /// + /// Given a selection target and a function of truth, retrieve the correct ternary state for display. + /// + protected static TernaryState GetStateFromSelection(IEnumerable selection, Func func) + { + if (selection.Any(func)) + return selection.All(func) ? TernaryState.True : TernaryState.Indeterminate; + + return TernaryState.False; + } + /// /// Called whenever the deletion of items has been requested. /// diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 0408ce74a6..044ad88333 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -53,21 +53,9 @@ namespace osu.Game.Skinning.Editor return displayableAnchors.Select(a => { - var countExisting = selection.Count(b => ((Drawable)b.Item).Anchor == a); - var countTotal = selection.Count(); - - TernaryState state; - - if (countExisting == countTotal) - state = TernaryState.True; - else if (countExisting > 0) - state = TernaryState.Indeterminate; - else - state = TernaryState.False; - return new AnchorMenuItem(a, selection, _ => applyAnchor(a)) { - State = { Value = state } + State = { Value = GetStateFromSelection(selection, c => ((Drawable)c.Item).Anchor == a) } }; }); } From a2faa0b74c5c10b89d5f06ded55abe6d68c9bfbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:13:53 +0900 Subject: [PATCH 090/134] Remove dead code --- osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 044ad88333..8792daef19 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -125,11 +125,6 @@ namespace osu.Game.Skinning.Editor { } - private void updateState(TernaryState obj) - { - throw new NotImplementedException(); - } - private static TernaryState getNextState(TernaryState state) => TernaryState.True; } } From 51f4077b2714b61db68db48706546c86a1125238 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:15:00 +0900 Subject: [PATCH 091/134] Reorder methods in `SkinSelectionHandler` to follow standards --- .../Skinning/Editor/SkinSelectionHandler.cs | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 8792daef19..c7c0f45cc0 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -17,6 +17,46 @@ namespace osu.Game.Skinning.Editor { public class SkinSelectionHandler : SelectionHandler { + public override bool HandleRotation(float angle) + { + // TODO: this doesn't correctly account for origin/anchor specs being different in a multi-selection. + foreach (var c in SelectedBlueprints) + ((Drawable)c.Item).Rotation += angle; + + return base.HandleRotation(angle); + } + + public override bool HandleScale(Vector2 scale, Anchor anchor) + { + adjustScaleFromAnchor(ref scale, anchor); + + foreach (var c in SelectedBlueprints) + ((Drawable)c.Item).Scale += scale * 0.01f; + + return true; + } + + public override bool HandleMovement(MoveSelectionEvent moveEvent) + { + foreach (var c in SelectedBlueprints) + { + Drawable drawable = (Drawable)c.Item; + drawable.Position += drawable.ScreenSpaceDeltaToParentSpace(moveEvent.ScreenSpaceDelta); + } + + return true; + } + + protected override void OnSelectionChanged() + { + base.OnSelectionChanged(); + + SelectionBox.CanRotate = true; + SelectionBox.CanScaleX = true; + SelectionBox.CanScaleY = true; + SelectionBox.CanReverse = false; + } + protected override void DeleteItems(IEnumerable items) { foreach (var i in items) @@ -67,46 +107,6 @@ namespace osu.Game.Skinning.Editor ((Drawable)item).Anchor = anchor; } - protected override void OnSelectionChanged() - { - base.OnSelectionChanged(); - - SelectionBox.CanRotate = true; - SelectionBox.CanScaleX = true; - SelectionBox.CanScaleY = true; - SelectionBox.CanReverse = false; - } - - public override bool HandleRotation(float angle) - { - // TODO: this doesn't correctly account for origin/anchor specs being different in a multi-selection. - foreach (var c in SelectedBlueprints) - ((Drawable)c.Item).Rotation += angle; - - return base.HandleRotation(angle); - } - - public override bool HandleScale(Vector2 scale, Anchor anchor) - { - adjustScaleFromAnchor(ref scale, anchor); - - foreach (var c in SelectedBlueprints) - ((Drawable)c.Item).Scale += scale * 0.01f; - - return true; - } - - public override bool HandleMovement(MoveSelectionEvent moveEvent) - { - foreach (var c in SelectedBlueprints) - { - Drawable drawable = (Drawable)c.Item; - drawable.Position += drawable.ScreenSpaceDeltaToParentSpace(moveEvent.ScreenSpaceDelta); - } - - return true; - } - private static void adjustScaleFromAnchor(ref Vector2 scale, Anchor reference) { // cancel out scale in axes we don't care about (based on which drag handle was used). From f36684a070308f6068a709b68dba2d67906bb632 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:17:01 +0900 Subject: [PATCH 092/134] Guard against non-threadsafe transformation logic in `ScalingContainer`- --- osu.Game/Graphics/Containers/ScalingContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index b691e372c5..2488fd14d0 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -50,7 +50,7 @@ namespace osu.Game.Graphics.Containers return; allowScaling = value; - updateSize(); + if (IsLoaded) updateSize(); } } From df8609b3dc6307a7d9e91b5f6a2df13a2b5d824d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:15:50 +0900 Subject: [PATCH 093/134] Move private field for skin editor overlay to where others exist --- osu.Game/OsuGame.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d031a8e7fa..b1173784b5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -80,6 +80,8 @@ namespace osu.Game private BeatmapSetOverlay beatmapSetOverlay; + private SkinEditorOverlay skinEditor; + [Cached] private readonly DifficultyRecommender difficultyRecommender = new DifficultyRecommender(); @@ -946,8 +948,6 @@ namespace osu.Game private ScalingContainer screenContainer; - private SkinEditorOverlay skinEditor; - protected override bool OnExiting() { if (ScreenStack.CurrentScreen is Loader) From a298a930701b337248823aa901364786c4ef19d7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:18:18 +0900 Subject: [PATCH 094/134] Remove redundant storage of blueprint's related item --- osu.Game/Skinning/Editor/SkinBlueprint.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinBlueprint.cs b/osu.Game/Skinning/Editor/SkinBlueprint.cs index 491a403325..11409c46ab 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprint.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprint.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Screens.Play.HUD; using osuTK; @@ -17,26 +16,20 @@ namespace osu.Game.Skinning.Editor { public class SkinBlueprint : SelectionBlueprint { - /// - /// The which this applies to. - /// - public readonly ISkinnableComponent Component; - private Container box; - private Drawable drawable => (Drawable)Component; + private Drawable drawable => (Drawable)Item; /// - /// Whether the blueprint should be shown even when the is not alive. + /// Whether the blueprint should be shown even when the is not alive. /// protected virtual bool AlwaysShowWhenSelected => false; - protected override bool ShouldBeAlive => (drawable.IsAlive && Component.IsPresent) || (AlwaysShowWhenSelected && State == SelectionState.Selected); + protected override bool ShouldBeAlive => (drawable.IsAlive && Item.IsPresent) || (AlwaysShowWhenSelected && State == SelectionState.Selected); public SkinBlueprint(ISkinnableComponent component) : base(component) { - Component = component; } [BackgroundDependencyLoader] From 7d8be8cd836dda2a401f4de40d70a680f7e6e958 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:20:00 +0900 Subject: [PATCH 095/134] Add comment about why we are running `checkForComponents` on a timer --- osu.Game/Skinning/Editor/SkinBlueprintContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs index f2bc8ecddf..d9bfefe5f2 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -30,6 +30,8 @@ namespace osu.Game.Skinning.Editor { foreach (var c in target.ChildrenOfType().ToArray()) AddBlueprintFor(c); + // We'd hope to eventually be running this in a more sensible way, but this handles situations where new drawables become present (ie. during ongoing gameplay) + // or when drawables in the target are loaded asynchronously and may not be immediately available when this BlueprintContainer is loaded. Scheduler.AddDelayed(checkForComponents, 1000); } From 15603de6e946c4570cb3c9befc68114e162a0c11 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:24:51 +0900 Subject: [PATCH 096/134] Change scale multiplier to be closer to expectations --- osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index c7c0f45cc0..d09ba8af0e 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -31,7 +31,8 @@ namespace osu.Game.Skinning.Editor adjustScaleFromAnchor(ref scale, anchor); foreach (var c in SelectedBlueprints) - ((Drawable)c.Item).Scale += scale * 0.01f; + // TODO: this is temporary and will be fixed with a separate refactor of selection transform logic. + ((Drawable)c.Item).Scale += scale * 0.02f; return true; } From 4cfa858dc4cd02cbf438ea9863d57a1c26568c63 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:37:15 +0900 Subject: [PATCH 097/134] Fix tooltips displaying for hidden `SelectionHandler` content --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index c0dbc5e7db..053e532137 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -57,7 +57,6 @@ namespace osu.Game.Screens.Edit.Compose.Components RelativeSizeAxes = Axes.Both; AlwaysPresent = true; - Alpha = 0; } [BackgroundDependencyLoader] @@ -318,7 +317,7 @@ namespace osu.Game.Screens.Edit.Compose.Components selectionDetailsText.Text = count > 0 ? count.ToString() : string.Empty; - this.FadeTo(count > 0 ? 1 : 0); + content.FadeTo(count > 0 ? 1 : 0); OnSelectionChanged(); } From 839ac968a9623bbabaabf3ea1d5087ef78f0ad7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 15:37:15 +0900 Subject: [PATCH 098/134] Fix tooltips displaying for hidden `SelectionHandler` content --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 917cbca4e1..f207e27a5e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -58,7 +58,6 @@ namespace osu.Game.Screens.Edit.Compose.Components RelativeSizeAxes = Axes.Both; AlwaysPresent = true; - Alpha = 0; } [BackgroundDependencyLoader] @@ -308,7 +307,7 @@ namespace osu.Game.Screens.Edit.Compose.Components selectionDetailsText.Text = count > 0 ? count.ToString() : string.Empty; - this.FadeTo(count > 0 ? 1 : 0); + content.FadeTo(count > 0 ? 1 : 0); OnSelectionChanged(); } From 3268a75f05afc1515b3feb874a4aa72bfb1d0173 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 17:34:34 +0900 Subject: [PATCH 099/134] Remove intermediate container to fix tests --- .../Editing/TestSceneEditorClipboard.cs | 4 +- .../Edit/Compose/Components/SelectionBox.cs | 48 ++++++++++++++++--- .../Compose/Components/SelectionHandler.cs | 42 ++-------------- 3 files changed, 48 insertions(+), 46 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs index 3a063af843..3aff74a0a8 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs @@ -132,8 +132,8 @@ namespace osu.Game.Tests.Visual.Editing { AddStep("deselect", () => EditorBeatmap.SelectedHitObjects.Clear()); - AddUntilStep("timeline selection box is not visible", () => Editor.ChildrenOfType().First().ChildrenOfType().First().Alpha == 0); - AddUntilStep("composer selection box is not visible", () => Editor.ChildrenOfType().First().ChildrenOfType().First().Alpha == 0); + AddUntilStep("timeline selection box is not visible", () => Editor.ChildrenOfType().First().ChildrenOfType().First().Alpha == 0); + AddUntilStep("composer selection box is not visible", () => Editor.ChildrenOfType().First().ChildrenOfType().First().Alpha == 0); } AddStep("paste hitobject", () => Editor.Paste()); diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 9d6b44e207..0d6cfc0689 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Input; @@ -16,6 +17,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { public class SelectionBox : CompositeDrawable { + public const float BORDER_RADIUS = 3; + public Func OnRotation; public Func OnScale; public Func OnFlip; @@ -92,21 +95,32 @@ namespace osu.Game.Screens.Edit.Compose.Components } } + private string text; + + public string Text + { + get => text; + set + { + if (value == text) + return; + + text = value; + if (selectionDetailsText != null) + selectionDetailsText.Text = value; + } + } + private Container dragHandles; private FillFlowContainer buttons; - public const float BORDER_RADIUS = 3; + private OsuSpriteText selectionDetailsText; [Resolved] private OsuColour colours { get; set; } [BackgroundDependencyLoader] - private void load() - { - RelativeSizeAxes = Axes.Both; - - recreate(); - } + private void load() => recreate(); protected override bool OnKeyDown(KeyDownEvent e) { @@ -144,6 +158,26 @@ namespace osu.Game.Screens.Edit.Compose.Components InternalChildren = new Drawable[] { + new Container + { + Name = "info text", + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + Colour = colours.YellowDark, + RelativeSizeAxes = Axes.Both, + }, + selectionDetailsText = new OsuSpriteText + { + Padding = new MarginPadding(2), + Colour = colours.Gray0, + Font = OsuFont.Default.With(size: 11), + Text = text, + } + } + }, new Container { Masking = true, diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index f207e27a5e..ce0a72a012 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -10,13 +10,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; 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 osuTK; @@ -43,10 +41,6 @@ namespace osu.Game.Screens.Edit.Compose.Components private readonly List> selectedBlueprints; - private Drawable content; - - private OsuSpriteText selectionDetailsText; - protected SelectionBox SelectionBox { get; private set; } [Resolved(CanBeNull = true)] @@ -63,33 +57,7 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - InternalChild = content = new Container - { - Children = new Drawable[] - { - // todo: should maybe be inside the SelectionBox? - new Container - { - Name = "info text", - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - Colour = colours.YellowDark, - RelativeSizeAxes = Axes.Both, - }, - selectionDetailsText = new OsuSpriteText - { - Padding = new MarginPadding(2), - Colour = colours.Gray0, - Font = OsuFont.Default.With(size: 11) - } - } - }, - SelectionBox = CreateSelectionBox(), - } - }; + InternalChild = SelectionBox = CreateSelectionBox(); SelectedItems.CollectionChanged += (sender, args) => { @@ -305,9 +273,9 @@ namespace osu.Game.Screens.Edit.Compose.Components { int count = SelectedItems.Count; - selectionDetailsText.Text = count > 0 ? count.ToString() : string.Empty; + SelectionBox.Text = count > 0 ? count.ToString() : string.Empty; - content.FadeTo(count > 0 ? 1 : 0); + SelectionBox.FadeTo(count > 0 ? 1 : 0); OnSelectionChanged(); } @@ -334,8 +302,8 @@ namespace osu.Game.Screens.Edit.Compose.Components selectionRect = selectionRect.Inflate(5f); - content.Position = selectionRect.Location; - content.Size = selectionRect.Size; + SelectionBox.Position = selectionRect.Location; + SelectionBox.Size = selectionRect.Size; } #endregion From b28e1569caad7b6a1781dc32129f57a9d74cc92c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 20:09:48 +0900 Subject: [PATCH 100/134] Remove no-longer-relevant matching comment --- .../Screens/Edit/Compose/Components/EditorBlueprintContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs index 29dfff0e96..db322faf65 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs @@ -62,7 +62,6 @@ namespace osu.Game.Screens.Edit.Compose.Components if (Composer != null) { - // For pooled rulesets, blueprints must be added for hitobjects already "current" as they would've not been "current" during the async load addition process above. foreach (var obj in Composer.HitObjects) AddBlueprintFor(obj.HitObject); From e00af3e71d2f2f754e641698dede05e3ac089b5b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 4 May 2021 09:45:58 +0300 Subject: [PATCH 101/134] Add test coverage --- .../NonVisual/FramedReplayInputHandlerTest.cs | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index a42b7d54ee..2062c4b820 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; +using osu.Framework.Utils; using osu.Game.Replays; using osu.Game.Rulesets.Replays; @@ -278,6 +280,38 @@ namespace osu.Game.Tests.NonVisual setTime(-100, -100); } + [Test] + public void TestReplayFrameSortStability() + { + const double repeating_time = 5000; + + int data = 0; + + // 1. add a range of frames in which some of them have the constant time 5000, all without any "data". + // 2. randomize the frames. + // 3. assign "data" to each frame in ascending order. + replay.Frames.AddRange(Enumerable.Range(1, 250).Select(i => + { + if (RNG.NextBool()) + return new TestReplayFrame(repeating_time, true); + else + return new TestReplayFrame(i * 1000, true); + }).OrderBy(_ => RNG.Next()).Select(f => new TestReplayFrame(f.Time, true, ++data))); + + replay.HasReceivedAllFrames = true; + + // create a new handler with the replay for the frames to be sorted. + handler = new TestInputHandler(replay); + + // ensure sort stability by checking whether the "data" assigned to each time-repeated frame is in ascending order, as it was before sort. + var repeatingTimeFramesData = replay.Frames + .Cast() + .Where(f => f.Time == repeating_time) + .Select(f => f.Data); + + Assert.That(repeatingTimeFramesData, Is.Ordered.Ascending); + } + private void setReplayFrames() { replay.Frames = new List @@ -324,11 +358,13 @@ namespace osu.Game.Tests.NonVisual private class TestReplayFrame : ReplayFrame { public readonly bool IsImportant; + public readonly int Data; - public TestReplayFrame(double time, bool isImportant = false) + public TestReplayFrame(double time, bool isImportant = false, int data = 0) : base(time) { IsImportant = isImportant; + Data = data; } } From ffc88db47aa7377e78a6db933723a314a937e933 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 May 2021 16:04:59 +0900 Subject: [PATCH 102/134] Implement Duration via the interface --- osu.Game/Storyboards/IStoryboardElementWithDuration.cs | 2 +- osu.Game/Storyboards/StoryboardSprite.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs index 02b438cb76..55f163ee07 100644 --- a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs @@ -16,6 +16,6 @@ namespace osu.Game.Storyboards /// /// The duration of the StoryboardElement. /// - double Duration { get; } + double Duration => EndTime - StartTime; } } diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 0aaf264341..bf87e7d10e 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -65,8 +65,6 @@ namespace osu.Game.Storyboards } } - public double Duration => EndTime - StartTime; - public bool HasCommands => TimelineGroup.HasCommands || loops.Any(l => l.HasCommands); private delegate void DrawablePropertyInitializer(Drawable drawable, T value); From b30145de40646e893d3123133fd46d67e52c23b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 May 2021 16:35:50 +0900 Subject: [PATCH 103/134] Specify explicit primitive type --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 1a11adad30..d424f90079 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -640,7 +640,7 @@ namespace osu.Game.Screens.Play return; } - var storyboardHasOutro = DimmableStoryboard.ContentDisplayed && !DimmableStoryboard.HasStoryboardEnded.Value; + bool storyboardHasOutro = DimmableStoryboard.ContentDisplayed && !DimmableStoryboard.HasStoryboardEnded.Value; if (storyboardHasOutro) { From 4c7a4239f818662055b08f610b7ab588a3520042 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 May 2021 16:36:05 +0900 Subject: [PATCH 104/134] Fix `AllowGameplayOverlays` potentially not working for outro skip overlay --- osu.Game/Screens/Play/Player.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d424f90079..6ed1a87d8a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -245,8 +245,6 @@ namespace osu.Game.Screens.Play HUDOverlay.ShowHud.Value = false; HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); - skipIntroOverlay.Hide(); - skipOutroOverlay.Hide(); } DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => @@ -398,7 +396,7 @@ namespace osu.Game.Screens.Play } }; - if (!Configuration.AllowSkipping) + if (!Configuration.AllowSkipping || !DrawableRuleset.AllowGameplayOverlays) { skipIntroOverlay.Expire(); skipOutroOverlay.Expire(); From b380be7169de5b4e2ca066d27fd5970a624e5cfb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 May 2021 16:43:51 +0900 Subject: [PATCH 105/134] Add xmldoc for `updateCompletionState` --- osu.Game/Screens/Play/Player.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 6ed1a87d8a..cf26bc479a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -582,6 +582,11 @@ namespace osu.Game.Screens.Play private ScheduledDelegate completionProgressDelegate; private Task prepareScoreForDisplayTask; + /// + /// Handles changes in player state which may progress the completion of gameplay / this screen's lifetime. + /// + /// If in a state where a storyboard outro is to be played, offers the choice of skipping beyond it. + /// Thrown if this method is called more than once without changing state. private void updateCompletionState(bool skipStoryboardOutro = false) { // screen may be in the exiting transition phase. From 18779b1d1e8fa6d6b9fdb4e0d389b8b7f0d08d54 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 May 2021 16:48:13 +0900 Subject: [PATCH 106/134] Cache last event time value to avoid super expensive LINQ --- .../Drawables/DrawableStoryboard.cs | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index a9a8b8a4ac..4c42823779 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -20,6 +20,13 @@ namespace osu.Game.Storyboards.Drawables [Cached] public Storyboard Storyboard { get; } + /// + /// Whether the storyboard is considered finished. + /// + public IBindable HasStoryboardEnded => hasStoryboardEnded; + + private readonly BindableBool hasStoryboardEnded = new BindableBool(); + protected override Container Content { get; } protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480); @@ -40,6 +47,8 @@ namespace osu.Game.Storyboards.Drawables public override bool RemoveCompletedTransforms => false; + private double? lastEventEndTime; + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => @@ -74,6 +83,14 @@ namespace osu.Game.Storyboards.Drawables Add(layer.CreateDrawable()); } + + lastEventEndTime = Storyboard.LatestEventTime; + } + + protected override void Update() + { + base.Update(); + hasStoryboardEnded.Value = lastEventEndTime == null || Time.Current >= lastEventEndTime; } public DrawableStoryboardLayer OverlayLayer => Children.Single(layer => layer.Name == "Overlay"); @@ -83,25 +100,5 @@ namespace osu.Game.Storyboards.Drawables foreach (var layer in Children) layer.Enabled = passing ? layer.Layer.VisibleWhenPassing : layer.Layer.VisibleWhenFailing; } - - protected override void Update() - { - base.Update(); - updateHasStoryboardEnded(); - } - - /// - /// Whether the storyboard is considered finished. - /// - public IBindable HasStoryboardEnded => hasStoryboardEnded; - - private readonly BindableBool hasStoryboardEnded = new BindableBool(); - - private void updateHasStoryboardEnded() - { - hasStoryboardEnded.Value = - Storyboard.LatestEventTime == null || - Time.Current >= Storyboard.LatestEventTime; - } } } From acc9258eb217dfd04dfdc71f32498df3884caba6 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 4 May 2021 00:59:22 -0700 Subject: [PATCH 107/134] Implement notes for settings --- osu.Game/Overlays/Settings/SettingsItem.cs | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 0bd9750b0b..1d6535c289 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -19,6 +19,7 @@ using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Settings { @@ -36,6 +37,8 @@ namespace osu.Game.Overlays.Settings private SpriteText labelText; + private readonly OsuTextFlowContainer noteText; + public bool ShowsDefaultIndicator = true; public string TooltipText { get; set; } @@ -57,6 +60,19 @@ namespace osu.Game.Overlays.Settings } } + /// + /// Text to be displayed at the bottom of this . + /// Used for further explanation or indicating drawbacks of the current setting. + /// + public string NoteText + { + set + { + noteText.Alpha = 1; + noteText.Text = value; + } + } + public virtual Bindable Current { get => controlWithCurrent.Current; @@ -92,7 +108,16 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS }, - Child = Control = CreateControl() + Children = new[] + { + Control = CreateControl(), + noteText = new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = 0, + }, + }, }, }; @@ -108,6 +133,12 @@ namespace osu.Game.Overlays.Settings } } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + noteText.Colour = colours.Yellow; + } + private void updateDisabled() { if (labelText != null) From 796bd8e47eab8b8268bcbecae9349539b99d85a3 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 4 May 2021 00:59:48 -0700 Subject: [PATCH 108/134] Add existing setting notes from stable --- .../Settings/Sections/Graphics/LayoutSettings.cs | 9 ++++++++- .../Sections/Graphics/RendererSettings.cs | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 4d5c2e06eb..a24dd1f64b 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -141,7 +141,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingSettings.ForEach(s => bindPreviewEvent(s.Current)); - windowModeDropdown.Current.ValueChanged += _ => updateResolutionDropdown(); + windowModeDropdown.Current.BindValueChanged(mode => + { + updateResolutionDropdown(); + + const string not_fullscreen_note = "Running without fullscreen mode will increase your input latency!"; + + windowModeDropdown.NoteText = mode.NewValue != WindowMode.Fullscreen ? not_fullscreen_note : string.Empty; + }, true); windowModes.BindCollectionChanged((sender, args) => { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 8773e6763c..3ad201640d 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -13,6 +13,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override string Header => "Renderer"; + private SettingsEnumDropdown frameLimiterDropdown; + [BackgroundDependencyLoader] private void load(FrameworkConfigManager config, OsuConfigManager osuConfig) { @@ -20,7 +22,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Children = new Drawable[] { // TODO: this needs to be a custom dropdown at some point - new SettingsEnumDropdown + frameLimiterDropdown = new SettingsEnumDropdown { LabelText = "Frame limiter", Current = config.GetBindable(FrameworkSetting.FrameSync) @@ -37,5 +39,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + frameLimiterDropdown.Current.BindValueChanged(limit => + { + const string unlimited_frames_note = "Using unlimited frame limiter can lead to stutters. \"2x refresh rate\" is recommended."; + + frameLimiterDropdown.NoteText = limit.NewValue == FrameSync.Unlimited ? unlimited_frames_note : string.Empty; + }, true); + } } } From 0a649227385b82fb95787e2fd8989fae1fca258a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 4 May 2021 01:00:35 -0700 Subject: [PATCH 109/134] Add supporter note to background source setting --- .../UserInterface/MainMenuSettings.cs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index 95e2e9da30..707f8cd314 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -2,8 +2,11 @@ // 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.Game.Configuration; +using osu.Game.Online.API; +using osu.Game.Users; namespace osu.Game.Overlays.Settings.Sections.UserInterface { @@ -11,9 +14,15 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { protected override string Header => "Main Menu"; + private IBindable user; + + private SettingsEnumDropdown backgroundSourceDropdown; + [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load(OsuConfigManager config, IAPIProvider api) { + user = api.LocalUser.GetBoundCopy(); + Children = new Drawable[] { new SettingsCheckbox @@ -31,7 +40,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface LabelText = "Intro sequence", Current = config.GetBindable(OsuSetting.IntroSequence), }, - new SettingsEnumDropdown + backgroundSourceDropdown = new SettingsEnumDropdown { LabelText = "Background source", Current = config.GetBindable(OsuSetting.MenuBackgroundSource), @@ -43,5 +52,17 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface } }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + backgroundSourceDropdown.Current.BindValueChanged(source => + { + const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag."; + + backgroundSourceDropdown.NoteText = user.Value?.IsSupporter == false ? not_supporter_note : string.Empty; + }, true); + } } } From a5842130027d8e9560c9311e997c4916ebc35ba7 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 4 May 2021 09:11:33 -0700 Subject: [PATCH 110/134] Use vertical padding instead of relative height for default button --- osu.Game/Overlays/Settings/SettingsItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 1d6535c289..6405431f6b 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -18,7 +18,6 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osuTK; using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Settings @@ -172,6 +171,7 @@ namespace osu.Game.Overlays.Settings { RelativeSizeAxes = Axes.Y; Width = SettingsPanel.CONTENT_MARGINS; + Padding = new MarginPadding { Vertical = 1.5f }; Alpha = 0f; } @@ -194,7 +194,7 @@ namespace osu.Game.Overlays.Settings Type = EdgeEffectType.Glow, Radius = 2, }, - Size = new Vector2(0.33f, 0.8f), + Width = 0.33f, Child = new Box { RelativeSizeAxes = Axes.Both }, }; } From 4ceb9b1562e52475ba8da9652bd2d31501983ef3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 4 May 2021 23:36:14 +0300 Subject: [PATCH 111/134] Avoid randomizing and overestimating logic with simple hardcoding Not sure what was in my mind while I was pushing that.. --- .../NonVisual/FramedReplayInputHandlerTest.cs | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index 2062c4b820..fe1186bf95 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using osu.Framework.Utils; using osu.Game.Replays; using osu.Game.Rulesets.Replays; @@ -281,26 +280,39 @@ namespace osu.Game.Tests.NonVisual } [Test] - public void TestReplayFrameSortStability() + public void TestReplayFramesSortStability() { const double repeating_time = 5000; - int data = 0; - - // 1. add a range of frames in which some of them have the constant time 5000, all without any "data". - // 2. randomize the frames. - // 3. assign "data" to each frame in ascending order. - replay.Frames.AddRange(Enumerable.Range(1, 250).Select(i => + // add a range of frames randomized in time but have a "data" assigned to them in ascending order. + replay.Frames.AddRange(new[] { - if (RNG.NextBool()) - return new TestReplayFrame(repeating_time, true); - else - return new TestReplayFrame(i * 1000, true); - }).OrderBy(_ => RNG.Next()).Select(f => new TestReplayFrame(f.Time, true, ++data))); + new TestReplayFrame(repeating_time, true, 0), + new TestReplayFrame(0, true, 1), + new TestReplayFrame(3000, true, 2), + new TestReplayFrame(repeating_time, true, 3), + new TestReplayFrame(repeating_time, true, 4), + new TestReplayFrame(6000, true, 5), + new TestReplayFrame(9000, true, 6), + new TestReplayFrame(repeating_time, true, 7), + new TestReplayFrame(repeating_time, true, 8), + new TestReplayFrame(1000, true, 9), + new TestReplayFrame(11000, true, 10), + new TestReplayFrame(21000, true, 11), + new TestReplayFrame(4000, true, 12), + new TestReplayFrame(repeating_time, true, 13), + new TestReplayFrame(repeating_time, true, 14), + new TestReplayFrame(8000, true, 15), + new TestReplayFrame(2000, true, 16), + new TestReplayFrame(7000, true, 17), + new TestReplayFrame(repeating_time, true, 18), + new TestReplayFrame(repeating_time, true, 19), + new TestReplayFrame(10000, true, 20), + }); replay.HasReceivedAllFrames = true; - // create a new handler with the replay for the frames to be sorted. + // create a new handler with the replay for the sort to be performed. handler = new TestInputHandler(replay); // ensure sort stability by checking whether the "data" assigned to each time-repeated frame is in ascending order, as it was before sort. From 45c0b74151c7f547838a98786c5859194ad3f442 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 4 May 2021 23:41:46 +0300 Subject: [PATCH 112/134] Use LINQ select for data assigning for simplicity To avoid having to read through all of frames and ensure nothing is failing there --- .../NonVisual/FramedReplayInputHandlerTest.cs | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index fe1186bf95..a9f9dfdc83 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -284,31 +284,33 @@ namespace osu.Game.Tests.NonVisual { const double repeating_time = 5000; + int incrementingData = 0; + // add a range of frames randomized in time but have a "data" assigned to them in ascending order. replay.Frames.AddRange(new[] { - new TestReplayFrame(repeating_time, true, 0), - new TestReplayFrame(0, true, 1), - new TestReplayFrame(3000, true, 2), - new TestReplayFrame(repeating_time, true, 3), - new TestReplayFrame(repeating_time, true, 4), - new TestReplayFrame(6000, true, 5), - new TestReplayFrame(9000, true, 6), - new TestReplayFrame(repeating_time, true, 7), - new TestReplayFrame(repeating_time, true, 8), - new TestReplayFrame(1000, true, 9), - new TestReplayFrame(11000, true, 10), - new TestReplayFrame(21000, true, 11), - new TestReplayFrame(4000, true, 12), - new TestReplayFrame(repeating_time, true, 13), - new TestReplayFrame(repeating_time, true, 14), - new TestReplayFrame(8000, true, 15), - new TestReplayFrame(2000, true, 16), - new TestReplayFrame(7000, true, 17), - new TestReplayFrame(repeating_time, true, 18), - new TestReplayFrame(repeating_time, true, 19), - new TestReplayFrame(10000, true, 20), - }); + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(0, true), + new TestReplayFrame(3000, true), + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(6000, true), + new TestReplayFrame(9000, true), + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(1000, true), + new TestReplayFrame(11000, true), + new TestReplayFrame(21000, true), + new TestReplayFrame(4000, true), + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(8000, true), + new TestReplayFrame(2000, true), + new TestReplayFrame(7000, true), + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(repeating_time, true), + new TestReplayFrame(10000, true), + }.Select(f => new TestReplayFrame(f.Time, true, incrementingData++))); replay.HasReceivedAllFrames = true; From 973475823735a94dce077f2b5e9005df9e689a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 4 May 2021 22:48:57 +0200 Subject: [PATCH 113/134] Simplify test case further --- .../NonVisual/FramedReplayInputHandlerTest.cs | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index a9f9dfdc83..a4fe2172e1 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -284,33 +284,31 @@ namespace osu.Game.Tests.NonVisual { const double repeating_time = 5000; - int incrementingData = 0; - // add a range of frames randomized in time but have a "data" assigned to them in ascending order. replay.Frames.AddRange(new[] { - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(0, true), - new TestReplayFrame(3000, true), - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(6000, true), - new TestReplayFrame(9000, true), - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(1000, true), - new TestReplayFrame(11000, true), - new TestReplayFrame(21000, true), - new TestReplayFrame(4000, true), - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(8000, true), - new TestReplayFrame(2000, true), - new TestReplayFrame(7000, true), - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(repeating_time, true), - new TestReplayFrame(10000, true), - }.Select(f => new TestReplayFrame(f.Time, true, incrementingData++))); + repeating_time, + 0, + 3000, + repeating_time, + repeating_time, + 6000, + 9000, + repeating_time, + repeating_time, + 1000, + 11000, + 21000, + 4000, + repeating_time, + repeating_time, + 8000, + 2000, + 7000, + repeating_time, + repeating_time, + 10000 + }.Select((time, index) => new TestReplayFrame(time, true, index))); replay.HasReceivedAllFrames = true; @@ -321,7 +319,7 @@ namespace osu.Game.Tests.NonVisual var repeatingTimeFramesData = replay.Frames .Cast() .Where(f => f.Time == repeating_time) - .Select(f => f.Data); + .Select(f => f.FrameIndex); Assert.That(repeatingTimeFramesData, Is.Ordered.Ascending); } @@ -372,13 +370,13 @@ namespace osu.Game.Tests.NonVisual private class TestReplayFrame : ReplayFrame { public readonly bool IsImportant; - public readonly int Data; + public readonly int FrameIndex; - public TestReplayFrame(double time, bool isImportant = false, int data = 0) + public TestReplayFrame(double time, bool isImportant = false, int frameIndex = 0) : base(time) { IsImportant = isImportant; - Data = data; + FrameIndex = frameIndex; } } From f7d9fb094e8d764e01948a6a8104e6a5f8adc2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 4 May 2021 22:59:10 +0200 Subject: [PATCH 114/134] Reword & clarify comments --- osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index a4fe2172e1..407dec936b 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -284,7 +284,10 @@ namespace osu.Game.Tests.NonVisual { const double repeating_time = 5000; - // add a range of frames randomized in time but have a "data" assigned to them in ascending order. + // add a collection of frames in shuffled order time-wise; each frame also stores its original index to check stability later. + // data is hand-picked and breaks if the unstable List.Sort() is used. + // in theory this can still return a false-positive with another unstable algorithm if extremely unlucky, + // but there is no conceivable fool-proof way to prevent that anyways. replay.Frames.AddRange(new[] { repeating_time, @@ -315,7 +318,7 @@ namespace osu.Game.Tests.NonVisual // create a new handler with the replay for the sort to be performed. handler = new TestInputHandler(replay); - // ensure sort stability by checking whether the "data" assigned to each time-repeated frame is in ascending order, as it was before sort. + // ensure sort stability by checking that the frames with time == repeating_time are sorted in ascending frame index order themselves. var repeatingTimeFramesData = replay.Frames .Cast() .Where(f => f.Time == repeating_time) From 23b9d8c260058df9da31790b981ba50504b8aa5a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 4 May 2021 14:02:12 -0700 Subject: [PATCH 115/134] Fix alpha not being zero when string is set to empty and use inequality on supporter condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- .../Settings/Sections/UserInterface/MainMenuSettings.cs | 2 +- osu.Game/Overlays/Settings/SettingsItem.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index 707f8cd314..b5ab6d2f60 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -61,7 +61,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag."; - backgroundSourceDropdown.NoteText = user.Value?.IsSupporter == false ? not_supporter_note : string.Empty; + backgroundSourceDropdown.NoteText = user.Value?.IsSupporter != true ? not_supporter_note : string.Empty; }, true); } } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 6405431f6b..c6f17cfc23 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Settings { set { - noteText.Alpha = 1; + noteText.Alpha = string.IsNullOrWhiteSpace(value) ? 0 : 1; noteText.Text = value; } } From 1472960319ecdd6f4627bdfd7aff9896b6bdcfe1 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Tue, 4 May 2021 21:35:36 -0400 Subject: [PATCH 116/134] Hide and disable skip outro overlay on rewind --- osu.Game/Screens/Play/Player.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index cf26bc479a..88e617245b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -598,6 +598,7 @@ namespace osu.Game.Screens.Play completionProgressDelegate?.Cancel(); completionProgressDelegate = null; ValidForResume = true; + skipOutroOverlay.Hide(); return; } From 1d4a8bc0ae9df6ea3b796974953c6b903ddb1f5c Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Tue, 4 May 2021 22:23:36 -0400 Subject: [PATCH 117/134] Add visual test for rewinding --- .../Visual/Gameplay/TestSceneStoryboardWithOutro.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 8326063f81..3229716b7e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -116,6 +116,15 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for score shown", () => Player.IsScoreShown); } + [Test] + public void TestStoryboardRewind() + { + CreateTest(null); + AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + AddStep("rewind", () => Player.GameplayClockContainer.Seek(-1000)); + AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration); + } + protected override bool AllowFail => true; protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); From 6178f38c95277c91e2a07cb0766d9a33318d24aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 16:15:06 +0900 Subject: [PATCH 118/134] Reword unlimited frame rate warning a bit --- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 3ad201640d..c42db1706f 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics frameLimiterDropdown.Current.BindValueChanged(limit => { - const string unlimited_frames_note = "Using unlimited frame limiter can lead to stutters. \"2x refresh rate\" is recommended."; + const string unlimited_frames_note = "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. \"2x refresh rate\" is recommended."; frameLimiterDropdown.NoteText = limit.NewValue == FrameSync.Unlimited ? unlimited_frames_note : string.Empty; }, true); From 1288f69fada2d8457b2e21bd9341ff517ab72c58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 16:16:02 +0900 Subject: [PATCH 119/134] Rename to `WarningText` --- .../Settings/Sections/Graphics/LayoutSettings.cs | 2 +- .../Settings/Sections/Graphics/RendererSettings.cs | 2 +- .../Sections/UserInterface/MainMenuSettings.cs | 2 +- osu.Game/Overlays/Settings/SettingsItem.cs | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index a24dd1f64b..937bcc8abf 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics const string not_fullscreen_note = "Running without fullscreen mode will increase your input latency!"; - windowModeDropdown.NoteText = mode.NewValue != WindowMode.Fullscreen ? not_fullscreen_note : string.Empty; + windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? not_fullscreen_note : string.Empty; }, true); windowModes.BindCollectionChanged((sender, args) => diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index c42db1706f..70225ff6b8 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { const string unlimited_frames_note = "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. \"2x refresh rate\" is recommended."; - frameLimiterDropdown.NoteText = limit.NewValue == FrameSync.Unlimited ? unlimited_frames_note : string.Empty; + frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? unlimited_frames_note : string.Empty; }, true); } } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index b5ab6d2f60..7c4c88f344 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -61,7 +61,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag."; - backgroundSourceDropdown.NoteText = user.Value?.IsSupporter != true ? not_supporter_note : string.Empty; + backgroundSourceDropdown.WarningText = user.Value?.IsSupporter != true ? not_supporter_note : string.Empty; }, true); } } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index c6f17cfc23..f4d7c72b7f 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Settings private SpriteText labelText; - private readonly OsuTextFlowContainer noteText; + private readonly OsuTextFlowContainer warningText; public bool ShowsDefaultIndicator = true; @@ -61,14 +61,14 @@ namespace osu.Game.Overlays.Settings /// /// Text to be displayed at the bottom of this . - /// Used for further explanation or indicating drawbacks of the current setting. + /// Generally used to recommend the user change their setting as the current one is considered sub-optimal. /// - public string NoteText + public string WarningText { set { - noteText.Alpha = string.IsNullOrWhiteSpace(value) ? 0 : 1; - noteText.Text = value; + warningText.Alpha = string.IsNullOrWhiteSpace(value) ? 0 : 1; + warningText.Text = value; } } @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Settings Children = new[] { Control = CreateControl(), - noteText = new OsuTextFlowContainer + warningText = new OsuTextFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.Settings [BackgroundDependencyLoader] private void load(OsuColour colours) { - noteText.Colour = colours.Yellow; + warningText.Colour = colours.Yellow; } private void updateDisabled() From 19ffcd00c27d04ce184f16cd55f141c803dfd011 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 16:19:06 +0900 Subject: [PATCH 120/134] Initialise warning text flow lazily as most items will not use it --- osu.Game/Overlays/Settings/SettingsItem.cs | 29 ++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index f4d7c72b7f..09e458ad7e 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -36,12 +36,15 @@ namespace osu.Game.Overlays.Settings private SpriteText labelText; - private readonly OsuTextFlowContainer warningText; + private OsuTextFlowContainer warningText; public bool ShowsDefaultIndicator = true; public string TooltipText { get; set; } + [Resolved] + private OsuColour colours { get; set; } + public virtual LocalisableString LabelText { get => labelText?.Text ?? string.Empty; @@ -67,6 +70,18 @@ namespace osu.Game.Overlays.Settings { set { + if (warningText == null) + { + // construct lazily for cases where the label is not needed (may be provided by the Control). + FlowContent.Add(warningText = new OsuTextFlowContainer + { + Colour = colours.Yellow, + Margin = new MarginPadding { Bottom = 5 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }); + } + warningText.Alpha = string.IsNullOrWhiteSpace(value) ? 0 : 1; warningText.Text = value; } @@ -110,12 +125,6 @@ namespace osu.Game.Overlays.Settings Children = new[] { Control = CreateControl(), - warningText = new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Alpha = 0, - }, }, }, }; @@ -132,12 +141,6 @@ namespace osu.Game.Overlays.Settings } } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - warningText.Colour = colours.Yellow; - } - private void updateDisabled() { if (labelText != null) From 08a45e9fc29d37b686a8430db7c37aab39894c00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 16:26:34 +0900 Subject: [PATCH 121/134] Remove dead code --- osu.Game/Overlays/Settings/SettingsItem.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 09e458ad7e..86a836d29b 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -230,12 +230,6 @@ namespace osu.Game.Overlays.Settings UpdateState(); } - public void SetButtonColour(Color4 buttonColour) - { - this.buttonColour = buttonColour; - UpdateState(); - } - public void UpdateState() => Scheduler.AddOnce(updateState); private void updateState() From 3cc9bad97968f220fc475f657f0189eb524b3f8a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 17:49:33 +0900 Subject: [PATCH 122/134] Actually check for correct state of fade content in rewind test --- .../Visual/Gameplay/TestSceneStoryboardWithOutro.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 3229716b7e..4138a81ebd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Graphics; @@ -119,9 +120,16 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestStoryboardRewind() { + SkipOverlay.FadeContainer fadeContainer() => Player.ChildrenOfType().First(); + CreateTest(null); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + AddUntilStep("skip overlay content becomes visible", () => fadeContainer().State == Visibility.Visible); + AddStep("rewind", () => Player.GameplayClockContainer.Seek(-1000)); + AddUntilStep("skip overlay content not visible", () => fadeContainer().State == Visibility.Hidden); + + AddUntilStep("skip overlay content becomes visible", () => fadeContainer().State == Visibility.Visible); AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration); } From 9ec3255c505e99a826b3eba40f86f80829502562 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 17:50:25 +0900 Subject: [PATCH 123/134] Fix `SkipOverlay`'s `FadeContent` not getting correct state from parent --- osu.Game/Screens/Play/SkipOverlay.cs | 30 +++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index ddb78dfb67..ed49fc40b2 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -8,19 +8,19 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Threading; +using osu.Framework.Utils; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Input.Bindings; using osu.Game.Screens.Ranking; using osuTK; using osuTK.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics.Containers; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; -using osu.Framework.Utils; -using osu.Game.Input.Bindings; namespace osu.Game.Screens.Play { @@ -92,6 +92,18 @@ namespace osu.Game.Screens.Play private double fadeOutBeginTime => startTime - MasterGameplayClockContainer.MINIMUM_SKIP_TIME; + public override void Hide() + { + base.Hide(); + fadeContainer.Hide(); + } + + public override void Show() + { + base.Show(); + fadeContainer.Show(); + } + protected override void LoadComplete() { base.LoadComplete(); @@ -147,7 +159,7 @@ namespace osu.Game.Screens.Play { } - private class FadeContainer : Container, IStateful + public class FadeContainer : Container, IStateful { public event Action StateChanged; @@ -170,7 +182,7 @@ namespace osu.Game.Screens.Play switch (state) { case Visibility.Visible: - // we may be triggered to become visible mnultiple times but we only want to transform once. + // we may be triggered to become visible multiple times but we only want to transform once. if (stateChanged) this.FadeIn(500, Easing.OutExpo); From 377af38d94541c48cab0d7083cae089b28916f20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 17:59:49 +0900 Subject: [PATCH 124/134] Remove unnecessary pixelSnapping parameter This was only required because there was text being rendered to the `BufferedContainer` content until now. Removing this should allow for better resolution in the background display (due to using a better minify scale mode). --- osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs index 566f49a799..0233112c69 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.Both; - InternalChild = new BufferedContainer(pixelSnapping: true) + InternalChild = new BufferedContainer() { CacheDrawnFrameBuffer = true, RelativeSizeAxes = Axes.Both, From 1410b8f36dce587d91b030bfe5b4736828bb074b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 18:30:57 +0900 Subject: [PATCH 125/134] Fix follow points displaying at incorrect locations when dragging a slider out-of-bounds --- .../Objects/Drawables/Connections/FollowPointConnection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 5541d0e790..cda4715280 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections Entry = null; } - private void onEntryInvalidated() => refreshPoints(); + private void onEntryInvalidated() => Scheduler.AddOnce(refreshPoints); private void refreshPoints() { From cf6ed7a7cf5bac2d8d8d463a1672b7318bd0b3d1 Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 5 May 2021 13:13:37 +0200 Subject: [PATCH 126/134] Refactored out changes in StarRatingDisplay --- .../Ranking/Expanded/StarRatingDisplay.cs | 145 +++++++----------- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 68 ++++---- .../Select/BeatmapInfoWedgeBackground.cs | 2 +- 3 files changed, 97 insertions(+), 118 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 748f58e430..f7e50fdc8a 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -22,22 +22,7 @@ namespace osu.Game.Screens.Ranking.Expanded /// public class StarRatingDisplay : CompositeDrawable { - [Resolved] - private OsuColour colours { get; set; } - - private CircularContainer colorContainer; - private StarDifficulty starDifficulty; - private FillFlowContainer foregroundContainer; - - public StarDifficulty StarDifficulty - { - get => starDifficulty; - set - { - starDifficulty = value; - setDifficulty(starDifficulty); - } - } + private readonly StarDifficulty difficulty; /// /// Creates a new using an already computed . @@ -45,94 +30,78 @@ namespace osu.Game.Screens.Ranking.Expanded /// The already computed to display the star difficulty of. public StarRatingDisplay(StarDifficulty starDifficulty) { - this.starDifficulty = starDifficulty; - } - - private void setDifficulty(StarDifficulty difficulty) - { - colorContainer.FadeColour(getDifficultyColour(difficulty), 250); - - foregroundContainer.Expire(); - foregroundContainer = null; - AddInternal(foregroundContainer = createForegroundContainer(difficulty)); + difficulty = starDifficulty; } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) { AutoSizeAxes = Axes.Both; - InternalChildren = new Drawable[] - { - colorContainer = new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Colour = getDifficultyColour(starDifficulty), - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - }, - } - }, - foregroundContainer = createForegroundContainer(starDifficulty), - }; - } - - private ColourInfo getDifficultyColour(StarDifficulty difficulty) - { - return difficulty.DifficultyRating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); - } - - private FillFlowContainer createForegroundContainer(StarDifficulty difficulty) - { var starRatingParts = difficulty.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); string wholePart = starRatingParts[0]; string fractionPart = starRatingParts[1]; string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; - return new FillFlowContainer + ColourInfo backgroundColour = difficulty.DifficultyRating == DifficultyRating.ExpertPlus + ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) + : (ColourInfo)colours.ForDifficultyRating(difficulty.DifficultyRating); + + InternalChildren = new Drawable[] { - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 8, Vertical = 4 }, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(2, 0), - Children = new Drawable[] + new CircularContainer { - new SpriteIcon + RelativeSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(7), - Icon = FontAwesome.Solid.Star, - Colour = Color4.Black - }, - new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - TextAnchor = Anchor.BottomLeft, - }.With(t => - { - t.AddText($"{wholePart}", s => + new Box { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); - t.AddText($"{separator}{fractionPart}", s => + RelativeSizeAxes = Axes.Both, + Colour = backgroundColour + }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 8, Vertical = 4 }, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(2, 0), + Children = new Drawable[] + { + new SpriteIcon { - s.Colour = Color4.Black; - s.Font = s.Font.With(size: 7); - s.UseFullGlyphHeight = false; - }); - }), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(7), + Icon = FontAwesome.Solid.Star, + Colour = Color4.Black + }, + new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + TextAnchor = Anchor.BottomLeft, + }.With(t => + { + t.AddText($"{wholePart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 14); + s.UseFullGlyphHeight = false; + }); + + t.AddText($"{separator}{fractionPart}", s => + { + s.Colour = Color4.Black; + s.Font = s.Font.With(size: 7); + s.UseFullGlyphHeight = false; + }); + }) + } } }; } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index cb5a276a5d..04063d5819 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -173,7 +173,7 @@ namespace osu.Game.Screens.Select private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; private FillFlowContainer infoLabelContainer; - private StarRatingDisplay starRatingDisplay; + private Container topRightMetadataContainer; private Container bpmLabelContainer; private ModSettingChangeTracker settingChangeTracker; private CancellationTokenSource cancellationTokenSource; @@ -232,34 +232,15 @@ namespace osu.Game.Screens.Select }, } }, - new FillFlowContainer + topRightMetadataContainer = new Container { Name = "Topright-aligned metadata", Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Direction = FillDirection.Vertical, Padding = new MarginPadding { Top = 14, Right = shear_width / 2 }, AutoSizeAxes = Axes.Both, Shear = wedged_container_shear, - Children = new Drawable[] - { - starRatingDisplay = new StarRatingDisplay(starDifficulty.Value ?? new StarDifficulty()) - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -wedged_container_shear, - Margin = new MarginPadding { Bottom = 5 } - }, - StatusPill = new BeatmapSetOnlineStatusPill - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -wedged_container_shear, - TextSize = 11, - TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, - Status = beatmapInfo.Status, - } - } + Child = createTopRightMetadataContainer(beatmapInfo, starDifficulty.Value ?? new StarDifficulty()) }, new FillFlowContainer { @@ -306,21 +287,50 @@ namespace osu.Game.Screens.Select titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); - starDifficulty.BindValueChanged(updateStarRatingDisplay, true); + starDifficulty.BindValueChanged(updateTopRightMetadata, true); // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) StatusPill.Hide(); } - private void updateStarRatingDisplay(ValueChangedEvent valueChanged) + private void updateTopRightMetadata(ValueChangedEvent valueChanged) { - if (valueChanged.NewValue.HasValue && valueChanged.NewValue.Value.Stars > 0) - starRatingDisplay.Show(); - else - starRatingDisplay.Hide(); + topRightMetadataContainer.Child.FadeOut(250); + topRightMetadataContainer.Child.Expire(); + topRightMetadataContainer.Child = createTopRightMetadataContainer(beatmap.BeatmapInfo, valueChanged.NewValue ?? new StarDifficulty()); + } - starRatingDisplay.StarDifficulty = valueChanged.NewValue ?? new StarDifficulty(); + private FillFlowContainer createTopRightMetadataContainer(BeatmapInfo beatmapInfo, StarDifficulty difficulty) + { + var container = new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + }; + + if (difficulty.Stars > 0) + { + container.Add(new StarRatingDisplay(difficulty) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -wedged_container_shear, + Margin = new MarginPadding { Bottom = 5 } + }); + } + + container.Add(StatusPill = new BeatmapSetOnlineStatusPill + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -wedged_container_shear, + TextSize = 11, + TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, + Status = beatmapInfo.Status, + }); + + return container; } private void refreshModInformation(ValueChangedEvent> modsChangedEvent) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs index 0233112c69..f50fb4dc8a 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.Both; - InternalChild = new BufferedContainer() + InternalChild = new BufferedContainer { CacheDrawnFrameBuffer = true, RelativeSizeAxes = Axes.Both, From 4ef901d08d51e586e447f831821463150d14229c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 May 2021 21:07:49 +0900 Subject: [PATCH 127/134] Remove unnecessary redirection property to `Container.Info` --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs | 4 ++-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 688cc9a035..ec19f00087 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -193,9 +193,9 @@ namespace osu.Game.Tests.Visual.SongSelect private class TestBeatmapInfoWedge : BeatmapInfoWedge { - public new WedgeInfoText Info => base.Info; - public new BeatmapInfoWedgeContainer Container => base.Container; + + public WedgeInfoText Info => base.Container.Info; } private class TestHitObject : ConvertHitObject, IHasPosition diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 04063d5819..c86bdc99ff 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -41,7 +41,6 @@ namespace osu.Game.Screens.Select private IBindable ruleset { get; set; } protected BeatmapInfoWedgeContainer Container; - protected WedgeInfoText Info => Container.Info; public BeatmapInfoWedge() { From 5049e2fbf9bf709df1f4b2614ef80c11e8f5d31e Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 5 May 2021 15:11:38 +0200 Subject: [PATCH 128/134] Refactored out changes in DifficultyColourBar --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 66 +++++++++------------ 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index c86bdc99ff..448bf088dc 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -174,6 +174,7 @@ namespace osu.Game.Screens.Select private FillFlowContainer infoLabelContainer; private Container topRightMetadataContainer; private Container bpmLabelContainer; + private Container difficultyColourBarContainer; private ModSettingChangeTracker settingChangeTracker; private CancellationTokenSource cancellationTokenSource; private IBindable starDifficulty; @@ -206,10 +207,11 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { - new DifficultyColourBar(beatmapInfo) + difficultyColourBarContainer = new Container { RelativeSizeAxes = Axes.Y, Width = 20, + Child = createDifficultyColourBar(starDifficulty.Value ?? new StarDifficulty()), }, new FillFlowContainer { @@ -286,20 +288,32 @@ namespace osu.Game.Screens.Select titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); - starDifficulty.BindValueChanged(updateTopRightMetadata, true); + starDifficulty.BindValueChanged(updateDifficulty, true); // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) StatusPill.Hide(); } - private void updateTopRightMetadata(ValueChangedEvent valueChanged) + private void updateDifficulty(ValueChangedEvent valueChanged) { + var difficulty = valueChanged.NewValue ?? new StarDifficulty(); + topRightMetadataContainer.Child.FadeOut(250); topRightMetadataContainer.Child.Expire(); - topRightMetadataContainer.Child = createTopRightMetadataContainer(beatmap.BeatmapInfo, valueChanged.NewValue ?? new StarDifficulty()); + topRightMetadataContainer.Child = createTopRightMetadataContainer(beatmap.BeatmapInfo, difficulty); + + difficultyColourBarContainer.Child.Expire(); + difficultyColourBarContainer.Child = createDifficultyColourBar(difficulty); } + private DifficultyColourBar createDifficultyColourBar(StarDifficulty difficulty) + => new DifficultyColourBar(difficulty) + { + RelativeSizeAxes = Axes.Y, + Width = 20, + }; + private FillFlowContainer createTopRightMetadataContainer(BeatmapInfo beatmapInfo, StarDifficulty difficulty) { var container = new FillFlowContainer @@ -515,64 +529,38 @@ namespace osu.Game.Screens.Select private class DifficultyColourBar : Container { - [Resolved] - private OsuColour colours { get; set; } + private readonly StarDifficulty difficulty; - private Box solidDifficultyBox; - private Box transparentDifficultyBox; - private CancellationTokenSource cancellationTokenSource; - private IBindable starDifficulty; - - private readonly BeatmapInfo beatmapInfo; - - public DifficultyColourBar(BeatmapInfo beatmapInfo) + public DifficultyColourBar(StarDifficulty difficulty) { - this.beatmapInfo = beatmapInfo; + this.difficulty = difficulty; } [BackgroundDependencyLoader] - private void load(BeatmapDifficultyCache difficultyCache) + private void load(OsuColour colours) { const float full_opacity_ratio = 0.7f; - cancellationTokenSource?.Cancel(); - cancellationTokenSource = new CancellationTokenSource(); - - starDifficulty?.UnbindAll(); - starDifficulty = difficultyCache.GetBindableDifficulty(beatmapInfo, cancellationTokenSource.Token); + var difficultyColour = colours.ForDifficultyRating(difficulty.DifficultyRating); Children = new Drawable[] { - solidDifficultyBox = new Box + new Box { RelativeSizeAxes = Axes.Both, + Colour = difficultyColour, Width = full_opacity_ratio, }, - transparentDifficultyBox = new Box + new Box { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, + Colour = difficultyColour, Alpha = 0.5f, X = full_opacity_ratio, Width = 1 - full_opacity_ratio, } }; - - starDifficulty.BindValueChanged(setColour, true); - } - - private void setColour(ValueChangedEvent valueChanged) - { - var difficultyColour = colours.ForDifficultyRating(valueChanged.NewValue?.DifficultyRating ?? (new StarDifficulty()).DifficultyRating); - - solidDifficultyBox.Colour = difficultyColour; - transparentDifficultyBox.Colour = difficultyColour; - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - cancellationTokenSource?.Cancel(); } } } From 88506a51dd95ec070457889ad6c89b96ca777720 Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 5 May 2021 17:51:29 +0200 Subject: [PATCH 129/134] reduced complexity --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 75 ++++++++++----------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 448bf088dc..475a547c27 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -233,15 +233,35 @@ namespace osu.Game.Screens.Select }, } }, - topRightMetadataContainer = new Container + new FillFlowContainer { Name = "Topright-aligned metadata", Anchor = Anchor.TopRight, Origin = Anchor.TopRight, + Direction = FillDirection.Vertical, Padding = new MarginPadding { Top = 14, Right = shear_width / 2 }, AutoSizeAxes = Axes.Both, Shear = wedged_container_shear, - Child = createTopRightMetadataContainer(beatmapInfo, starDifficulty.Value ?? new StarDifficulty()) + Children = new Drawable[] + { + starRatingContainer = new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -wedged_container_shear, + Margin = new MarginPadding { Bottom = 5 } + }, + StatusPill = new BeatmapSetOnlineStatusPill + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -wedged_container_shear, + TextSize = 11, + TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, + Status = beatmapInfo.Status, + } + } }, new FillFlowContainer { @@ -299,51 +319,24 @@ namespace osu.Game.Screens.Select { var difficulty = valueChanged.NewValue ?? new StarDifficulty(); - topRightMetadataContainer.Child.FadeOut(250); - topRightMetadataContainer.Child.Expire(); - topRightMetadataContainer.Child = createTopRightMetadataContainer(beatmap.BeatmapInfo, difficulty); + if (starRatingContainer.Children.Count > 0) + { + starRatingContainer.Child.FadeOut(250); + starRatingContainer.Child.Expire(); + } - difficultyColourBarContainer.Child.Expire(); - difficultyColourBarContainer.Child = createDifficultyColourBar(difficulty); - } + starRatingContainer.Child = difficulty.Stars > 0 ? new StarRatingDisplay(difficulty) : Empty(); - private DifficultyColourBar createDifficultyColourBar(StarDifficulty difficulty) - => new DifficultyColourBar(difficulty) + if (difficultyColourBarContainer.Children.Count > 0) + { + difficultyColourBarContainer.Child.Expire(); + } + + difficultyColourBarContainer.Child = new DifficultyColourBar(difficulty) { RelativeSizeAxes = Axes.Y, Width = 20, }; - - private FillFlowContainer createTopRightMetadataContainer(BeatmapInfo beatmapInfo, StarDifficulty difficulty) - { - var container = new FillFlowContainer - { - Direction = FillDirection.Vertical, - AutoSizeAxes = Axes.Both, - }; - - if (difficulty.Stars > 0) - { - container.Add(new StarRatingDisplay(difficulty) - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -wedged_container_shear, - Margin = new MarginPadding { Bottom = 5 } - }); - } - - container.Add(StatusPill = new BeatmapSetOnlineStatusPill - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -wedged_container_shear, - TextSize = 11, - TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, - Status = beatmapInfo.Status, - }); - - return container; } private void refreshModInformation(ValueChangedEvent> modsChangedEvent) From 279750775848a7f6536ecbff54e69773d01c2464 Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 5 May 2021 17:56:07 +0200 Subject: [PATCH 130/134] Reorganized elements for readability --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 128 ++++++++++---------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 475a547c27..15e484e24c 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -132,39 +132,13 @@ namespace osu.Game.Screens.Select } } - public class BeatmapInfoWedgeContainer : Container - { - private readonly WorkingBeatmap beatmap; - private readonly RulesetInfo ruleset; - - internal WedgeInfoText Info; - - public BeatmapInfoWedgeContainer(WorkingBeatmap beatmap, RulesetInfo ruleset) - { - this.beatmap = beatmap; - this.ruleset = ruleset; - } - - [BackgroundDependencyLoader] - private void load() - { - RelativeSizeAxes = Axes.Both; - - Children = new Drawable[] - { - new BeatmapInfoWedgeBackground(beatmap), - Info = new WedgeInfoText(beatmap, ruleset), - }; - } - } - public class WedgeInfoText : Container { - public FillFlowContainer MapperContainer { get; private set; } + public OsuSpriteText VersionLabel { get; private set; } public OsuSpriteText TitleLabel { get; private set; } public OsuSpriteText ArtistLabel { get; private set; } - public OsuSpriteText VersionLabel { get; private set; } public BeatmapSetOnlineStatusPill StatusPill { get; private set; } + public FillFlowContainer MapperContainer { get; private set; } [Resolved] private IBindable> mods { get; set; } @@ -172,16 +146,17 @@ namespace osu.Game.Screens.Select private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; private FillFlowContainer infoLabelContainer; - private Container topRightMetadataContainer; + private Container starRatingContainer; private Container bpmLabelContainer; private Container difficultyColourBarContainer; - private ModSettingChangeTracker settingChangeTracker; private CancellationTokenSource cancellationTokenSource; private IBindable starDifficulty; private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; + private ModSettingChangeTracker settingChangeTracker; + public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset) { this.beatmap = beatmap; @@ -211,7 +186,6 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.Y, Width = 20, - Child = createDifficultyColourBar(starDifficulty.Value ?? new StarDifficulty()), }, new FillFlowContainer { @@ -304,8 +278,6 @@ namespace osu.Game.Screens.Select } }; - addInfoLabels(); - titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); starDifficulty.BindValueChanged(updateDifficulty, true); @@ -313,38 +285,8 @@ namespace osu.Game.Screens.Select // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) StatusPill.Hide(); - } - private void updateDifficulty(ValueChangedEvent valueChanged) - { - var difficulty = valueChanged.NewValue ?? new StarDifficulty(); - - if (starRatingContainer.Children.Count > 0) - { - starRatingContainer.Child.FadeOut(250); - starRatingContainer.Child.Expire(); - } - - starRatingContainer.Child = difficulty.Stars > 0 ? new StarRatingDisplay(difficulty) : Empty(); - - if (difficultyColourBarContainer.Children.Count > 0) - { - difficultyColourBarContainer.Child.Expire(); - } - - difficultyColourBarContainer.Child = new DifficultyColourBar(difficulty) - { - RelativeSizeAxes = Axes.Y, - Width = 20, - }; - } - - private void refreshModInformation(ValueChangedEvent> modsChangedEvent) - { - settingChangeTracker?.Dispose(); - settingChangeTracker = new ModSettingChangeTracker(modsChangedEvent.NewValue); - settingChangeTracker.SettingChanged += _ => refreshBPMLabel(modsChangedEvent.NewValue); - refreshBPMLabel(modsChangedEvent.NewValue); + addInfoLabels(); } private void setMetadata(string source) @@ -455,6 +397,38 @@ namespace osu.Game.Screens.Select }; } + private void updateDifficulty(ValueChangedEvent valueChanged) + { + var difficulty = valueChanged.NewValue ?? new StarDifficulty(); + + if (starRatingContainer.Children.Count > 0) + { + starRatingContainer.Child.FadeOut(250); + starRatingContainer.Child.Expire(); + } + + starRatingContainer.Child = difficulty.Stars > 0 ? new StarRatingDisplay(difficulty) : Empty(); + + if (difficultyColourBarContainer.Children.Count > 0) + { + difficultyColourBarContainer.Child.Expire(); + } + + difficultyColourBarContainer.Child = new DifficultyColourBar(difficulty) + { + RelativeSizeAxes = Axes.Y, + Width = 20, + }; + } + + private void refreshModInformation(ValueChangedEvent> modsChangedEvent) + { + settingChangeTracker?.Dispose(); + settingChangeTracker = new ModSettingChangeTracker(modsChangedEvent.NewValue); + settingChangeTracker.SettingChanged += _ => refreshBPMLabel(modsChangedEvent.NewValue); + refreshBPMLabel(modsChangedEvent.NewValue); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -557,5 +531,31 @@ namespace osu.Game.Screens.Select } } } + + public class BeatmapInfoWedgeContainer : Container + { + private readonly WorkingBeatmap beatmap; + private readonly RulesetInfo ruleset; + + internal WedgeInfoText Info; + + public BeatmapInfoWedgeContainer(WorkingBeatmap beatmap, RulesetInfo ruleset) + { + this.beatmap = beatmap; + this.ruleset = ruleset; + } + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new BeatmapInfoWedgeBackground(beatmap), + Info = new WedgeInfoText(beatmap, ruleset), + }; + } + } } } From bb385f425531c1efdf37fd258df9057edaf10fc9 Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 5 May 2021 18:15:59 +0200 Subject: [PATCH 131/134] Reverted difficulty and mod updates --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 117 +++++++++----------- 1 file changed, 55 insertions(+), 62 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 15e484e24c..4be7d3b0f4 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -40,6 +40,14 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable ruleset { get; set; } + [Resolved] + private IBindable> mods { get; set; } + + [Resolved] + private BeatmapDifficultyCache difficultyCache { get; set; } + + private IBindable beatmapDifficulty; + protected BeatmapInfoWedgeContainer Container; public BeatmapInfoWedge() @@ -80,6 +88,8 @@ namespace osu.Game.Screens.Select private WorkingBeatmap beatmap; + private CancellationTokenSource cancellationSource; + public WorkingBeatmap Beatmap { get => beatmap; @@ -88,6 +98,13 @@ namespace osu.Game.Screens.Select if (beatmap == value) return; beatmap = value; + cancellationSource?.Cancel(); + cancellationSource = new CancellationTokenSource(); + + beatmapDifficulty?.UnbindAll(); + beatmapDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo, cancellationSource.Token); + beatmapDifficulty.BindValueChanged(_ => updateDisplay()); + updateDisplay(); } } @@ -117,7 +134,7 @@ namespace osu.Game.Screens.Select return; } - LoadComponentAsync(loadingInfo = new BeatmapInfoWedgeContainer(beatmap, ruleset.Value) + LoadComponentAsync(loadingInfo = new BeatmapInfoWedgeContainer(beatmap, ruleset.Value, mods.Value, beatmapDifficulty.Value ?? new StarDifficulty()) { Shear = -Shear, Depth = Container?.Depth + 1 ?? 0, @@ -132,6 +149,12 @@ namespace osu.Game.Screens.Select } } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + cancellationSource?.Cancel(); + } + public class WedgeInfoText : Container { public OsuSpriteText VersionLabel { get; private set; } @@ -140,41 +163,32 @@ namespace osu.Game.Screens.Select public BeatmapSetOnlineStatusPill StatusPill { get; private set; } public FillFlowContainer MapperContainer { get; private set; } - [Resolved] - private IBindable> mods { get; set; } - private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; private FillFlowContainer infoLabelContainer; - private Container starRatingContainer; private Container bpmLabelContainer; - private Container difficultyColourBarContainer; - private CancellationTokenSource cancellationTokenSource; - private IBindable starDifficulty; private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; + private readonly IReadOnlyList mods; + private readonly StarDifficulty starDifficulty; private ModSettingChangeTracker settingChangeTracker; - public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset) + public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IReadOnlyList mods, StarDifficulty difficulty) { this.beatmap = beatmap; ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset; + this.mods = mods; + starDifficulty = difficulty; } [BackgroundDependencyLoader] - private void load(LocalisationManager localisation, BeatmapDifficultyCache difficultyCache) + private void load(LocalisationManager localisation) { var beatmapInfo = beatmap.BeatmapInfo; var metadata = beatmapInfo.Metadata ?? beatmap.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); - cancellationTokenSource?.Cancel(); - cancellationTokenSource = new CancellationTokenSource(); - - starDifficulty?.UnbindAll(); - starDifficulty = difficultyCache.GetBindableDifficulty(beatmapInfo, cancellationTokenSource.Token); - RelativeSizeAxes = Axes.Both; titleBinding = localisation.GetLocalisedString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); @@ -182,7 +196,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { - difficultyColourBarContainer = new Container + new DifficultyColourBar(starDifficulty) { RelativeSizeAxes = Axes.Y, Width = 20, @@ -216,16 +230,14 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Top = 14, Right = shear_width / 2 }, AutoSizeAxes = Axes.Both, Shear = wedged_container_shear, - Children = new Drawable[] + Children = new[] { - starRatingContainer = new Container + createStarRatingDisplay(starDifficulty).With(display => { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -wedged_container_shear, - Margin = new MarginPadding { Bottom = 5 } - }, + display.Anchor = Anchor.TopRight; + display.Origin = Anchor.TopRight; + display.Shear = -wedged_container_shear; + }), StatusPill = new BeatmapSetOnlineStatusPill { Anchor = Anchor.TopRight, @@ -280,7 +292,6 @@ namespace osu.Game.Screens.Select titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); - starDifficulty.BindValueChanged(updateDifficulty, true); // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) @@ -289,6 +300,13 @@ namespace osu.Game.Screens.Select addInfoLabels(); } + private static Drawable createStarRatingDisplay(StarDifficulty difficulty) => difficulty.Stars > 0 + ? new StarRatingDisplay(difficulty) + { + Margin = new MarginPadding { Bottom = 5 } + } + : Empty(); + private void setMetadata(string source) { ArtistLabel.Text = artistBinding.Value; @@ -320,7 +338,10 @@ namespace osu.Game.Screens.Select } }; - mods.BindValueChanged(refreshModInformation, true); + settingChangeTracker = new ModSettingChangeTracker(mods); + settingChangeTracker.SettingChanged += _ => refreshBPMLabel(); + + refreshBPMLabel(); } private InfoLabel[] getRulesetInfoLabels() @@ -350,7 +371,7 @@ namespace osu.Game.Screens.Select return Array.Empty(); } - private void refreshBPMLabel(IReadOnlyList mods) + private void refreshBPMLabel() { var b = beatmap.Beatmap; if (b == null) @@ -397,38 +418,6 @@ namespace osu.Game.Screens.Select }; } - private void updateDifficulty(ValueChangedEvent valueChanged) - { - var difficulty = valueChanged.NewValue ?? new StarDifficulty(); - - if (starRatingContainer.Children.Count > 0) - { - starRatingContainer.Child.FadeOut(250); - starRatingContainer.Child.Expire(); - } - - starRatingContainer.Child = difficulty.Stars > 0 ? new StarRatingDisplay(difficulty) : Empty(); - - if (difficultyColourBarContainer.Children.Count > 0) - { - difficultyColourBarContainer.Child.Expire(); - } - - difficultyColourBarContainer.Child = new DifficultyColourBar(difficulty) - { - RelativeSizeAxes = Axes.Y, - Width = 20, - }; - } - - private void refreshModInformation(ValueChangedEvent> modsChangedEvent) - { - settingChangeTracker?.Dispose(); - settingChangeTracker = new ModSettingChangeTracker(modsChangedEvent.NewValue); - settingChangeTracker.SettingChanged += _ => refreshBPMLabel(modsChangedEvent.NewValue); - refreshBPMLabel(modsChangedEvent.NewValue); - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -536,13 +525,17 @@ namespace osu.Game.Screens.Select { private readonly WorkingBeatmap beatmap; private readonly RulesetInfo ruleset; + private readonly StarDifficulty starDifficulty; + private readonly IReadOnlyList mods; internal WedgeInfoText Info; - public BeatmapInfoWedgeContainer(WorkingBeatmap beatmap, RulesetInfo ruleset) + public BeatmapInfoWedgeContainer(WorkingBeatmap beatmap, RulesetInfo ruleset, IReadOnlyList mods, StarDifficulty difficulty) { this.beatmap = beatmap; this.ruleset = ruleset; + this.mods = mods; + starDifficulty = difficulty; } [BackgroundDependencyLoader] @@ -553,7 +546,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { new BeatmapInfoWedgeBackground(beatmap), - Info = new WedgeInfoText(beatmap, ruleset), + Info = new WedgeInfoText(beatmap, ruleset, mods, starDifficulty), }; } } From b6b9a696017ca41dd9befb1ca5b63c2fa129f008 Mon Sep 17 00:00:00 2001 From: Denrage Date: Wed, 5 May 2021 18:50:49 +0200 Subject: [PATCH 132/134] Removed unnecessary class for wrapping --- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 7 +-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 43 +++++-------------- 2 files changed, 14 insertions(+), 36 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index ec19f00087..b9e92cba62 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -7,6 +7,7 @@ using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; @@ -135,7 +136,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void selectBeatmap([CanBeNull] IBeatmap b) { - BeatmapInfoWedge.BeatmapInfoWedgeContainer containerBefore = null; + Container containerBefore = null; AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () => { @@ -193,9 +194,9 @@ namespace osu.Game.Tests.Visual.SongSelect private class TestBeatmapInfoWedge : BeatmapInfoWedge { - public new BeatmapInfoWedgeContainer Container => base.Container; + public new Container Container => base.Container; - public WedgeInfoText Info => base.Container.Info; + public new WedgeInfoText Info => base.Info; } private class TestHitObject : ConvertHitObject, IHasPosition diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 4be7d3b0f4..53ac97cc7d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -48,7 +48,8 @@ namespace osu.Game.Screens.Select private IBindable beatmapDifficulty; - protected BeatmapInfoWedgeContainer Container; + protected Container Container; + protected WedgeInfoText Info; public BeatmapInfoWedge() { @@ -111,7 +112,7 @@ namespace osu.Game.Screens.Select public override bool IsPresent => base.IsPresent || Container == null; // Visibility is updated in the LoadComponentAsync callback - private BeatmapInfoWedgeContainer loadingInfo; + private Container loadingInfo; private void updateDisplay() { @@ -134,10 +135,16 @@ namespace osu.Game.Screens.Select return; } - LoadComponentAsync(loadingInfo = new BeatmapInfoWedgeContainer(beatmap, ruleset.Value, mods.Value, beatmapDifficulty.Value ?? new StarDifficulty()) + LoadComponentAsync(loadingInfo = new Container { + RelativeSizeAxes = Axes.Both, Shear = -Shear, Depth = Container?.Depth + 1 ?? 0, + Children = new Drawable[] + { + new BeatmapInfoWedgeBackground(beatmap), + Info = new WedgeInfoText(beatmap, ruleset.Value, mods.Value, beatmapDifficulty.Value ?? new StarDifficulty()), + } }, loaded => { // ensure we are the most recent loaded wedge. @@ -520,35 +527,5 @@ namespace osu.Game.Screens.Select } } } - - public class BeatmapInfoWedgeContainer : Container - { - private readonly WorkingBeatmap beatmap; - private readonly RulesetInfo ruleset; - private readonly StarDifficulty starDifficulty; - private readonly IReadOnlyList mods; - - internal WedgeInfoText Info; - - public BeatmapInfoWedgeContainer(WorkingBeatmap beatmap, RulesetInfo ruleset, IReadOnlyList mods, StarDifficulty difficulty) - { - this.beatmap = beatmap; - this.ruleset = ruleset; - this.mods = mods; - starDifficulty = difficulty; - } - - [BackgroundDependencyLoader] - private void load() - { - RelativeSizeAxes = Axes.Both; - - Children = new Drawable[] - { - new BeatmapInfoWedgeBackground(beatmap), - Info = new WedgeInfoText(beatmap, ruleset, mods, starDifficulty), - }; - } - } } } From fe9ade6754360eb1e36c41f46c7d386d9b8565c4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 May 2021 02:14:04 +0900 Subject: [PATCH 133/134] Rename Container to DisplayedContent --- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 6 +++--- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 15 ++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index b9e92cba62..67c85a1120 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -140,11 +140,11 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () => { - containerBefore = infoWedge.Container; + containerBefore = infoWedge.DisplayedContent; infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : CreateWorkingBeatmap(b); }); - AddUntilStep("wait for async load", () => infoWedge.Container != containerBefore); + AddUntilStep("wait for async load", () => infoWedge.DisplayedContent != containerBefore); } private IBeatmap createTestBeatmap(RulesetInfo ruleset) @@ -194,7 +194,7 @@ namespace osu.Game.Tests.Visual.SongSelect private class TestBeatmapInfoWedge : BeatmapInfoWedge { - public new Container Container => base.Container; + public new Container DisplayedContent => base.DisplayedContent; public new WedgeInfoText Info => base.Info; } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 53ac97cc7d..d84052b94d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -48,7 +48,8 @@ namespace osu.Game.Screens.Select private IBindable beatmapDifficulty; - protected Container Container; + protected Container DisplayedContent; + protected WedgeInfoText Info; public BeatmapInfoWedge() @@ -110,7 +111,7 @@ namespace osu.Game.Screens.Select } } - public override bool IsPresent => base.IsPresent || Container == null; // Visibility is updated in the LoadComponentAsync callback + public override bool IsPresent => base.IsPresent || DisplayedContent == null; // Visibility is updated in the LoadComponentAsync callback private Container loadingInfo; @@ -124,9 +125,9 @@ namespace osu.Game.Screens.Select { State.Value = beatmap == null ? Visibility.Hidden : Visibility.Visible; - Container?.FadeOut(250); - Container?.Expire(); - Container = null; + DisplayedContent?.FadeOut(250); + DisplayedContent?.Expire(); + DisplayedContent = null; } if (beatmap == null) @@ -139,7 +140,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.Both, Shear = -Shear, - Depth = Container?.Depth + 1 ?? 0, + Depth = DisplayedContent?.Depth + 1 ?? 0, Children = new Drawable[] { new BeatmapInfoWedgeBackground(beatmap), @@ -151,7 +152,7 @@ namespace osu.Game.Screens.Select if (loaded != loadingInfo) return; removeOldInfo(); - Add(Container = loaded); + Add(DisplayedContent = loaded); }); } } From cffeb8641f484a860580bbcce38f977563e68674 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 May 2021 02:14:57 +0900 Subject: [PATCH 134/134] Make setters private for protected containers --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index d84052b94d..18615d9192 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -48,9 +48,9 @@ namespace osu.Game.Screens.Select private IBindable beatmapDifficulty; - protected Container DisplayedContent; + protected Container DisplayedContent { get; private set; } - protected WedgeInfoText Info; + protected WedgeInfoText Info { get; private set; } public BeatmapInfoWedge() {