From 16d34bcc0a04b319a53d86f20a863a837eb8d73d Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Mon, 12 Apr 2021 16:02:19 -0400 Subject: [PATCH 001/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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/267] 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 9f24cdb355bff38f788c6b2cb6e1f8bfce0b7e5b Mon Sep 17 00:00:00 2001 From: Denrage Date: Mon, 19 Apr 2021 16:53:44 +0200 Subject: [PATCH 023/267] Added Author Link in BeatmapInfoWedge --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 29 +++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 4069dc82ed..14e5831ef9 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -29,6 +29,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Screens.Ranking.Expanded; +using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Select { @@ -307,7 +308,7 @@ namespace osu.Game.Screens.Select Margin = new MarginPadding { Top = 10 }, Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, - Children = getMapper(metadata) + Children = new[] { getMapper(metadata) }, }, infoLabelContainer = new FillFlowContainer { @@ -430,24 +431,20 @@ namespace osu.Game.Screens.Select ForceRedraw(); } - private OsuSpriteText[] getMapper(BeatmapMetadata metadata) + private LinkFlowContainer getMapper(BeatmapMetadata metadata) { - if (string.IsNullOrEmpty(metadata.Author?.Username)) - return Array.Empty(); + if (metadata.Author == null) + return new LinkFlowContainer(); - return new[] + return new LinkFlowContainer(s => { - new OsuSpriteText - { - Text = "mapped by ", - Font = OsuFont.GetFont(size: 15), - }, - new OsuSpriteText - { - Text = metadata.Author.Username, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15), - } - }; + s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); + }).With(d => + { + d.AutoSizeAxes = Axes.Both; + d.AddText("mapped by "); + d.AddUserLink(metadata.Author); + }); } protected override void Dispose(bool isDisposing) From eb977312ed71bee57676714afb2a81c0522bdd9d Mon Sep 17 00:00:00 2001 From: Denrage Date: Mon, 19 Apr 2021 16:54:29 +0200 Subject: [PATCH 024/267] Added Author link in BeatmapSet Overlay --- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 31c1439c8f..1ffcf9722a 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -13,6 +13,8 @@ using osuTK.Graphics; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Users; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.BeatmapSet { @@ -50,7 +52,7 @@ namespace osu.Game.Overlays.BeatmapSet fields.Children = new Drawable[] { - new Field("mapped by", BeatmapSet.Metadata.Author.Username, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)), + new Field("mapped by", BeatmapSet.Metadata.Author, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)), new Field("submitted", online.Submitted, OsuFont.GetFont(weight: FontWeight.Bold)) { Margin = new MarginPadding { Top = 5 }, @@ -146,6 +148,25 @@ namespace osu.Game.Overlays.BeatmapSet } }; } + + public Field(string first, User second, FontUsage secondFont) + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + + Children = new[] + { + new LinkFlowContainer(s => + { + s.Font = OsuFont.GetFont(size: 11); + }).With(d => + { + d.AutoSizeAxes = Axes.Both; + d.AddText($"{first} "); + d.AddUserLink(second, s => s.Font = secondFont.With(size: 11)); + }), + }; + } } } } From 6bf6084ae9c3129d8a5672946e33205e8eabfcd3 Mon Sep 17 00:00:00 2001 From: Denrage Date: Mon, 19 Apr 2021 19:24:46 +0200 Subject: [PATCH 025/267] fixed according to suggestions --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 14e5831ef9..deb77c27de 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -308,7 +308,7 @@ namespace osu.Game.Screens.Select Margin = new MarginPadding { Top = 10 }, Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, - Children = new[] { getMapper(metadata) }, + Child = getMapper(metadata), }, infoLabelContainer = new FillFlowContainer { @@ -431,10 +431,10 @@ namespace osu.Game.Screens.Select ForceRedraw(); } - private LinkFlowContainer getMapper(BeatmapMetadata metadata) + private Drawable getMapper(BeatmapMetadata metadata) { if (metadata.Author == null) - return new LinkFlowContainer(); + return Empty(); return new LinkFlowContainer(s => { From c73bbf0aa7566c1bf33784caacb91fc786a7a2cc Mon Sep 17 00:00:00 2001 From: Denrage Date: Mon, 19 Apr 2021 19:24:58 +0200 Subject: [PATCH 026/267] Fixed Tests --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 7ea6373763..16afc5ace7 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("check version", () => infoWedge.Info.VersionLabel.Current.Value == $"{ruleset.ShortName}Version"); AddAssert("check title", () => infoWedge.Info.TitleLabel.Current.Value == $"{ruleset.ShortName}Source — {ruleset.ShortName}Title"); AddAssert("check artist", () => infoWedge.Info.ArtistLabel.Current.Value == $"{ruleset.ShortName}Artist"); - AddAssert("check author", () => infoWedge.Info.MapperContainer.Children.OfType().Any(s => s.Current.Value == $"{ruleset.ShortName}Author")); + AddAssert("check author", () => infoWedge.Info.MapperContainer.ChildrenOfType().Any(s => s.Current.Value == $"{ruleset.ShortName}Author")); } private void testInfoLabels(int expectedCount) @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("check empty version", () => string.IsNullOrEmpty(infoWedge.Info.VersionLabel.Current.Value)); 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 empty author", () => !infoWedge.Info.MapperContainer.ChildrenOfType().Any()); AddAssert("check no info labels", () => !infoWedge.Info.ChildrenOfType().Any()); } From 505a117862cce9818970a71833736c7a294b84c2 Mon Sep 17 00:00:00 2001 From: Denrage Date: Mon, 19 Apr 2021 23:41:51 +0200 Subject: [PATCH 027/267] 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 028/267] 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 029/267] 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 030/267] 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 031/267] 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 032/267] 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 033/267] 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 034/267] 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 035/267] 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 036/267] 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 037/267] 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 038/267] 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 039/267] 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 040/267] 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 decd8803bc6daa0669003e22115672dbda48033f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 24 Apr 2021 07:44:33 +0300 Subject: [PATCH 041/267] Abstract base appearence and hover update from drag handles --- .../Compose/Components/SelectionBoxControl.cs | 96 +++++++++++++++++++ .../Components/SelectionBoxDragHandle.cs | 77 +-------------- .../Components/SelectionBoxScaleHandle.cs | 17 ++++ 3 files changed, 116 insertions(+), 74 deletions(-) create mode 100644 osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs create mode 100644 osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs new file mode 100644 index 0000000000..3432334deb --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -0,0 +1,96 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Edit.Compose.Components +{ + /// + /// Represents the base appearance for UI controls of the , + /// such as scale handles, rotation handles, buttons, etc... + /// + public abstract class SelectionBoxControl : CompositeDrawable + { + public event Action OperationStarted; + public event Action OperationEnded; + + internal event Action HoverGained; + internal event Action HoverLost; + + private Circle circle; + + [Resolved] + protected OsuColour Colours { get; private set; } + + [BackgroundDependencyLoader] + private void load() + { + Origin = Anchor.Centre; + + InternalChildren = new Drawable[] + { + circle = new Circle + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + UpdateHoverState(); + } + + protected override bool OnHover(HoverEvent e) + { + UpdateHoverState(); + HoverGained?.Invoke(); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + HoverLost?.Invoke(); + UpdateHoverState(); + } + + /// + /// Whether this control is currently handling mouse down input. + /// + protected bool HandlingMouse { get; set; } + + protected override bool OnMouseDown(MouseDownEvent e) + { + HandlingMouse = true; + UpdateHoverState(); + return true; + } + + protected override void OnMouseUp(MouseUpEvent e) + { + HandlingMouse = false; + UpdateHoverState(); + base.OnMouseUp(e); + } + + protected virtual void UpdateHoverState() + { + circle.Colour = HandlingMouse ? Colours.GrayF : (IsHovered ? Colours.Red : Colours.YellowDark); + this.ScaleTo(HandlingMouse || IsHovered ? 1.5f : 1, 100, Easing.OutQuint); + } + + protected void OnOperationStarted() => OperationStarted?.Invoke(); + + protected void OnOperationEnded() => OperationEnded?.Invoke(); + } +} diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs index 921b4eb042..ea4f9704ef 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs @@ -2,75 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osuTK; namespace osu.Game.Screens.Edit.Compose.Components { - public class SelectionBoxDragHandle : Container + public abstract class SelectionBoxDragHandle : SelectionBoxControl { - public Action OperationStarted; - public Action OperationEnded; - public Action HandleDrag { get; set; } - private Circle circle; - - [Resolved] - private OsuColour colours { get; set; } - - [BackgroundDependencyLoader] - private void load() - { - Size = new Vector2(10); - Origin = Anchor.Centre; - - InternalChildren = new Drawable[] - { - circle = new Circle - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - UpdateHoverState(); - } - - protected override bool OnHover(HoverEvent e) - { - UpdateHoverState(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - UpdateHoverState(); - } - - protected bool HandlingMouse; - - protected override bool OnMouseDown(MouseDownEvent e) - { - HandlingMouse = true; - UpdateHoverState(); - return true; - } - protected override bool OnDragStart(DragStartEvent e) { - OperationStarted?.Invoke(); + OnOperationStarted(); return true; } @@ -83,23 +25,10 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void OnDragEnd(DragEndEvent e) { HandlingMouse = false; - OperationEnded?.Invoke(); + OnOperationEnded(); UpdateHoverState(); base.OnDragEnd(e); } - - protected override void OnMouseUp(MouseUpEvent e) - { - HandlingMouse = false; - UpdateHoverState(); - base.OnMouseUp(e); - } - - protected virtual void UpdateHoverState() - { - circle.Colour = HandlingMouse ? colours.GrayF : (IsHovered ? colours.Red : colours.YellowDark); - this.ScaleTo(HandlingMouse || IsHovered ? 1.5f : 1, 100, Easing.OutQuint); - } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs new file mode 100644 index 0000000000..a87c661f45 --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs @@ -0,0 +1,17 @@ +// 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 osuTK; + +namespace osu.Game.Screens.Edit.Compose.Components +{ + public class SelectionBoxScaleHandle : SelectionBoxDragHandle + { + [BackgroundDependencyLoader] + private void load() + { + Size = new Vector2(10); + } + } +} From 4bfa9cd6b6014a40666bf00492c95c8d888560f7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 24 Apr 2021 07:46:38 +0300 Subject: [PATCH 042/267] Change inheritance of selection box buttons to base control instead --- ...BoxDragHandleButton.cs => SelectionBoxButton.cs} | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) rename osu.Game/Screens/Edit/Compose/Components/{SelectionBoxDragHandleButton.cs => SelectionBoxButton.cs} (77%) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleButton.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs similarity index 77% rename from osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleButton.cs rename to osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs index 74ae949389..917e5189b2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs @@ -12,10 +12,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components { - /// - /// A drag "handle" which shares the visual appearance but behaves more like a clickable button. - /// - public sealed class SelectionBoxDragHandleButton : SelectionBoxDragHandle, IHasTooltip + public sealed class SelectionBoxButton : SelectionBoxControl, IHasTooltip { private SpriteIcon icon; @@ -23,7 +20,7 @@ namespace osu.Game.Screens.Edit.Compose.Components public Action Action; - public SelectionBoxDragHandleButton(IconUsage iconUsage, string tooltip) + public SelectionBoxButton(IconUsage iconUsage, string tooltip) { this.iconUsage = iconUsage; @@ -36,7 +33,7 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - Size *= 2; + Size = new Vector2(20); AddInternal(icon = new SpriteIcon { RelativeSizeAxes = Axes.Both, @@ -49,9 +46,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnClick(ClickEvent e) { - OperationStarted?.Invoke(); + OnOperationStarted(); Action?.Invoke(); - OperationEnded?.Invoke(); + OnOperationEnded(); return true; } From 206fc94b8c9e71be4dc3049003f63147bf735a22 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 24 Apr 2021 07:47:15 +0300 Subject: [PATCH 043/267] Add rotation drag handle component --- .../Components/SelectionBoxRotationHandle.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs new file mode 100644 index 0000000000..c4a4fafdc2 --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -0,0 +1,42 @@ +// 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.Extensions.EnumExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Edit.Compose.Components +{ + public class SelectionBoxRotationHandle : SelectionBoxDragHandle + { + private SpriteIcon icon; + + [BackgroundDependencyLoader] + private void load() + { + Size = new Vector2(15f); + AddInternal(icon = new SpriteIcon + { + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.Solid.Redo, + Scale = new Vector2 + { + X = Anchor.HasFlagFast(Anchor.x0) ? 1f : -1f, + Y = Anchor.HasFlagFast(Anchor.y0) ? 1f : -1f + } + }); + } + + protected override void UpdateHoverState() + { + icon.Colour = !HandlingMouse && IsHovered ? Color4.White : Color4.Black; + base.UpdateHoverState(); + } + } +} From 59ae5ab913f74d75677576e10d3b3a9484a713a7 Mon Sep 17 00:00:00 2001 From: Denrage Date: Sat, 24 Apr 2021 13:25:29 +0200 Subject: [PATCH 044/267] 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 62bcc5f76d891f45addc79500350be050f3b7fe9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Apr 2021 07:49:31 +0300 Subject: [PATCH 045/267] Add property for tracking whether control is during operation --- .../Compose/Components/SelectionBoxControl.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 3432334deb..081848f372 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -25,6 +25,11 @@ namespace osu.Game.Screens.Edit.Compose.Components private Circle circle; + /// + /// Whether an operation has began from this control. + /// + public bool InOperation { get; private set; } + [Resolved] protected OsuColour Colours { get; private set; } @@ -89,8 +94,16 @@ namespace osu.Game.Screens.Edit.Compose.Components this.ScaleTo(HandlingMouse || IsHovered ? 1.5f : 1, 100, Easing.OutQuint); } - protected void OnOperationStarted() => OperationStarted?.Invoke(); + protected void OnOperationStarted() + { + InOperation = true; + OperationStarted?.Invoke(); + } - protected void OnOperationEnded() => OperationEnded?.Invoke(); + protected void OnOperationEnded() + { + InOperation = false; + OperationEnded?.Invoke(); + } } } From ab7178267459a27b5a3a9896013cd09fe250dac9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Apr 2021 07:43:56 +0300 Subject: [PATCH 046/267] Use colour fade transform for selection box controls To become harminous with the fade transforms of the rotation control --- .../Edit/Compose/Components/SelectionBoxButton.cs | 2 +- .../Edit/Compose/Components/SelectionBoxControl.cs | 10 ++++++++-- .../Compose/Components/SelectionBoxRotationHandle.cs | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs index 917e5189b2..fbbebe3288 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void UpdateHoverState() { base.UpdateHoverState(); - icon.Colour = !HandlingMouse && IsHovered ? Color4.White : Color4.Black; + icon.FadeColour(!HandlingMouse && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint); } public string TooltipText { get; } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 081848f372..374af20742 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -17,6 +17,8 @@ namespace osu.Game.Screens.Edit.Compose.Components /// public abstract class SelectionBoxControl : CompositeDrawable { + public const double TRANSFORM_DURATION = 100; + public event Action OperationStarted; public event Action OperationEnded; @@ -90,8 +92,12 @@ namespace osu.Game.Screens.Edit.Compose.Components protected virtual void UpdateHoverState() { - circle.Colour = HandlingMouse ? Colours.GrayF : (IsHovered ? Colours.Red : Colours.YellowDark); - this.ScaleTo(HandlingMouse || IsHovered ? 1.5f : 1, 100, Easing.OutQuint); + if (HandlingMouse) + circle.FadeColour(Colours.GrayF, TRANSFORM_DURATION, Easing.OutQuint); + else + circle.FadeColour(IsHovered ? Colours.Red : Colours.YellowDark, TRANSFORM_DURATION, Easing.OutQuint); + + this.ScaleTo(HandlingMouse || IsHovered ? 1.5f : 1, TRANSFORM_DURATION, Easing.OutQuint); } protected void OnOperationStarted() diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index c4a4fafdc2..6303caf9ed 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -35,8 +35,8 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void UpdateHoverState() { - icon.Colour = !HandlingMouse && IsHovered ? Color4.White : Color4.Black; base.UpdateHoverState(); + icon.FadeColour(!HandlingMouse && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint); } } } From 77f7d4c9632e281d8665a81c55252f12b181e163 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 24 Apr 2021 08:06:00 +0300 Subject: [PATCH 047/267] Add composite managing display of selection box drag handles --- .../SelectionBoxDragHandleDisplay.cs | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleDisplay.cs diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleDisplay.cs new file mode 100644 index 0000000000..1cba8ca6b3 --- /dev/null +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleDisplay.cs @@ -0,0 +1,103 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Screens.Edit.Compose.Components +{ + /// + /// Represents a display composite containing and managing the visibility state of the selection box's drag handles. + /// + public class SelectionBoxDragHandleDisplay : CompositeDrawable + { + private Container scaleHandles; + private Container rotationHandles; + + private readonly List allDragHandles = new List(); + + public new MarginPadding Padding + { + get => base.Padding; + set => base.Padding = value; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + scaleHandles = new Container + { + RelativeSizeAxes = Axes.Both, + }, + rotationHandles = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(-12.5f), + }, + }; + } + + public void AddScaleHandle(SelectionBoxScaleHandle handle) + { + bindDragHandle(handle); + scaleHandles.Add(handle); + } + + public void AddRotationHandle(SelectionBoxRotationHandle handle) + { + handle.Alpha = 0; + handle.AlwaysPresent = true; + + bindDragHandle(handle); + rotationHandles.Add(handle); + } + + private void bindDragHandle(SelectionBoxDragHandle handle) + { + handle.HoverGained += updateRotationHandlesVisibility; + handle.HoverLost += updateRotationHandlesVisibility; + handle.OperationStarted += updateRotationHandlesVisibility; + handle.OperationEnded += updateRotationHandlesVisibility; + allDragHandles.Add(handle); + } + + private SelectionBoxRotationHandle displayedRotationHandle; + private SelectionBoxDragHandle activeHandle; + + private void updateRotationHandlesVisibility() + { + if (activeHandle?.InOperation == true || activeHandle?.IsHovered == true) + return; + + displayedRotationHandle?.FadeOut(SelectionBoxControl.TRANSFORM_DURATION, Easing.OutQuint); + displayedRotationHandle = null; + + activeHandle = allDragHandles.SingleOrDefault(h => h.InOperation); + activeHandle ??= allDragHandles.SingleOrDefault(h => h.IsHovered); + + if (activeHandle != null) + { + displayedRotationHandle = getCorrespondingRotationHandle(activeHandle, rotationHandles); + displayedRotationHandle?.FadeIn(SelectionBoxControl.TRANSFORM_DURATION, Easing.OutQuint); + } + } + + /// + /// Gets the rotation handle corresponding to the given handle. + /// + [CanBeNull] + private static SelectionBoxRotationHandle getCorrespondingRotationHandle(SelectionBoxDragHandle handle, IEnumerable rotationHandles) + { + if (handle is SelectionBoxRotationHandle rotationHandle) + return rotationHandle; + + return rotationHandles.SingleOrDefault(r => r.Anchor == handle.Anchor); + } + } +} From a8c460f7df0924830c3ad7c3b657a04eda8ed4c7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 24 Apr 2021 08:18:46 +0300 Subject: [PATCH 048/267] Replace separated top-centered rotation button with rotation drag handles --- .../Edit/Compose/Components/SelectionBox.cs | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 9d6b44e207..d7db98f6a2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - private Container dragHandles; + private SelectionBoxDragHandleDisplay dragHandles; private FillFlowContainer buttons; public const float BORDER_RADIUS = 3; @@ -161,7 +161,7 @@ namespace osu.Game.Screens.Edit.Compose.Components }, } }, - dragHandles = new Container + dragHandles = new SelectionBoxDragHandleDisplay { RelativeSizeAxes = Axes.Both, // ensures that the centres of all drag handles line up with the middle of the selection box border. @@ -186,75 +186,76 @@ namespace osu.Game.Screens.Edit.Compose.Components private void addRotationComponents() { - const float separation = 40; - addButton(FontAwesome.Solid.Undo, "Rotate 90 degrees counter-clockwise", () => OnRotation?.Invoke(-90)); addButton(FontAwesome.Solid.Redo, "Rotate 90 degrees clockwise", () => OnRotation?.Invoke(90)); - AddRangeInternal(new Drawable[] - { - new Box - { - Depth = float.MaxValue, - Colour = colours.YellowLight, - Blending = BlendingParameters.Additive, - Alpha = 0.3f, - Size = new Vector2(BORDER_RADIUS, separation), - Anchor = Anchor.TopCentre, - Origin = Anchor.BottomCentre, - }, - new SelectionBoxDragHandleButton(FontAwesome.Solid.Redo, "Free rotate") - { - Anchor = Anchor.TopCentre, - Y = -separation, - HandleDrag = e => OnRotation?.Invoke(convertDragEventToAngleOfRotation(e)), - OperationStarted = operationStarted, - OperationEnded = operationEnded - } - }); + addRotateHandle(Anchor.TopLeft); + addRotateHandle(Anchor.TopRight); + addRotateHandle(Anchor.BottomLeft); + addRotateHandle(Anchor.BottomRight); } private void addYScaleComponents() { addButton(FontAwesome.Solid.ArrowsAltV, "Flip vertically (Ctrl-J)", () => OnFlip?.Invoke(Direction.Vertical)); - addDragHandle(Anchor.TopCentre); - addDragHandle(Anchor.BottomCentre); + addScaleHandle(Anchor.TopCentre); + addScaleHandle(Anchor.BottomCentre); } private void addFullScaleComponents() { - addDragHandle(Anchor.TopLeft); - addDragHandle(Anchor.TopRight); - addDragHandle(Anchor.BottomLeft); - addDragHandle(Anchor.BottomRight); + addScaleHandle(Anchor.TopLeft); + addScaleHandle(Anchor.TopRight); + addScaleHandle(Anchor.BottomLeft); + addScaleHandle(Anchor.BottomRight); } private void addXScaleComponents() { addButton(FontAwesome.Solid.ArrowsAltH, "Flip horizontally (Ctrl-H)", () => OnFlip?.Invoke(Direction.Horizontal)); - addDragHandle(Anchor.CentreLeft); - addDragHandle(Anchor.CentreRight); + addScaleHandle(Anchor.CentreLeft); + addScaleHandle(Anchor.CentreRight); } private void addButton(IconUsage icon, string tooltip, Action action) { - buttons.Add(new SelectionBoxDragHandleButton(icon, tooltip) + var button = new SelectionBoxButton(icon, tooltip) { - OperationStarted = operationStarted, - OperationEnded = operationEnded, Action = action - }); + }; + + button.OperationStarted += operationStarted; + button.OperationEnded += operationEnded; + buttons.Add(button); } - private void addDragHandle(Anchor anchor) => dragHandles.Add(new SelectionBoxDragHandle + private void addScaleHandle(Anchor anchor) { - Anchor = anchor, - HandleDrag = e => OnScale?.Invoke(e.Delta, anchor), - OperationStarted = operationStarted, - OperationEnded = operationEnded - }); + var handle = new SelectionBoxScaleHandle + { + Anchor = anchor, + HandleDrag = e => OnScale?.Invoke(e.Delta, anchor) + }; + + handle.OperationStarted += operationStarted; + handle.OperationEnded += operationEnded; + dragHandles.AddScaleHandle(handle); + } + + private void addRotateHandle(Anchor anchor) + { + var handle = new SelectionBoxRotationHandle + { + Anchor = anchor, + HandleDrag = e => OnRotation?.Invoke(convertDragEventToAngleOfRotation(e)) + }; + + handle.OperationStarted += operationStarted; + handle.OperationEnded += operationEnded; + dragHandles.AddRotationHandle(handle); + } private int activeOperations; From 11318fd9fcbf8ffc4b9830dd4285037237e0f7b8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 24 Apr 2021 09:35:02 +0300 Subject: [PATCH 049/267] Add test coverage --- .../Editing/TestSceneComposeSelectBox.cs | 98 ++++++++++++++++++- 1 file changed, 95 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs index cf5f1b8818..13b563619a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs @@ -1,21 +1,24 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Game.Screens.Edit.Compose.Components; using osuTK; +using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public class TestSceneComposeSelectBox : OsuTestScene + public class TestSceneComposeSelectBox : OsuManualInputManagerTestScene { private Container selectionArea; + private SelectionBox selectionBox; public TestSceneComposeSelectBox() { - SelectionBox selectionBox = null; - AddStep("create box", () => Child = selectionArea = new Container { @@ -68,5 +71,94 @@ namespace osu.Game.Tests.Visual.Editing selectionArea.Rotation += angle; return true; } + + [SetUp] + public void SetUp() => Schedule(() => + { + InputManager.MoveMouseTo(selectionBox); + selectionBox.CanRotate = true; + selectionBox.CanScaleX = true; + selectionBox.CanScaleY = true; + }); + + [Test] + public void TestRotationHandleShownOnHover() + { + SelectionBoxRotationHandle rotationHandle = null; + + AddStep("enable rotation", () => selectionBox.CanRotate = true); + AddStep("retrieve rotation handle", () => rotationHandle = this.ChildrenOfType().First()); + + AddAssert("handle hidden", () => rotationHandle.Alpha == 0); + AddStep("hover over handle", () => InputManager.MoveMouseTo(rotationHandle)); + AddUntilStep("rotation handle shown", () => rotationHandle.Alpha == 1); + + AddStep("move mouse away", () => InputManager.MoveMouseTo(selectionBox)); + AddUntilStep("handle hidden", () => rotationHandle.Alpha == 0); + } + + [Test] + public void TestRotationHandleShownOnHoveringClosestScaleHandler() + { + SelectionBoxRotationHandle rotationHandle = null; + + AddStep("retrieve rotation handle", () => rotationHandle = this.ChildrenOfType().First()); + + AddAssert("rotation handle hidden", () => rotationHandle.Alpha == 0); + AddStep("hover over closest scale handle", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single(s => s.Anchor == rotationHandle.Anchor)); + }); + AddUntilStep("rotation handle shown", () => rotationHandle.Alpha == 1); + + AddStep("move mouse away", () => InputManager.MoveMouseTo(selectionBox)); + AddUntilStep("handle hidden", () => rotationHandle.Alpha == 0); + } + + [Test] + public void TestHoverRotationHandleFromScaleHandle() + { + SelectionBoxRotationHandle rotationHandle = null; + + AddStep("retrieve rotation handle", () => rotationHandle = this.ChildrenOfType().First()); + + AddAssert("rotation handle hidden", () => rotationHandle.Alpha == 0); + AddStep("hover over closest scale handle", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single(s => s.Anchor == rotationHandle.Anchor)); + }); + AddUntilStep("rotation handle shown", () => rotationHandle.Alpha == 1); + AddAssert("rotation handle not hovered", () => !rotationHandle.IsHovered); + + AddStep("hover over rotation handle", () => InputManager.MoveMouseTo(rotationHandle)); + AddAssert("rotation handle still shown", () => rotationHandle.Alpha == 1); + AddAssert("rotation handle hovered", () => rotationHandle.IsHovered); + + AddStep("move mouse away", () => InputManager.MoveMouseTo(selectionBox)); + AddUntilStep("handle hidden", () => rotationHandle.Alpha == 0); + } + + [Test] + public void TestDraggingScaleHandleKeepsCorrespondingRotationHandleShown() + { + SelectionBoxRotationHandle rotationHandle = null; + + AddStep("retrieve rotation handle", () => rotationHandle = this.ChildrenOfType().First()); + + AddAssert("rotation handle hidden", () => rotationHandle.Alpha == 0); + AddStep("hover over and hold closest scale handle", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single(s => s.Anchor == rotationHandle.Anchor)); + InputManager.PressButton(MouseButton.Left); + }); + AddUntilStep("rotation handle shown", () => rotationHandle.Alpha == 1); + + AddStep("drag to centre", () => InputManager.MoveMouseTo(selectionBox)); + AddAssert("rotation handle still shown", () => rotationHandle.Alpha > 0); + + AddStep("unhold left", () => InputManager.ReleaseButton(MouseButton.Left)); + AddStep("move mouse away", () => InputManager.MoveMouseTo(selectionBox, new Vector2(20))); + AddUntilStep("handle hidden", () => rotationHandle.Alpha == 0); + } } } From 79e2b232d8a18775731bd3cca9c479d787ca64b8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Apr 2021 19:26:53 +0300 Subject: [PATCH 050/267] Improve English MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 374af20742..9ad30a366d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private Circle circle; /// - /// Whether an operation has began from this control. + /// Whether this control is currently being operated on by the user. /// public bool InOperation { get; private set; } From 7490511ebf4b869a1b98793ac773fb92b1f6714e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Apr 2021 19:57:16 +0300 Subject: [PATCH 051/267] Instantiate selection box on SetUp --- .../Editing/TestSceneComposeSelectBox.cs | 47 +++++++------------ 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs index 13b563619a..7b939245a4 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs @@ -17,32 +17,30 @@ namespace osu.Game.Tests.Visual.Editing private Container selectionArea; private SelectionBox selectionBox; - public TestSceneComposeSelectBox() + [SetUp] + public void SetUp() => Schedule(() => { - AddStep("create box", () => - Child = selectionArea = new Container + Child = selectionArea = new Container + { + Size = new Vector2(400), + Position = -new Vector2(150), + Anchor = Anchor.Centre, + Children = new Drawable[] { - Size = new Vector2(400), - Position = -new Vector2(150), - Anchor = Anchor.Centre, - Children = new Drawable[] + selectionBox = new SelectionBox { - selectionBox = new SelectionBox - { - CanRotate = true, - CanScaleX = true, - CanScaleY = true, + CanRotate = true, + CanScaleX = true, + CanScaleY = true, - OnRotation = handleRotation, - OnScale = handleScale - } + OnRotation = handleRotation, + OnScale = handleScale } - }); + } + }; - AddToggleStep("toggle rotation", state => selectionBox.CanRotate = state); - AddToggleStep("toggle x", state => selectionBox.CanScaleX = state); - AddToggleStep("toggle y", state => selectionBox.CanScaleY = state); - } + InputManager.MoveMouseTo(selectionBox); + }); private bool handleScale(Vector2 amount, Anchor reference) { @@ -72,15 +70,6 @@ namespace osu.Game.Tests.Visual.Editing return true; } - [SetUp] - public void SetUp() => Schedule(() => - { - InputManager.MoveMouseTo(selectionBox); - selectionBox.CanRotate = true; - selectionBox.CanScaleX = true; - selectionBox.CanScaleY = true; - }); - [Test] public void TestRotationHandleShownOnHover() { From c58ef4230da768aad729e4785a156c80e83bad54 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Apr 2021 19:58:50 +0300 Subject: [PATCH 052/267] Inherit `VisibilityContainer` and make duration constant protected --- .../Edit/Compose/Components/SelectionBoxControl.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 9ad30a366d..501ce6381a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -15,9 +15,9 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Represents the base appearance for UI controls of the , /// such as scale handles, rotation handles, buttons, etc... /// - public abstract class SelectionBoxControl : CompositeDrawable + public abstract class SelectionBoxControl : VisibilityContainer { - public const double TRANSFORM_DURATION = 100; + protected const double TRANSFORM_DURATION = 100; public event Action OperationStarted; public event Action OperationEnded; @@ -90,6 +90,10 @@ namespace osu.Game.Screens.Edit.Compose.Components base.OnMouseUp(e); } + protected override void PopIn() => this.FadeIn(TRANSFORM_DURATION, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(TRANSFORM_DURATION, Easing.OutQuint); + protected virtual void UpdateHoverState() { if (HandlingMouse) From 7390a12e4b9bda91f0d4f4d374094abaf3fece92 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Apr 2021 19:59:08 +0300 Subject: [PATCH 053/267] SelectionBoxDragHandleDisplay -> SelectionBoxDragHandleContainer --- osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs | 4 ++-- ...gHandleDisplay.cs => SelectionBoxDragHandleContainer.cs} | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game/Screens/Edit/Compose/Components/{SelectionBoxDragHandleDisplay.cs => SelectionBoxDragHandleContainer.cs} (92%) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index d7db98f6a2..774ea076a5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } - private SelectionBoxDragHandleDisplay dragHandles; + private SelectionBoxDragHandleContainer dragHandles; private FillFlowContainer buttons; public const float BORDER_RADIUS = 3; @@ -161,7 +161,7 @@ namespace osu.Game.Screens.Edit.Compose.Components }, } }, - dragHandles = new SelectionBoxDragHandleDisplay + dragHandles = new SelectionBoxDragHandleContainer { RelativeSizeAxes = Axes.Both, // ensures that the centres of all drag handles line up with the middle of the selection box border. diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs similarity index 92% rename from osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleDisplay.cs rename to osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs index 1cba8ca6b3..151c169a33 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Represents a display composite containing and managing the visibility state of the selection box's drag handles. /// - public class SelectionBoxDragHandleDisplay : CompositeDrawable + public class SelectionBoxDragHandleContainer : CompositeDrawable { private Container scaleHandles; private Container rotationHandles; @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (activeHandle?.InOperation == true || activeHandle?.IsHovered == true) return; - displayedRotationHandle?.FadeOut(SelectionBoxControl.TRANSFORM_DURATION, Easing.OutQuint); + displayedRotationHandle?.Hide(); displayedRotationHandle = null; activeHandle = allDragHandles.SingleOrDefault(h => h.InOperation); @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (activeHandle != null) { displayedRotationHandle = getCorrespondingRotationHandle(activeHandle, rotationHandles); - displayedRotationHandle?.FadeIn(SelectionBoxControl.TRANSFORM_DURATION, Easing.OutQuint); + displayedRotationHandle?.Show(); } } From 334927ed35f3de3edae71467fafe69808c660008 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Apr 2021 20:11:41 +0300 Subject: [PATCH 054/267] Remove leftover step --- osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs index 7b939245a4..914b8b6f27 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs @@ -75,7 +75,6 @@ namespace osu.Game.Tests.Visual.Editing { SelectionBoxRotationHandle rotationHandle = null; - AddStep("enable rotation", () => selectionBox.CanRotate = true); AddStep("retrieve rotation handle", () => rotationHandle = this.ChildrenOfType().First()); AddAssert("handle hidden", () => rotationHandle.Alpha == 0); From b252485e1ab0dd5bfa38b35ce315219869fb45b0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Apr 2021 20:13:21 +0300 Subject: [PATCH 055/267] Remove protected expose of `HandlingMouse` setter Regardless of `OnDragEnd()`, `OnMouseUp()` will still be called resetting the value of that state back. --- osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs | 2 +- .../Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 501ce6381a..3a2fc7f83a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -74,7 +74,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Whether this control is currently handling mouse down input. /// - protected bool HandlingMouse { get; set; } + protected bool HandlingMouse { get; private set; } protected override bool OnMouseDown(MouseDownEvent e) { diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs index ea4f9704ef..d7e58df748 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs @@ -24,7 +24,6 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void OnDragEnd(DragEndEvent e) { - HandlingMouse = false; OnOperationEnded(); UpdateHoverState(); From 485da47d89d9fa4786935fcbd64c9a1d3b6eaac4 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 26 Apr 2021 01:41:36 +0300 Subject: [PATCH 056/267] Revert "Inherit `VisibilityContainer` and make duration constant protected" This reverts commit c58ef4230da768aad729e4785a156c80e83bad54. Uhh, how did I push this.. --- .../Edit/Compose/Components/SelectionBoxControl.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 3a2fc7f83a..38ed23fa13 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -15,9 +15,9 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Represents the base appearance for UI controls of the , /// such as scale handles, rotation handles, buttons, etc... /// - public abstract class SelectionBoxControl : VisibilityContainer + public abstract class SelectionBoxControl : CompositeDrawable { - protected const double TRANSFORM_DURATION = 100; + public const double TRANSFORM_DURATION = 100; public event Action OperationStarted; public event Action OperationEnded; @@ -90,10 +90,6 @@ namespace osu.Game.Screens.Edit.Compose.Components base.OnMouseUp(e); } - protected override void PopIn() => this.FadeIn(TRANSFORM_DURATION, Easing.OutQuint); - - protected override void PopOut() => this.FadeOut(TRANSFORM_DURATION, Easing.OutQuint); - protected virtual void UpdateHoverState() { if (HandlingMouse) From beee318acc92bd0831bcd19984807c7f029e54bf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 26 Apr 2021 01:45:50 +0300 Subject: [PATCH 057/267] Add more distance between each hit object in editor selection test To avoid potentially hovering over the rotation control instead of wherever the test desired to move the mouse to. --- .../Visual/Editing/TestSceneEditorSelection.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSelection.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSelection.cs index b82842e30d..4ce1d995a5 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSelection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSelection.cs @@ -50,9 +50,9 @@ namespace osu.Game.Tests.Visual.Editing AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects = new[] { new HitCircle { StartTime = 100 }, - new HitCircle { StartTime = 200, Position = new Vector2(50) }, - new HitCircle { StartTime = 300, Position = new Vector2(100) }, - new HitCircle { StartTime = 400, Position = new Vector2(150) }, + new HitCircle { StartTime = 200, Position = new Vector2(100) }, + new HitCircle { StartTime = 300, Position = new Vector2(200) }, + new HitCircle { StartTime = 400, Position = new Vector2(300) }, })); AddStep("select objects", () => EditorBeatmap.SelectedHitObjects.AddRange(addedObjects)); @@ -95,9 +95,9 @@ namespace osu.Game.Tests.Visual.Editing var addedObjects = new[] { new HitCircle { StartTime = 100 }, - new HitCircle { StartTime = 200, Position = new Vector2(50) }, - new HitCircle { StartTime = 300, Position = new Vector2(100) }, - new HitCircle { StartTime = 400, Position = new Vector2(150) }, + new HitCircle { StartTime = 200, Position = new Vector2(100) }, + new HitCircle { StartTime = 300, Position = new Vector2(200) }, + new HitCircle { StartTime = 400, Position = new Vector2(300) }, }; AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects)); @@ -131,9 +131,9 @@ namespace osu.Game.Tests.Visual.Editing AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects = new[] { new HitCircle { StartTime = 100 }, - new HitCircle { StartTime = 200, Position = new Vector2(50) }, - new HitCircle { StartTime = 300, Position = new Vector2(100) }, - new HitCircle { StartTime = 400, Position = new Vector2(150) }, + new HitCircle { StartTime = 200, Position = new Vector2(100) }, + new HitCircle { StartTime = 300, Position = new Vector2(200) }, + new HitCircle { StartTime = 400, Position = new Vector2(300) }, })); moveMouseToObject(() => addedObjects[0]); From b75b9a97edfcf27dd2d47dfa95cb34a1a159ae04 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 27 Apr 2021 14:09:58 +0700 Subject: [PATCH 058/267] add OsuMarkdownContainer All of the markdown file in osu-wiki have YAML frontmatter. This YAML is parsed as common markdown paragraph. So we add `UseYamlFrontMatter()` in markdown pipeline builder to parse YAML as `YamlFrontMatterBlock`. --- .../Markdown/OsuMarkdownContainer.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs new file mode 100644 index 0000000000..589c27f0a0 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig; +using Markdig.Extensions.AutoIdentifiers; +using Markdig.Extensions.Yaml; +using Markdig.Syntax; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Containers.Markdown; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownContainer : MarkdownContainer + { + protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level) + { + switch (markdownObject) + { + case YamlFrontMatterBlock _: + // Don't parse YAML Frontmatter + break; + + default: + base.AddMarkdownComponent(markdownObject, container, level); + break; + } + } + + protected override MarkdownPipeline CreateBuilder() + => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) + .UseEmojiAndSmiley() + .UseYamlFrontMatter() + .UseAdvancedExtensions().Build(); + } +} From aa07482cbb2f48a193e9afd1dda3ccbea2140170 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 27 Apr 2021 14:15:19 +0700 Subject: [PATCH 059/267] Add OsuMarkdownLinkText Color from https://github.com/ppy/osu-web/blob/d56352aeefc412507c3dab7c16e3e3118421b436/resources/assets/less/functions.less#L159-L165 --- .../Markdown/OsuMarkdownLinkText.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs new file mode 100644 index 0000000000..39b35fd84b --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig.Syntax.Inlines; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Sprites; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownLinkText : MarkdownLinkText + { + private SpriteText spriteText; + + public OsuMarkdownLinkText(string text, LinkInline linkInline) + : base(text, linkInline) + { + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + spriteText.Colour = colourProvider.Light2; + } + + public override SpriteText CreateSpriteText() + { + return spriteText = base.CreateSpriteText(); + } + } +} From c686c5224bdd8050f45c25fcf511dee0ac06f96a Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 27 Apr 2021 14:17:51 +0700 Subject: [PATCH 060/267] add OsuMarkdownTextFlowContainer --- .../Markdown/OsuMarkdownTextFlowContainer.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs new file mode 100644 index 0000000000..7a6818b4c2 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig.Syntax.Inlines; +using osu.Framework.Graphics.Containers.Markdown; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownTextFlowContainer : MarkdownTextFlowContainer + { + protected override void AddLinkText(string text, LinkInline linkInline) + => AddDrawable(new OsuMarkdownLinkText(text, linkInline)); + } +} From 6cccbabad83cd5743d51f63c088db7d68ecf3cf5 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 27 Apr 2021 14:19:16 +0700 Subject: [PATCH 061/267] override CreateTextFlow in OsuMarkdownContainer --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 589c27f0a0..fc7ced8ea7 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -12,6 +12,8 @@ namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownContainer : MarkdownContainer { + public override MarkdownTextFlowContainer CreateTextFlow() => new OsuMarkdownTextFlowContainer(); + protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level) { switch (markdownObject) From 65aa01866ee8fb6d14ef78ce3873e7bbad4692a8 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 27 Apr 2021 14:38:21 +0700 Subject: [PATCH 062/267] add test scene for OsuMarkdownContainer --- .../TestSceneOsuMarkdownContainer.cs | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs new file mode 100644 index 0000000000..9352404c07 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -0,0 +1,53 @@ +// 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers.Markdown; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneOsuMarkdownContainer : OsuTestScene + { + private OsuMarkdownContainer markdownContainer; + + [Cached] + private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Orange); + + [SetUp] + public void Setup() => Schedule(() => + { + Children = new Drawable[] + { + new Box + { + Colour = overlayColour.Background5, + RelativeSizeAxes = Axes.Both, + }, + new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(20), + Child = markdownContainer = new OsuMarkdownContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + } + } + }; + }); + + [Test] + public void TestLink() + { + AddStep("Add Link", () => + { + markdownContainer.Text = "[Welcome to osu!](https://osu.ppy.sh)"; + }); + } + } +} From 6959f2a8ccf182d2362553806f5e687a216237cd Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 27 Apr 2021 16:01:32 +0700 Subject: [PATCH 063/267] add OsuMarkdownFencedCodeBlock Reference : https://github.com/ppy/osu-web/blob/d56352aeefc412507c3dab7c16e3e3118421b436/resources/assets/less/bem/osu-md.less#L41-L45 --- .../TestSceneOsuMarkdownContainer.cs | 13 ++++++ .../Markdown/OsuMarkdownContainer.cs | 6 ++- .../Markdown/OsuMarkdownFencedCodeBlock.cs | 44 +++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 9352404c07..3d782ee184 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -49,5 +49,18 @@ namespace osu.Game.Tests.Visual.UserInterface markdownContainer.Text = "[Welcome to osu!](https://osu.ppy.sh)"; }); } + + [Test] + public void TestFencedCodeBlock() + { + AddStep("Add Code Block", () => + { + markdownContainer.Text = @"```markdown +# Markdown code block + +This is markdown code block. +```"; + }); + } } } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index fc7ced8ea7..95f538eab7 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -12,8 +12,6 @@ namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownContainer : MarkdownContainer { - public override MarkdownTextFlowContainer CreateTextFlow() => new OsuMarkdownTextFlowContainer(); - protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level) { switch (markdownObject) @@ -28,6 +26,10 @@ namespace osu.Game.Graphics.Containers.Markdown } } + public override MarkdownTextFlowContainer CreateTextFlow() => new OsuMarkdownTextFlowContainer(); + + protected override MarkdownFencedCodeBlock CreateFencedCodeBlock(FencedCodeBlock fencedCodeBlock) => new OsuMarkdownFencedCodeBlock(fencedCodeBlock); + protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) .UseEmojiAndSmiley() diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs new file mode 100644 index 0000000000..ddd88dd915 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig.Syntax; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownFencedCodeBlock : MarkdownFencedCodeBlock + { + private Box background; + private MarkdownTextFlowContainer textFlow; + + public OsuMarkdownFencedCodeBlock(FencedCodeBlock fencedCodeBlock) + : base(fencedCodeBlock) + { + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + // TODO : Change to monospace font to match with osu-web + background.Colour = colourProvider.Background6; + textFlow.Colour = colourProvider.Light1; + } + + protected override Drawable CreateBackground() + { + return background = new Box + { + RelativeSizeAxes = Axes.Both, + }; + } + + public override MarkdownTextFlowContainer CreateTextFlow() + { + return textFlow = base.CreateTextFlow(); + } + } +} From 6a921af08555a0b868cacc04a623f07b69e4211d Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 28 Apr 2021 09:23:05 +0700 Subject: [PATCH 064/267] add OsuMarkdownSeparator Reference https://github.com/ppy/osu-web/blob/d56352aeefc412507c3dab7c16e3e3118421b436/resources/assets/less/bem/osu-md.less#L19-L21 --- .../TestSceneOsuMarkdownContainer.cs | 13 ++++++++++ .../Markdown/OsuMarkdownContainer.cs | 2 ++ .../Markdown/OsuMarkdownSeparator.cs | 26 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 3d782ee184..966b5095f9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -62,5 +62,18 @@ This is markdown code block. ```"; }); } + + [Test] + public void TestSeparator() + { + AddStep("Add Seperator", () => + { + markdownContainer.Text = @"Line above + +--- + +Line below"; + }); + } } } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 95f538eab7..6885e3d60b 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -30,6 +30,8 @@ namespace osu.Game.Graphics.Containers.Markdown protected override MarkdownFencedCodeBlock CreateFencedCodeBlock(FencedCodeBlock fencedCodeBlock) => new OsuMarkdownFencedCodeBlock(fencedCodeBlock); + protected override MarkdownSeparator CreateSeparator(ThematicBreakBlock thematicBlock) => new OsuMarkdownSeparator(); + protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) .UseEmojiAndSmiley() diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs new file mode 100644 index 0000000000..9b28200452 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownSeparator : MarkdownSeparator + { + private Drawable separator; + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + separator.Colour = colourProvider.Background3; + } + + protected override Drawable CreateSeparator() + { + return separator = base.CreateSeparator(); + } + } +} From 736eace00ac68dd56dd86103e7a62a0eb17d13ee Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 28 Apr 2021 10:11:29 +0700 Subject: [PATCH 065/267] add OsuMarkdownQuoteBlock Reference: https://github.com/ppy/osu-web/blob/d56352aeefc412507c3dab7c16e3e3118421b436/resources/assets/less/base.less#L7-L10 --- .../TestSceneOsuMarkdownContainer.cs | 10 +++++ .../Markdown/OsuMarkdownContainer.cs | 2 + .../Markdown/OsuMarkdownQuoteBlock.cs | 45 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 966b5095f9..d78716bede 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -75,5 +75,15 @@ This is markdown code block. Line below"; }); } + + [Test] + public void TestQuote() + { + AddStep("Add quote", () => + { + markdownContainer.Text = + @"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."; + }); + } } } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 6885e3d60b..9f0000777d 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -32,6 +32,8 @@ namespace osu.Game.Graphics.Containers.Markdown protected override MarkdownSeparator CreateSeparator(ThematicBreakBlock thematicBlock) => new OsuMarkdownSeparator(); + protected override MarkdownQuoteBlock CreateQuoteBlock(QuoteBlock quoteBlock) => new OsuMarkdownQuoteBlock(quoteBlock); + protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) .UseEmojiAndSmiley() diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs new file mode 100644 index 0000000000..869cba82f2 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs @@ -0,0 +1,45 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig.Syntax; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownQuoteBlock : MarkdownQuoteBlock + { + private Drawable background; + + public OsuMarkdownQuoteBlock(QuoteBlock quoteBlock) + : base(quoteBlock) + { + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + background.Colour = colourProvider.Content2; + } + + protected override Drawable CreateBackground() + { + return background = base.CreateBackground(); + } + + public override MarkdownTextFlowContainer CreateTextFlow() + { + var textFlow = base.CreateTextFlow(); + textFlow.Margin = new MarginPadding + { + Top = 10, + Bottom = 10, + Left = 20, + Right = 20, + }; + return textFlow; + } + } +} From 2252d308c8a67e82c81d6b76e116f00cf6f0ea95 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 28 Apr 2021 10:53:00 +0700 Subject: [PATCH 066/267] add OsuMarkdownTableCell Reference : https://github.com/ppy/osu-web/blob/d56352aeefc412507c3dab7c16e3e3118421b436/resources/assets/less/bem/osu-md.less#L254-L277 --- .../Markdown/OsuMarkdownTableCell.cs | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs new file mode 100644 index 0000000000..d8b9145228 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.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 Markdig.Extensions.Tables; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownTableCell : MarkdownTableCell + { + private readonly bool isHeading; + + public OsuMarkdownTableCell(TableCell cell, TableColumnDefinition definition, bool isHeading) + : base(cell, definition) + { + this.isHeading = isHeading; + Masking = false; + BorderThickness = 0; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + var border = new Box + { + RelativeSizeAxes = Axes.X, + }; + + // TODO : Change font weight to 700 for heading + if (isHeading) + { + border.Colour = colourProvider.Background3; + border.Height = 2; + border.Anchor = Anchor.BottomLeft; + border.Origin = Anchor.BottomLeft; + } + else + { + border.Colour = colourProvider.Background4; + border.Height = 1; + border.Anchor = Anchor.TopLeft; + border.Origin = Anchor.TopLeft; + } + + AddInternal(border); + } + } +} From c09067c3d558d5a45dade3efb0aebcbb0d7dcefc Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 28 Apr 2021 10:53:12 +0700 Subject: [PATCH 067/267] add OsuMarkdownTable --- .../TestSceneOsuMarkdownContainer.cs | 14 ++++++++++++++ .../Markdown/OsuMarkdownContainer.cs | 3 +++ .../Containers/Markdown/OsuMarkdownTable.cs | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index d78716bede..d80d2362b9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -85,5 +85,19 @@ Line below"; @"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."; }); } + + [Test] + public void TestTable() + { + AddStep("Add Table", () => + { + markdownContainer.Text = + @"| Left Aligned | Center Aligned | Right Aligned | +| :------------------- | :--------------------: | ---------------------:| +| Long Align Left Text | Long Align Center Text | Long Align Right Text | +| Align Left | Align Center | Align Right | +| Left | Center | Right |"; + }); + } } } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 9f0000777d..56bf72656a 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -3,6 +3,7 @@ using Markdig; using Markdig.Extensions.AutoIdentifiers; +using Markdig.Extensions.Tables; using Markdig.Extensions.Yaml; using Markdig.Syntax; using osu.Framework.Graphics.Containers; @@ -34,6 +35,8 @@ namespace osu.Game.Graphics.Containers.Markdown protected override MarkdownQuoteBlock CreateQuoteBlock(QuoteBlock quoteBlock) => new OsuMarkdownQuoteBlock(quoteBlock); + protected override MarkdownTable CreateTable(Table table) => new OsuMarkdownTable(table); + protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) .UseEmojiAndSmiley() diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs new file mode 100644 index 0000000000..e0a1ab1220 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Markdig.Extensions.Tables; +using osu.Framework.Graphics.Containers.Markdown; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownTable : MarkdownTable + { + public OsuMarkdownTable(Table table) + : base(table) + { + } + + protected override MarkdownTableCell CreateTableCell(TableCell cell, TableColumnDefinition definition, bool isHeading) => new OsuMarkdownTableCell(cell, definition, isHeading); + } +} From 4e691ce4b06fb59a5a953a236a607cae2e53ebf7 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 28 Apr 2021 11:01:54 +0700 Subject: [PATCH 068/267] add test link with inline text markdown --- .../UserInterface/TestSceneOsuMarkdownContainer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index d80d2362b9..4add9f22a5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -50,6 +50,15 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + [Test] + public void TestLinkWithInlineText() + { + AddStep("Add Link with inline text", () => + { + markdownContainer.Text = "Hey, [welcome to osu!](https://osu.ppy.sh) Please enjoy the game."; + }); + } + [Test] public void TestFencedCodeBlock() { From 171e954e89b7e378f599e30d8525850b4aece2ff Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 29 Apr 2021 13:48:00 +0700 Subject: [PATCH 069/267] add unordered list test --- .../TestSceneOsuMarkdownContainer.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 4add9f22a5..11c06abee7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -108,5 +108,25 @@ Line below"; | Left | Center | Right |"; }); } + + [Test] + public void TestUnorderedList() + { + AddStep("Add Unordered List", () => + { + markdownContainer.Text = @"- First item level 1 +- Second item level 1 + - First item level 2 + - First item level 3 + - Second item level 3 + - Third item level 3 + - First item level 4 + - Second item level 4 + - Third item level 4 + - Second item level 2 + - Third item level 2 +- Third item level 1"; + }); + } } } From 2d17219c8fa8dd28de771604a12fd618e3cab6e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Apr 2021 19:56:49 +0900 Subject: [PATCH 070/267] Setup basic test and classes for scale adjustment --- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 42 +++++++++++++++++++ .../Play/HUD/SkinnableAccuracyCounter.cs | 2 +- .../Screens/Play/HUD/SkinnableHUDComponent.cs | 32 ++++++++++++++ .../Screens/Play/HUD/SkinnableScoreCounter.cs | 2 +- 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index fec1610160..029bf129c8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -4,17 +4,21 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; +using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay @@ -32,6 +36,32 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private OsuConfigManager config { get; set; } + protected override void LoadComplete() + { + base.LoadComplete(); + + Add(new Container + { + RelativeSizeAxes = Axes.Both, + Width = 0.3f, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + Alpha = 0.7f, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = createSkinSourceComponents(), + }, + } + }); + } + [Test] public void TestComboCounterIncrementing() { @@ -74,6 +104,18 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("key counter flow not affected", () => keyCounterFlow.IsPresent); } + private IReadOnlyList createSkinSourceComponents() + { + var hudComponents = typeof(SkinnableHUDComponent).Assembly.GetTypes().Where(t => typeof(SkinnableHUDComponent).IsAssignableFrom(t)).ToArray(); + + List drawables = new List(); + + foreach (var component in hudComponents) + drawables.AddRange(component.CreateSettingsControls()); + + return drawables; + } + private void createNew(Action action = null) { AddStep("create overlay", () => diff --git a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs index 76c9c30813..ebb3bcd148 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs @@ -6,7 +6,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableAccuracyCounter : SkinnableDrawable, IAccuracyCounter + public class SkinnableAccuracyCounter : SkinnableHUDComponent, IAccuracyCounter { public Bindable Current { get; } = new Bindable(); diff --git a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs new file mode 100644 index 0000000000..ea14a15348 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs @@ -0,0 +1,32 @@ +// 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.Graphics; +using osu.Game.Configuration; +using osu.Game.Skinning; + +namespace osu.Game.Screens.Play.HUD +{ + /// + /// A skinnable HUD component which can be scaled and repositioned at a skinner/user's will. + /// + public abstract class SkinnableHUDComponent : SkinnableDrawable + { + [SettingSource("Scale", "The scale at which this component should be displayed.")] + public BindableNumber SkinScale { get; } = new BindableFloat(1) + { + Precision = 0.1f, + MinValue = 0.1f, + MaxValue = 10, + Default = 1, + Value = 1, + }; + + protected SkinnableHUDComponent(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) + : base(component, defaultImplementation, allowFallback, confineMode) + { + } + } +} diff --git a/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs index b46f5684b1..9165b2c7f0 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs @@ -10,7 +10,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableScoreCounter : SkinnableDrawable, IScoreCounter + public class SkinnableScoreCounter : SkinnableHUDComponent, IScoreCounter { public Bindable Current { get; } = new Bindable(); From fca173225a2a8e8bf032f2e1019d197a64af1023 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Apr 2021 15:40:35 +0900 Subject: [PATCH 071/267] Refactor editor selection/blueprint components to be generic --- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 17 ++++++++++++++--- .../Screens/Play/HUD/SkinnableComboCounter.cs | 2 +- .../Screens/Play/HUD/SkinnableHealthDisplay.cs | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 029bf129c8..4f8a78368e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; @@ -13,6 +12,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Game.Configuration; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.Gameplay { Colour = Color4.Black, RelativeSizeAxes = Axes.Both, - Alpha = 0.7f, + Alpha = 0.9f, }, new FillFlowContainer { @@ -106,12 +106,23 @@ namespace osu.Game.Tests.Visual.Gameplay private IReadOnlyList createSkinSourceComponents() { - var hudComponents = typeof(SkinnableHUDComponent).Assembly.GetTypes().Where(t => typeof(SkinnableHUDComponent).IsAssignableFrom(t)).ToArray(); + Drawable[] hudComponents = typeof(SkinnableHUDComponent).Assembly + .GetTypes() + .Where(t => typeof(SkinnableHUDComponent).IsAssignableFrom(t)) + .Where(t => !t.IsAbstract) + .Select(t => Activator.CreateInstance(t) as Drawable) + .ToArray(); List drawables = new List(); foreach (var component in hudComponents) + { + drawables.Add(new OsuSpriteText + { + Text = component.GetType().Name + }); drawables.AddRange(component.CreateSettingsControls()); + } return drawables; } diff --git a/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs index c04c50141a..629bb467bc 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs @@ -6,7 +6,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableComboCounter : SkinnableDrawable, IComboCounter + public class SkinnableComboCounter : SkinnableHUDComponent, IComboCounter { public Bindable Current { get; } = new Bindable(); diff --git a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs index 1f91f5e50f..f8a8696dae 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs @@ -9,7 +9,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableHealthDisplay : SkinnableDrawable, IHealthDisplay + public class SkinnableHealthDisplay : SkinnableHUDComponent, IHealthDisplay { public Bindable Current { get; } = new BindableDouble(1) { From 99b428ee4b853033abfac1e0ee08a57c185d7a91 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Apr 2021 18:03:49 +0900 Subject: [PATCH 072/267] Add very basic skin editor test --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs new file mode 100644 index 0000000000..2391945b91 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -0,0 +1,222 @@ +// 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.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Logging; +using osu.Framework.Testing; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneSkinEditor : OsuTestScene + { + private HUDOverlay hudOverlay; + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create hud", () => + { + hudOverlay = new HUDOverlay(null, null, null, Array.Empty()); + + // Add any key just to display the key counter visually. + hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); + + hudOverlay.ComboCounter.Current.Value = 1; + }); + + AddStep("create editor overlay", () => Add(new SkinEditor(hudOverlay))); + } + + public class SkinEditor : CompositeDrawable + { + private readonly Drawable target; + + public SkinEditor(Drawable target) + { + this.target = target; + + RelativeSizeAxes = Axes.Both; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChildren = new[] + { + target, + new SkinBlueprintContainer(target), + }; + } + + public class SkinBlueprintContainer : BlueprintContainer + { + private readonly Drawable target; + + public SkinBlueprintContainer(Drawable target) + { + this.target = target; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + SkinnableHUDComponent[] components = target.ChildrenOfType().ToArray(); + + foreach (var c in components) + { + Logger.Log($"Adding blueprint for {c.GetType()}"); + AddBlueprintFor(c); + } + } + + protected override SelectionHandler CreateSelectionHandler() => new SkinSelectionHandler(); + + public class SkinSelectionHandler : SelectionHandler + { + protected override void DeleteItems(IEnumerable items) + { + foreach (var i in items) + i.Drawable.Expire(); + } + + protected override void OnSelectionChanged() + { + base.OnSelectionChanged(); + + SelectionBox.CanRotate = true; + SelectionBox.CanScaleX = true; + SelectionBox.CanScaleY = true; + SelectionBox.CanReverse = false; + } + + public override bool HandleRotation(float angle) + { + foreach (var c in SelectedBlueprints) + 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) + c.Item.Scale += scale * 0.01f; + + 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). + if ((reference & Anchor.x1) > 0) scale.X = 0; + if ((reference & Anchor.y1) > 0) scale.Y = 0; + + // reverse the scale direction if dragging from top or left. + if ((reference & Anchor.x0) > 0) scale.X = -scale.X; + if ((reference & Anchor.y0) > 0) scale.Y = -scale.Y; + } + + public override bool HandleMovement(MoveSelectionEvent moveEvent) + { + foreach (var c in SelectedBlueprints) + c.Item.Position += moveEvent.InstantDelta; + return true; + } + } + + protected override SelectionBlueprint CreateBlueprintFor(SkinnableHUDComponent component) + => new SkinBlueprint(component); + + public class SkinBlueprint : SelectionBlueprint + { + /// + /// The which this applies to. + /// + public readonly SkinnableHUDComponent Component; + + private Container box; + private Drawable drawable => Component.Drawable; + + /// + /// Whether the blueprint should be shown even when the is not alive. + /// + protected virtual bool AlwaysShowWhenSelected => false; + + protected override bool ShouldBeAlive => (Component.IsAlive && Component.IsPresent) || (AlwaysShowWhenSelected && State == SelectionState.Selected); + + public SkinBlueprint(SkinnableHUDComponent component) + : base(component) + { + Component = component; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChildren = new Drawable[] + { + box = new Container + { + Colour = colours.Yellow, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f, + AlwaysPresent = true, + }, + } + }, + }; + } + + private Quad drawableQuad; + + public override Quad ScreenSpaceDrawQuad => drawableQuad; + + protected override void Update() + { + base.Update(); + + drawableQuad = drawable.ScreenSpaceDrawQuad; + var quad = ToLocalSpace(drawable.ScreenSpaceDrawQuad); + + box.Position = quad.TopLeft; + box.Size = quad.Size; + box.Rotation = Component.Rotation; + } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => drawable.ReceivePositionalInputAt(screenSpacePos); + + public override Vector2 ScreenSpaceSelectionPoint => Component.ToScreenSpace(Vector2.Zero); + + public override Quad SelectionQuad => drawable.ScreenSpaceDrawQuad; + + public override Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Component.Parent.ToLocalSpace(screenSpacePosition) - Component.Position; + } + } + } + } +} From 74fb7cd180051a928cb714e291de09188beec55c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Apr 2021 14:21:07 +0900 Subject: [PATCH 073/267] Extract storable attributes to bindables --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 18 +++++----- .../Screens/Play/HUD/SkinnableHUDComponent.cs | 33 ++++++++++++++----- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 2391945b91..4594db36ae 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -111,7 +111,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override bool HandleRotation(float angle) { foreach (var c in SelectedBlueprints) - c.Item.Rotation += angle; + c.Item.SkinRotation.Value += angle; return base.HandleRotation(angle); } @@ -121,11 +121,18 @@ namespace osu.Game.Tests.Visual.Gameplay adjustScaleFromAnchor(ref scale, anchor); foreach (var c in SelectedBlueprints) - c.Item.Scale += scale * 0.01f; + c.Item.SkinScale.Value += scale.X * 0.01f; return true; } + public override bool HandleMovement(MoveSelectionEvent moveEvent) + { + foreach (var c in SelectedBlueprints) + c.Item.SkinPosition.Value += moveEvent.InstantDelta.X; + 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). @@ -136,13 +143,6 @@ namespace osu.Game.Tests.Visual.Gameplay if ((reference & Anchor.x0) > 0) scale.X = -scale.X; if ((reference & Anchor.y0) > 0) scale.Y = -scale.Y; } - - public override bool HandleMovement(MoveSelectionEvent moveEvent) - { - foreach (var c in SelectedBlueprints) - c.Item.Position += moveEvent.InstantDelta; - return true; - } } protected override SelectionBlueprint CreateBlueprintFor(SkinnableHUDComponent component) diff --git a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs index ea14a15348..5b8d313400 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs @@ -4,8 +4,10 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Layout; using osu.Game.Configuration; using osu.Game.Skinning; +using osuTK; namespace osu.Game.Screens.Play.HUD { @@ -15,18 +17,33 @@ namespace osu.Game.Screens.Play.HUD public abstract class SkinnableHUDComponent : SkinnableDrawable { [SettingSource("Scale", "The scale at which this component should be displayed.")] - public BindableNumber SkinScale { get; } = new BindableFloat(1) - { - Precision = 0.1f, - MinValue = 0.1f, - MaxValue = 10, - Default = 1, - Value = 1, - }; + public BindableNumber SkinScale { get; } = new BindableFloat(1); + + [SettingSource("Position", "The position at which this component should be displayed.")] + public BindableNumber SkinPosition { get; } = new BindableFloat(); + + [SettingSource("Rotation", "The rotation at which this component should be displayed.")] + public BindableNumber SkinRotation { get; } = new BindableFloat(); + + [SettingSource("Anchor", "The screen edge this component should align to.")] + public Bindable SkinAnchor { get; } = new Bindable(); protected SkinnableHUDComponent(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) : base(component, defaultImplementation, allowFallback, confineMode) { + SkinScale.BindValueChanged(scale => Drawable.Scale = new Vector2(scale.NewValue)); + SkinPosition.BindValueChanged(position => Position = new Vector2(position.NewValue)); + SkinRotation.BindValueChanged(rotation => Drawable.Rotation = rotation.NewValue); + SkinAnchor.BindValueChanged(anchor => Anchor = anchor.NewValue); + } + + protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) + { + SkinScale.Value = Drawable.Scale.X; + SkinPosition.Value = Position.X; + SkinRotation.Value = Drawable.Rotation; + SkinAnchor.Value = Anchor; + return base.OnInvalidate(invalidation, source); } } } From 1cb8fc9a241a2d07d43019c67f2b7312cc3aa69b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Apr 2021 15:14:48 +0900 Subject: [PATCH 074/267] Extract editor classes out of test namespace and add anchor support --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 213 ++---------------- .../Screens/Play/HUD/SkinnableHUDComponent.cs | 5 +- osu.Game/Skinning/Editor/SkinBlueprint.cs | 86 +++++++ .../Skinning/Editor/SkinBlueprintContainer.cs | 36 +++ osu.Game/Skinning/Editor/SkinEditor.cs | 36 +++ .../Skinning/Editor/SkinSelectionHandler.cs | 139 ++++++++++++ 6 files changed, 315 insertions(+), 200 deletions(-) create mode 100644 osu.Game/Skinning/Editor/SkinBlueprint.cs create mode 100644 osu.Game/Skinning/Editor/SkinBlueprintContainer.cs create mode 100644 osu.Game/Skinning/Editor/SkinEditor.cs create mode 100644 osu.Game/Skinning/Editor/SkinSelectionHandler.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 4594db36ae..e46cd70667 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -2,221 +2,36 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Logging; using osu.Framework.Testing; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; -using osu.Game.Screens.Play.HUD; -using osuTK; +using osu.Game.Skinning.Editor; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinEditor : OsuTestScene + public class TestSceneSkinEditor : SkinnableTestScene { - private HUDOverlay hudOverlay; - [SetUpSteps] public void SetUpSteps() { - AddStep("create hud", () => + AddStep("create editor overlay", () => { - hudOverlay = new HUDOverlay(null, null, null, Array.Empty()); + SetContents(() => + { + var hudOverlay = new HUDOverlay(null, null, null, Array.Empty()); - // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); + // Add any key just to display the key counter visually. + hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); + hudOverlay.ComboCounter.Current.Value = 1; - hudOverlay.ComboCounter.Current.Value = 1; + return new SkinEditor(hudOverlay); + }); }); - - AddStep("create editor overlay", () => Add(new SkinEditor(hudOverlay))); } - public class SkinEditor : CompositeDrawable - { - private readonly Drawable target; - - public SkinEditor(Drawable target) - { - this.target = target; - - RelativeSizeAxes = Axes.Both; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - InternalChildren = new[] - { - target, - new SkinBlueprintContainer(target), - }; - } - - public class SkinBlueprintContainer : BlueprintContainer - { - private readonly Drawable target; - - public SkinBlueprintContainer(Drawable target) - { - this.target = target; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - SkinnableHUDComponent[] components = target.ChildrenOfType().ToArray(); - - foreach (var c in components) - { - Logger.Log($"Adding blueprint for {c.GetType()}"); - AddBlueprintFor(c); - } - } - - protected override SelectionHandler CreateSelectionHandler() => new SkinSelectionHandler(); - - public class SkinSelectionHandler : SelectionHandler - { - protected override void DeleteItems(IEnumerable items) - { - foreach (var i in items) - i.Drawable.Expire(); - } - - protected override void OnSelectionChanged() - { - base.OnSelectionChanged(); - - SelectionBox.CanRotate = true; - SelectionBox.CanScaleX = true; - SelectionBox.CanScaleY = true; - SelectionBox.CanReverse = false; - } - - public override bool HandleRotation(float angle) - { - foreach (var c in SelectedBlueprints) - c.Item.SkinRotation.Value += angle; - - return base.HandleRotation(angle); - } - - public override bool HandleScale(Vector2 scale, Anchor anchor) - { - adjustScaleFromAnchor(ref scale, anchor); - - foreach (var c in SelectedBlueprints) - c.Item.SkinScale.Value += scale.X * 0.01f; - - return true; - } - - public override bool HandleMovement(MoveSelectionEvent moveEvent) - { - foreach (var c in SelectedBlueprints) - c.Item.SkinPosition.Value += moveEvent.InstantDelta.X; - 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). - if ((reference & Anchor.x1) > 0) scale.X = 0; - if ((reference & Anchor.y1) > 0) scale.Y = 0; - - // reverse the scale direction if dragging from top or left. - if ((reference & Anchor.x0) > 0) scale.X = -scale.X; - if ((reference & Anchor.y0) > 0) scale.Y = -scale.Y; - } - } - - protected override SelectionBlueprint CreateBlueprintFor(SkinnableHUDComponent component) - => new SkinBlueprint(component); - - public class SkinBlueprint : SelectionBlueprint - { - /// - /// The which this applies to. - /// - public readonly SkinnableHUDComponent Component; - - private Container box; - private Drawable drawable => Component.Drawable; - - /// - /// Whether the blueprint should be shown even when the is not alive. - /// - protected virtual bool AlwaysShowWhenSelected => false; - - protected override bool ShouldBeAlive => (Component.IsAlive && Component.IsPresent) || (AlwaysShowWhenSelected && State == SelectionState.Selected); - - public SkinBlueprint(SkinnableHUDComponent component) - : base(component) - { - Component = component; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - InternalChildren = new Drawable[] - { - box = new Container - { - Colour = colours.Yellow, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.2f, - AlwaysPresent = true, - }, - } - }, - }; - } - - private Quad drawableQuad; - - public override Quad ScreenSpaceDrawQuad => drawableQuad; - - protected override void Update() - { - base.Update(); - - drawableQuad = drawable.ScreenSpaceDrawQuad; - var quad = ToLocalSpace(drawable.ScreenSpaceDrawQuad); - - box.Position = quad.TopLeft; - box.Size = quad.Size; - box.Rotation = Component.Rotation; - } - - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => drawable.ReceivePositionalInputAt(screenSpacePos); - - public override Vector2 ScreenSpaceSelectionPoint => Component.ToScreenSpace(Vector2.Zero); - - public override Quad SelectionQuad => drawable.ScreenSpaceDrawQuad; - - public override Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Component.Parent.ToLocalSpace(screenSpacePosition) - Component.Position; - } - } - } + protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); } } diff --git a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs index 5b8d313400..2064f8589d 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs @@ -34,7 +34,10 @@ namespace osu.Game.Screens.Play.HUD SkinScale.BindValueChanged(scale => Drawable.Scale = new Vector2(scale.NewValue)); SkinPosition.BindValueChanged(position => Position = new Vector2(position.NewValue)); SkinRotation.BindValueChanged(rotation => Drawable.Rotation = rotation.NewValue); - SkinAnchor.BindValueChanged(anchor => Anchor = anchor.NewValue); + SkinAnchor.BindValueChanged(anchor => + { + Drawable.Anchor = anchor.NewValue; + }); } protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) diff --git a/osu.Game/Skinning/Editor/SkinBlueprint.cs b/osu.Game/Skinning/Editor/SkinBlueprint.cs new file mode 100644 index 0000000000..f9fffab579 --- /dev/null +++ b/osu.Game/Skinning/Editor/SkinBlueprint.cs @@ -0,0 +1,86 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +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; + +namespace osu.Game.Skinning.Editor +{ + public class SkinBlueprint : SelectionBlueprint + { + /// + /// The which this applies to. + /// + public readonly SkinnableHUDComponent Component; + + private Container box; + private Drawable drawable => Component.Drawable; + + /// + /// Whether the blueprint should be shown even when the is not alive. + /// + protected virtual bool AlwaysShowWhenSelected => false; + + protected override bool ShouldBeAlive => (Component.IsAlive && Component.IsPresent) || (AlwaysShowWhenSelected && State == SelectionState.Selected); + + public SkinBlueprint(SkinnableHUDComponent component) + : base(component) + { + Component = component; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChildren = new Drawable[] + { + box = new Container + { + Colour = colours.Yellow, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f, + AlwaysPresent = true, + }, + } + }, + }; + } + + private Quad drawableQuad; + + public override Quad ScreenSpaceDrawQuad => drawableQuad; + + protected override void Update() + { + base.Update(); + + drawableQuad = drawable.ScreenSpaceDrawQuad; + var quad = ToLocalSpace(drawable.ScreenSpaceDrawQuad); + + box.Position = quad.TopLeft; + box.Size = quad.Size; + box.Rotation = Component.Rotation; + } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => drawable.ReceivePositionalInputAt(screenSpacePos); + + public override Vector2 ScreenSpaceSelectionPoint => Component.ToScreenSpace(Vector2.Zero); + + public override Quad SelectionQuad => drawable.ScreenSpaceDrawQuad; + + public override Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Component.Parent.ToLocalSpace(screenSpacePosition) - Component.Position; + } +} diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs new file mode 100644 index 0000000000..ddf3fd28a7 --- /dev/null +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Testing; +using osu.Game.Rulesets.Edit; +using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Screens.Play.HUD; + +namespace osu.Game.Skinning.Editor +{ + public class SkinBlueprintContainer : BlueprintContainer + { + private readonly Drawable target; + + public SkinBlueprintContainer(Drawable target) + { + this.target = target; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + SkinnableHUDComponent[] components = target.ChildrenOfType().ToArray(); + + foreach (var c in components) AddBlueprintFor(c); + } + + protected override SelectionHandler CreateSelectionHandler() => new SkinSelectionHandler(); + + protected override SelectionBlueprint CreateBlueprintFor(SkinnableHUDComponent component) + => new SkinBlueprint(component); + } +} diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs new file mode 100644 index 0000000000..74d32bcb9f --- /dev/null +++ b/osu.Game/Skinning/Editor/SkinEditor.cs @@ -0,0 +1,36 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Cursor; + +namespace osu.Game.Skinning.Editor +{ + public class SkinEditor : CompositeDrawable + { + private readonly Drawable target; + + public SkinEditor(Drawable target) + { + this.target = target; + + RelativeSizeAxes = Axes.Both; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChild = new OsuContextMenuContainer + { + RelativeSizeAxes = Axes.Both, + Children = new[] + { + target, + new SkinBlueprintContainer(target), + } + }; + } + } +} diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs new file mode 100644 index 0000000000..4f28d4e0d2 --- /dev/null +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -0,0 +1,139 @@ +// 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.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Edit; +using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Screens.Play.HUD; +using osuTK; + +namespace osu.Game.Skinning.Editor +{ + public class SkinSelectionHandler : SelectionHandler + { + protected override void DeleteItems(IEnumerable items) + { + foreach (var i in items) + i.Drawable.Expire(); + } + + protected override IEnumerable GetContextMenuItemsForSelection(IEnumerable> selection) + { + yield return new OsuMenuItem("Anchor") + { + Items = createAnchorItems().ToArray() + }; + + foreach (var item in base.GetContextMenuItemsForSelection(selection)) + yield return item; + + IEnumerable createAnchorItems() + { + var displayableAnchors = new[] + { + Anchor.TopLeft, + Anchor.TopCentre, + Anchor.TopRight, + Anchor.CentreLeft, + Anchor.Centre, + Anchor.CentreRight, + Anchor.BottomLeft, + Anchor.BottomCentre, + Anchor.BottomRight, + }; + + return displayableAnchors.Select(a => + { + var countExisting = selection.Count(b => b.Item.SkinAnchor.Value == 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 } + }; + }); + } + } + + private void applyAnchor(Anchor anchor) + { + foreach (var item in SelectedItems) + item.SkinAnchor.Value = 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) + { + foreach (var c in SelectedBlueprints) + c.Item.SkinRotation.Value += angle; + + return base.HandleRotation(angle); + } + + public override bool HandleScale(Vector2 scale, Anchor anchor) + { + adjustScaleFromAnchor(ref scale, anchor); + + foreach (var c in SelectedBlueprints) + c.Item.SkinScale.Value += scale.X * 0.01f; + + return true; + } + + public override bool HandleMovement(MoveSelectionEvent moveEvent) + { + foreach (var c in SelectedBlueprints) + c.Item.SkinPosition.Value += moveEvent.InstantDelta.X; + 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). + if ((reference & Anchor.x1) > 0) scale.X = 0; + if ((reference & Anchor.y1) > 0) scale.Y = 0; + + // reverse the scale direction if dragging from top or left. + if ((reference & Anchor.x0) > 0) scale.X = -scale.X; + if ((reference & Anchor.y0) > 0) scale.Y = -scale.Y; + } + + public class AnchorMenuItem : TernaryStateMenuItem + { + public AnchorMenuItem(Anchor anchor, IEnumerable> selection, Action action) + : base(anchor.ToString(), getNextState, MenuItemType.Standard, action) + { + } + + private void updateState(TernaryState obj) + { + throw new NotImplementedException(); + } + + private static TernaryState getNextState(TernaryState state) => TernaryState.True; + } + } +} From 59339aa4fd3e46485c83c0a1c73eec18e45bddf9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Apr 2021 15:28:32 +0900 Subject: [PATCH 075/267] Add support for x/y position and scale back in --- .../Screens/Play/HUD/SkinnableHUDComponent.cs | 28 +++++++++++++------ .../Skinning/Editor/SkinSelectionHandler.cs | 11 ++++++-- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs index 2064f8589d..533573efd2 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs @@ -16,11 +16,17 @@ namespace osu.Game.Screens.Play.HUD /// public abstract class SkinnableHUDComponent : SkinnableDrawable { - [SettingSource("Scale", "The scale at which this component should be displayed.")] - public BindableNumber SkinScale { get; } = new BindableFloat(1); + [SettingSource("ScaleX", "The horizontal scale at which this component should be displayed.")] + public BindableNumber SkinScaleX { get; } = new BindableFloat(1); - [SettingSource("Position", "The position at which this component should be displayed.")] - public BindableNumber SkinPosition { get; } = new BindableFloat(); + [SettingSource("ScaleY", "The vertical scale at which this component should be displayed.")] + public BindableNumber SkinScaleY { get; } = new BindableFloat(1); + + [SettingSource("PositionX", "The horizontal position at which this component should be displayed.")] + public BindableNumber SkinPositionX { get; } = new BindableFloat(); + + [SettingSource("PositionY", "The vertical position at which this component should be displayed.")] + public BindableNumber SkinPositionY { get; } = new BindableFloat(); [SettingSource("Rotation", "The rotation at which this component should be displayed.")] public BindableNumber SkinRotation { get; } = new BindableFloat(); @@ -31,8 +37,12 @@ namespace osu.Game.Screens.Play.HUD protected SkinnableHUDComponent(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) : base(component, defaultImplementation, allowFallback, confineMode) { - SkinScale.BindValueChanged(scale => Drawable.Scale = new Vector2(scale.NewValue)); - SkinPosition.BindValueChanged(position => Position = new Vector2(position.NewValue)); + SkinScaleX.BindValueChanged(x => Drawable.Scale = new Vector2(x.NewValue, Drawable.Scale.Y)); + SkinScaleY.BindValueChanged(y => Drawable.Scale = new Vector2(Drawable.Scale.X, y.NewValue)); + + SkinPositionX.BindValueChanged(x => Position = new Vector2(x.NewValue, Position.Y)); + SkinPositionY.BindValueChanged(y => Position = new Vector2(Position.X, y.NewValue)); + SkinRotation.BindValueChanged(rotation => Drawable.Rotation = rotation.NewValue); SkinAnchor.BindValueChanged(anchor => { @@ -42,8 +52,10 @@ namespace osu.Game.Screens.Play.HUD protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) { - SkinScale.Value = Drawable.Scale.X; - SkinPosition.Value = Position.X; + SkinScaleX.Value = Drawable.Scale.X; + SkinScaleY.Value = Drawable.Scale.Y; + SkinPositionX.Value = Position.X; + SkinPositionY.Value = Position.Y; SkinRotation.Value = Drawable.Rotation; SkinAnchor.Value = Anchor; return base.OnInvalidate(invalidation, source); diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 4f28d4e0d2..55f36c73d6 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -98,7 +98,10 @@ namespace osu.Game.Skinning.Editor adjustScaleFromAnchor(ref scale, anchor); foreach (var c in SelectedBlueprints) - c.Item.SkinScale.Value += scale.X * 0.01f; + { + c.Item.SkinScaleX.Value += scale.X * 0.01f; + c.Item.SkinScaleY.Value += scale.Y * 0.01f; + } return true; } @@ -106,7 +109,11 @@ namespace osu.Game.Skinning.Editor public override bool HandleMovement(MoveSelectionEvent moveEvent) { foreach (var c in SelectedBlueprints) - c.Item.SkinPosition.Value += moveEvent.InstantDelta.X; + { + c.Item.SkinPositionX.Value += moveEvent.InstantDelta.X; + c.Item.SkinPositionY.Value += moveEvent.InstantDelta.Y; + } + return true; } From 2540d6029c4d804dd2e0378c35b58319349c8ebb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Apr 2021 17:47:28 +0900 Subject: [PATCH 076/267] Use AutoSize for SkinnableHudComponents --- .../Screens/Play/HUD/SkinnableHUDComponent.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs index 533573efd2..f5333c940f 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs @@ -37,26 +37,26 @@ namespace osu.Game.Screens.Play.HUD protected SkinnableHUDComponent(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) : base(component, defaultImplementation, allowFallback, confineMode) { - SkinScaleX.BindValueChanged(x => Drawable.Scale = new Vector2(x.NewValue, Drawable.Scale.Y)); - SkinScaleY.BindValueChanged(y => Drawable.Scale = new Vector2(Drawable.Scale.X, y.NewValue)); + SkinScaleX.BindValueChanged(x => Scale = new Vector2(x.NewValue, Scale.Y)); + SkinScaleY.BindValueChanged(y => Scale = new Vector2(Scale.X, y.NewValue)); SkinPositionX.BindValueChanged(x => Position = new Vector2(x.NewValue, Position.Y)); SkinPositionY.BindValueChanged(y => Position = new Vector2(Position.X, y.NewValue)); - SkinRotation.BindValueChanged(rotation => Drawable.Rotation = rotation.NewValue); - SkinAnchor.BindValueChanged(anchor => - { - Drawable.Anchor = anchor.NewValue; - }); + SkinRotation.BindValueChanged(rotation => Rotation = rotation.NewValue); + SkinAnchor.BindValueChanged(anchor => { Anchor = anchor.NewValue; }); + + RelativeSizeAxes = Axes.None; + AutoSizeAxes = Axes.Both; } protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) { - SkinScaleX.Value = Drawable.Scale.X; - SkinScaleY.Value = Drawable.Scale.Y; + SkinScaleX.Value = Scale.X; + SkinScaleY.Value = Scale.Y; SkinPositionX.Value = Position.X; SkinPositionY.Value = Position.Y; - SkinRotation.Value = Drawable.Rotation; + SkinRotation.Value = Rotation; SkinAnchor.Value = Anchor; return base.OnInvalidate(invalidation, source); } From defa350aa71cf07ffcee310fbfbde9dbc1c1c187 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Apr 2021 18:06:59 +0900 Subject: [PATCH 077/267] Set defaults on SkinnableHUDComponent to cancel out relative size default Specifying locally on each HUD component looks to make more sense. --- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 26 ------------------- .../Play/HUD/SkinnableAccuracyCounter.cs | 2 ++ .../Screens/Play/HUD/SkinnableComboCounter.cs | 2 ++ .../Screens/Play/HUD/SkinnableHUDComponent.cs | 6 ++++- .../Play/HUD/SkinnableHealthDisplay.cs | 3 +++ .../Screens/Play/HUD/SkinnableScoreCounter.cs | 2 ++ 6 files changed, 14 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 4f8a78368e..5c3d3c03bf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -36,32 +36,6 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private OsuConfigManager config { get; set; } - protected override void LoadComplete() - { - base.LoadComplete(); - - Add(new Container - { - RelativeSizeAxes = Axes.Both, - Width = 0.3f, - Children = new Drawable[] - { - new Box - { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, - Alpha = 0.9f, - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = createSkinSourceComponents(), - }, - } - }); - } - [Test] public void TestComboCounterIncrementing() { diff --git a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs index ebb3bcd148..33132adf23 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD @@ -14,6 +15,7 @@ namespace osu.Game.Screens.Play.HUD : base(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter), _ => new DefaultAccuracyCounter()) { CentreComponent = false; + AutoSizeAxes = Axes.Both; } private IAccuracyCounter skinnedCounter; diff --git a/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs index 629bb467bc..8785eccfc3 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD @@ -14,6 +15,7 @@ namespace osu.Game.Screens.Play.HUD : base(new HUDSkinComponent(HUDSkinComponents.ComboCounter), skinComponent => new DefaultComboCounter()) { CentreComponent = false; + AutoSizeAxes = Axes.Both; } private IComboCounter skinnedCounter; diff --git a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs index f5333c940f..7d23611718 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs @@ -46,8 +46,11 @@ namespace osu.Game.Screens.Play.HUD SkinRotation.BindValueChanged(rotation => Rotation = rotation.NewValue); SkinAnchor.BindValueChanged(anchor => { Anchor = anchor.NewValue; }); + // reset everything and require each component to specify what they want, + // as if they were just drawables. maybe we want to change SkinnableDrawable to not default + // to RelativeSizeAxes.Both... RelativeSizeAxes = Axes.None; - AutoSizeAxes = Axes.Both; + AutoSizeAxes = Axes.None; } protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) @@ -58,6 +61,7 @@ namespace osu.Game.Screens.Play.HUD SkinPositionY.Value = Position.Y; SkinRotation.Value = Rotation; SkinAnchor.Value = Anchor; + return base.OnInvalidate(invalidation, source); } } diff --git a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs index f8a8696dae..ceac147b63 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; @@ -35,6 +36,8 @@ namespace osu.Game.Screens.Play.HUD : base(new HUDSkinComponent(HUDSkinComponents.HealthDisplay), _ => new DefaultHealthDisplay()) { CentreComponent = false; + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; } private IHealthDisplay skinnedCounter; diff --git a/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs index 9165b2c7f0..c47baf95ff 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; @@ -22,6 +23,7 @@ namespace osu.Game.Screens.Play.HUD : base(new HUDSkinComponent(HUDSkinComponents.ScoreCounter), _ => new DefaultScoreCounter()) { CentreComponent = false; + AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader] From fd587a82ffe2f73ac5302b528222b0d8f42ad78b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Apr 2021 18:34:34 +0900 Subject: [PATCH 078/267] Replace abstract class with interface, attached to the actual components (not skinnable wrapper) --- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 27 -------- .../Play/HUD/DefaultAccuracyCounter.cs | 2 +- .../Screens/Play/HUD/DefaultComboCounter.cs | 2 +- .../Screens/Play/HUD/DefaultHealthDisplay.cs | 2 +- .../Screens/Play/HUD/DefaultScoreCounter.cs | 2 +- .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 2 +- .../Screens/Play/HUD/ISkinnableComponent.cs | 14 ++++ .../Screens/Play/HUD/LegacyComboCounter.cs | 2 +- .../Play/HUD/SkinnableAccuracyCounter.cs | 4 +- .../Screens/Play/HUD/SkinnableComboCounter.cs | 4 +- .../Screens/Play/HUD/SkinnableHUDComponent.cs | 68 ------------------- .../Play/HUD/SkinnableHealthDisplay.cs | 5 +- .../Screens/Play/HUD/SkinnableScoreCounter.cs | 4 +- osu.Game/Skinning/Editor/SkinBlueprint.cs | 17 ++--- .../Skinning/Editor/SkinBlueprintContainer.cs | 8 +-- .../Skinning/Editor/SkinSelectionHandler.cs | 26 +++---- osu.Game/Skinning/LegacyAccuracyCounter.cs | 2 +- osu.Game/Skinning/LegacyHealthDisplay.cs | 2 +- osu.Game/Skinning/LegacyScoreCounter.cs | 3 +- 19 files changed, 52 insertions(+), 144 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/ISkinnableComponent.cs delete mode 100644 osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 5c3d3c03bf..fec1610160 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -9,16 +9,12 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Game.Configuration; -using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; -using osu.Game.Screens.Play.HUD; -using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay @@ -78,29 +74,6 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("key counter flow not affected", () => keyCounterFlow.IsPresent); } - private IReadOnlyList createSkinSourceComponents() - { - Drawable[] hudComponents = typeof(SkinnableHUDComponent).Assembly - .GetTypes() - .Where(t => typeof(SkinnableHUDComponent).IsAssignableFrom(t)) - .Where(t => !t.IsAbstract) - .Select(t => Activator.CreateInstance(t) as Drawable) - .ToArray(); - - List drawables = new List(); - - foreach (var component in hudComponents) - { - drawables.Add(new OsuSpriteText - { - Text = component.GetType().Name - }); - drawables.AddRange(component.CreateSettingsControls()); - } - - return drawables; - } - private void createNew(Action action = null) { AddStep("create overlay", () => diff --git a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs index d5d8ec570a..b8a43708b4 100644 --- a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public class DefaultAccuracyCounter : PercentageCounter, IAccuracyCounter + public class DefaultAccuracyCounter : PercentageCounter, IAccuracyCounter, ISkinnableComponent { private readonly Vector2 offset = new Vector2(-20, 5); diff --git a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs index 63e7a88550..959766ecd1 100644 --- a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public class DefaultComboCounter : RollingCounter, IComboCounter + public class DefaultComboCounter : RollingCounter, IComboCounter, ISkinnableComponent { private readonly Vector2 offset = new Vector2(20, 5); diff --git a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs index b550b469e9..e3cd71691d 100644 --- a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs @@ -16,7 +16,7 @@ using osu.Framework.Utils; namespace osu.Game.Screens.Play.HUD { - public class DefaultHealthDisplay : HealthDisplay, IHasAccentColour + public class DefaultHealthDisplay : HealthDisplay, IHasAccentColour, ISkinnableComponent { /// /// The base opacity of the glow. diff --git a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs index 1dcfe2e067..dde5c18b38 100644 --- a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Play.HUD { - public class DefaultScoreCounter : ScoreCounter + public class DefaultScoreCounter : ScoreCounter, ISkinnableComponent { public DefaultScoreCounter() : base(6) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 89f135de7f..3b24c8cc9e 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { - public class BarHitErrorMeter : HitErrorMeter + public class BarHitErrorMeter : HitErrorMeter, ISkinnableComponent { private readonly Anchor alignment; diff --git a/osu.Game/Screens/Play/HUD/ISkinnableComponent.cs b/osu.Game/Screens/Play/HUD/ISkinnableComponent.cs new file mode 100644 index 0000000000..6d4558443f --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ISkinnableComponent.cs @@ -0,0 +1,14 @@ +// 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.Graphics; + +namespace osu.Game.Screens.Play.HUD +{ + /// + /// Denotes a drawable which, as a drawable, can be adjusted via skinning specifications. + /// + public interface ISkinnableComponent : IDrawable + { + } +} diff --git a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs index b4604c0d01..4ae722e44c 100644 --- a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Play.HUD /// /// Uses the 'x' symbol and has a pop-out effect while rolling over. /// - public class LegacyComboCounter : CompositeDrawable, IComboCounter + public class LegacyComboCounter : CompositeDrawable, IComboCounter, ISkinnableComponent { public Bindable Current { get; } = new BindableInt { MinValue = 0, }; diff --git a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs index 33132adf23..76c9c30813 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs @@ -2,12 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableAccuracyCounter : SkinnableHUDComponent, IAccuracyCounter + public class SkinnableAccuracyCounter : SkinnableDrawable, IAccuracyCounter { public Bindable Current { get; } = new Bindable(); @@ -15,7 +14,6 @@ namespace osu.Game.Screens.Play.HUD : base(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter), _ => new DefaultAccuracyCounter()) { CentreComponent = false; - AutoSizeAxes = Axes.Both; } private IAccuracyCounter skinnedCounter; diff --git a/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs index 8785eccfc3..c04c50141a 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs @@ -2,12 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableComboCounter : SkinnableHUDComponent, IComboCounter + public class SkinnableComboCounter : SkinnableDrawable, IComboCounter { public Bindable Current { get; } = new Bindable(); @@ -15,7 +14,6 @@ namespace osu.Game.Screens.Play.HUD : base(new HUDSkinComponent(HUDSkinComponents.ComboCounter), skinComponent => new DefaultComboCounter()) { CentreComponent = false; - AutoSizeAxes = Axes.Both; } private IComboCounter skinnedCounter; diff --git a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs b/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs deleted file mode 100644 index 7d23611718..0000000000 --- a/osu.Game/Screens/Play/HUD/SkinnableHUDComponent.cs +++ /dev/null @@ -1,68 +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.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Layout; -using osu.Game.Configuration; -using osu.Game.Skinning; -using osuTK; - -namespace osu.Game.Screens.Play.HUD -{ - /// - /// A skinnable HUD component which can be scaled and repositioned at a skinner/user's will. - /// - public abstract class SkinnableHUDComponent : SkinnableDrawable - { - [SettingSource("ScaleX", "The horizontal scale at which this component should be displayed.")] - public BindableNumber SkinScaleX { get; } = new BindableFloat(1); - - [SettingSource("ScaleY", "The vertical scale at which this component should be displayed.")] - public BindableNumber SkinScaleY { get; } = new BindableFloat(1); - - [SettingSource("PositionX", "The horizontal position at which this component should be displayed.")] - public BindableNumber SkinPositionX { get; } = new BindableFloat(); - - [SettingSource("PositionY", "The vertical position at which this component should be displayed.")] - public BindableNumber SkinPositionY { get; } = new BindableFloat(); - - [SettingSource("Rotation", "The rotation at which this component should be displayed.")] - public BindableNumber SkinRotation { get; } = new BindableFloat(); - - [SettingSource("Anchor", "The screen edge this component should align to.")] - public Bindable SkinAnchor { get; } = new Bindable(); - - protected SkinnableHUDComponent(ISkinComponent component, Func defaultImplementation, Func allowFallback = null, ConfineMode confineMode = ConfineMode.NoScaling) - : base(component, defaultImplementation, allowFallback, confineMode) - { - SkinScaleX.BindValueChanged(x => Scale = new Vector2(x.NewValue, Scale.Y)); - SkinScaleY.BindValueChanged(y => Scale = new Vector2(Scale.X, y.NewValue)); - - SkinPositionX.BindValueChanged(x => Position = new Vector2(x.NewValue, Position.Y)); - SkinPositionY.BindValueChanged(y => Position = new Vector2(Position.X, y.NewValue)); - - SkinRotation.BindValueChanged(rotation => Rotation = rotation.NewValue); - SkinAnchor.BindValueChanged(anchor => { Anchor = anchor.NewValue; }); - - // reset everything and require each component to specify what they want, - // as if they were just drawables. maybe we want to change SkinnableDrawable to not default - // to RelativeSizeAxes.Both... - RelativeSizeAxes = Axes.None; - AutoSizeAxes = Axes.None; - } - - protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) - { - SkinScaleX.Value = Scale.X; - SkinScaleY.Value = Scale.Y; - SkinPositionX.Value = Position.X; - SkinPositionY.Value = Position.Y; - SkinRotation.Value = Rotation; - SkinAnchor.Value = Anchor; - - return base.OnInvalidate(invalidation, source); - } - } -} diff --git a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs index ceac147b63..1f91f5e50f 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs @@ -3,14 +3,13 @@ using System; using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableHealthDisplay : SkinnableHUDComponent, IHealthDisplay + public class SkinnableHealthDisplay : SkinnableDrawable, IHealthDisplay { public Bindable Current { get; } = new BindableDouble(1) { @@ -36,8 +35,6 @@ namespace osu.Game.Screens.Play.HUD : base(new HUDSkinComponent(HUDSkinComponents.HealthDisplay), _ => new DefaultHealthDisplay()) { CentreComponent = false; - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; } private IHealthDisplay skinnedCounter; diff --git a/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs index c47baf95ff..b46f5684b1 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs @@ -4,14 +4,13 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableScoreCounter : SkinnableHUDComponent, IScoreCounter + public class SkinnableScoreCounter : SkinnableDrawable, IScoreCounter { public Bindable Current { get; } = new Bindable(); @@ -23,7 +22,6 @@ namespace osu.Game.Screens.Play.HUD : base(new HUDSkinComponent(HUDSkinComponents.ScoreCounter), _ => new DefaultScoreCounter()) { CentreComponent = false; - AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader] diff --git a/osu.Game/Skinning/Editor/SkinBlueprint.cs b/osu.Game/Skinning/Editor/SkinBlueprint.cs index f9fffab579..674153cb26 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprint.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprint.cs @@ -15,24 +15,25 @@ using osuTK; namespace osu.Game.Skinning.Editor { - public class SkinBlueprint : SelectionBlueprint + public class SkinBlueprint : SelectionBlueprint { /// /// The which this applies to. /// - public readonly SkinnableHUDComponent Component; + public readonly ISkinnableComponent Component; private Container box; - private Drawable drawable => Component.Drawable; + + private Drawable drawable => (Drawable)Component; /// /// Whether the blueprint should be shown even when the is not alive. /// protected virtual bool AlwaysShowWhenSelected => false; - protected override bool ShouldBeAlive => (Component.IsAlive && Component.IsPresent) || (AlwaysShowWhenSelected && State == SelectionState.Selected); + protected override bool ShouldBeAlive => (drawable.IsAlive && Component.IsPresent) || (AlwaysShowWhenSelected && State == SelectionState.Selected); - public SkinBlueprint(SkinnableHUDComponent component) + public SkinBlueprint(ISkinnableComponent component) : base(component) { Component = component; @@ -72,15 +73,15 @@ namespace osu.Game.Skinning.Editor box.Position = quad.TopLeft; box.Size = quad.Size; - box.Rotation = Component.Rotation; + box.Rotation = drawable.Rotation; } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => drawable.ReceivePositionalInputAt(screenSpacePos); - public override Vector2 ScreenSpaceSelectionPoint => Component.ToScreenSpace(Vector2.Zero); + public override Vector2 ScreenSpaceSelectionPoint => drawable.ToScreenSpace(Vector2.Zero); public override Quad SelectionQuad => drawable.ScreenSpaceDrawQuad; - public override Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Component.Parent.ToLocalSpace(screenSpacePosition) - Component.Position; + public override Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Component.Parent.ToLocalSpace(screenSpacePosition) - drawable.Position; } } diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs index ddf3fd28a7..f997e84355 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -10,7 +10,7 @@ using osu.Game.Screens.Play.HUD; namespace osu.Game.Skinning.Editor { - public class SkinBlueprintContainer : BlueprintContainer + public class SkinBlueprintContainer : BlueprintContainer { private readonly Drawable target; @@ -23,14 +23,14 @@ namespace osu.Game.Skinning.Editor { base.LoadComplete(); - SkinnableHUDComponent[] components = target.ChildrenOfType().ToArray(); + ISkinnableComponent[] components = target.ChildrenOfType().ToArray(); foreach (var c in components) AddBlueprintFor(c); } - protected override SelectionHandler CreateSelectionHandler() => new SkinSelectionHandler(); + protected override SelectionHandler CreateSelectionHandler() => new SkinSelectionHandler(); - protected override SelectionBlueprint CreateBlueprintFor(SkinnableHUDComponent component) + protected override SelectionBlueprint CreateBlueprintFor(ISkinnableComponent component) => new SkinBlueprint(component); } } diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 55f36c73d6..38404efd0c 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -14,15 +14,15 @@ using osuTK; namespace osu.Game.Skinning.Editor { - public class SkinSelectionHandler : SelectionHandler + public class SkinSelectionHandler : SelectionHandler { - protected override void DeleteItems(IEnumerable items) + protected override void DeleteItems(IEnumerable items) { foreach (var i in items) - i.Drawable.Expire(); + i.Hide(); } - protected override IEnumerable GetContextMenuItemsForSelection(IEnumerable> selection) + protected override IEnumerable GetContextMenuItemsForSelection(IEnumerable> selection) { yield return new OsuMenuItem("Anchor") { @@ -49,7 +49,7 @@ namespace osu.Game.Skinning.Editor return displayableAnchors.Select(a => { - var countExisting = selection.Count(b => b.Item.SkinAnchor.Value == a); + var countExisting = selection.Count(b => ((Drawable)b.Item).Anchor == a); var countTotal = selection.Count(); TernaryState state; @@ -72,7 +72,7 @@ namespace osu.Game.Skinning.Editor private void applyAnchor(Anchor anchor) { foreach (var item in SelectedItems) - item.SkinAnchor.Value = anchor; + ((Drawable)item).Anchor = anchor; } protected override void OnSelectionChanged() @@ -88,7 +88,7 @@ namespace osu.Game.Skinning.Editor public override bool HandleRotation(float angle) { foreach (var c in SelectedBlueprints) - c.Item.SkinRotation.Value += angle; + ((Drawable)c.Item).Rotation += angle; return base.HandleRotation(angle); } @@ -98,20 +98,16 @@ namespace osu.Game.Skinning.Editor adjustScaleFromAnchor(ref scale, anchor); foreach (var c in SelectedBlueprints) - { - c.Item.SkinScaleX.Value += scale.X * 0.01f; - c.Item.SkinScaleY.Value += scale.Y * 0.01f; - } + ((Drawable)c.Item).Scale += scale * 0.01f; return true; } - public override bool HandleMovement(MoveSelectionEvent moveEvent) + public override bool HandleMovement(MoveSelectionEvent moveEvent) { foreach (var c in SelectedBlueprints) { - c.Item.SkinPositionX.Value += moveEvent.InstantDelta.X; - c.Item.SkinPositionY.Value += moveEvent.InstantDelta.Y; + ((Drawable)c.Item).Position += moveEvent.InstantDelta; } return true; @@ -130,7 +126,7 @@ namespace osu.Game.Skinning.Editor public class AnchorMenuItem : TernaryStateMenuItem { - public AnchorMenuItem(Anchor anchor, IEnumerable> selection, Action action) + public AnchorMenuItem(Anchor anchor, IEnumerable> selection, Action action) : base(anchor.ToString(), getNextState, MenuItemType.Standard, action) { } diff --git a/osu.Game/Skinning/LegacyAccuracyCounter.cs b/osu.Game/Skinning/LegacyAccuracyCounter.cs index 7d6f1dc916..c592e06924 100644 --- a/osu.Game/Skinning/LegacyAccuracyCounter.cs +++ b/osu.Game/Skinning/LegacyAccuracyCounter.cs @@ -11,7 +11,7 @@ using osuTK; namespace osu.Game.Skinning { - public class LegacyAccuracyCounter : PercentageCounter, IAccuracyCounter + public class LegacyAccuracyCounter : PercentageCounter, IAccuracyCounter, ISkinnableComponent { private readonly ISkin skin; diff --git a/osu.Game/Skinning/LegacyHealthDisplay.cs b/osu.Game/Skinning/LegacyHealthDisplay.cs index 2921d46467..2e29abf453 100644 --- a/osu.Game/Skinning/LegacyHealthDisplay.cs +++ b/osu.Game/Skinning/LegacyHealthDisplay.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Skinning { - public class LegacyHealthDisplay : CompositeDrawable, IHealthDisplay + public class LegacyHealthDisplay : CompositeDrawable, IHealthDisplay, ISkinnableComponent { private const double epic_cutoff = 0.5; diff --git a/osu.Game/Skinning/LegacyScoreCounter.cs b/osu.Game/Skinning/LegacyScoreCounter.cs index 1d330ef495..cae8044242 100644 --- a/osu.Game/Skinning/LegacyScoreCounter.cs +++ b/osu.Game/Skinning/LegacyScoreCounter.cs @@ -5,11 +5,12 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Play.HUD; using osuTK; namespace osu.Game.Skinning { - public class LegacyScoreCounter : ScoreCounter + public class LegacyScoreCounter : ScoreCounter, ISkinnableComponent { private readonly ISkin skin; From 4f9e1e4945d002ea20a35855bd2bcdd160aa50eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Apr 2021 18:59:55 +0900 Subject: [PATCH 079/267] Check for new components every one second to handle late loaders --- osu.Game/Skinning/Editor/SkinBlueprintContainer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs index f997e84355..f2bc8ecddf 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -23,9 +23,14 @@ namespace osu.Game.Skinning.Editor { base.LoadComplete(); - ISkinnableComponent[] components = target.ChildrenOfType().ToArray(); + checkForComponents(); + } - foreach (var c in components) AddBlueprintFor(c); + private void checkForComponents() + { + foreach (var c in target.ChildrenOfType().ToArray()) AddBlueprintFor(c); + + Scheduler.AddDelayed(checkForComponents, 1000); } protected override SelectionHandler CreateSelectionHandler() => new SkinSelectionHandler(); From 74c6fdc4b8e52611b8e51645e19f27b9e042e5e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Apr 2021 19:00:16 +0900 Subject: [PATCH 080/267] Add `DrawableRuleset` to the skin editor test to get a hit error meter to display --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index e46cd70667..eaa0c29616 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -2,10 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Rulesets; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; using osu.Game.Skinning.Editor; using osuTK.Input; @@ -21,13 +26,32 @@ namespace osu.Game.Tests.Visual.Gameplay { SetContents(() => { - var hudOverlay = new HUDOverlay(null, null, null, Array.Empty()); + var ruleset = new OsuRuleset(); + var working = CreateWorkingBeatmap(ruleset.RulesetInfo); + var beatmap = working.GetPlayableBeatmap(ruleset.RulesetInfo); + + ScoreProcessor scoreProcessor = new ScoreProcessor(); + + var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap); + + var hudOverlay = new HUDOverlay(scoreProcessor, null, drawableRuleset, Array.Empty()); // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); hudOverlay.ComboCounter.Current.Value = 1; - return new SkinEditor(hudOverlay); + // Apply a miss judgement + scoreProcessor.ApplyResult(new JudgementResult(new HitObject(), new Judgement()) { Type = HitResult.Good }); + + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + drawableRuleset, + new SkinEditor(hudOverlay), + } + }; }); }); } From de73ac7ceccfa3d518baa6ec93190efda3ea2d24 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 13:53:01 +0900 Subject: [PATCH 081/267] Allow skin editor to be invoked from any context This is kind of how I see things working going forward, where the editor can be applied to anything in the game which supports it (ie. a results screen, gameplay screen, etc.) and it will immediately allow changing the interface. This adds a test scene which shows this working with gameplay. --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 59 +++++------------ .../TestSceneSkinEditorMultipleSkins.cs | 61 +++++++++++++++++ osu.Game/Skinning/Editor/SkinEditor.cs | 66 +++++++++++++++++-- 3 files changed, 138 insertions(+), 48 deletions(-) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index eaa0c29616..0c2c6ed454 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -1,61 +1,36 @@ // 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.Graphics; -using osu.Framework.Graphics.Containers; +using NUnit.Framework; using osu.Framework.Testing; using osu.Game.Rulesets; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; -using osu.Game.Rulesets.Scoring; -using osu.Game.Screens.Play; using osu.Game.Skinning.Editor; -using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { - public class TestSceneSkinEditor : SkinnableTestScene + public class TestSceneSkinEditor : PlayerTestScene { + private SkinEditor skinEditor; + [SetUpSteps] - public void SetUpSteps() + public override void SetUpSteps() { - AddStep("create editor overlay", () => + base.SetUpSteps(); + + AddStep("add editor overlay", () => { - SetContents(() => - { - var ruleset = new OsuRuleset(); - var working = CreateWorkingBeatmap(ruleset.RulesetInfo); - var beatmap = working.GetPlayableBeatmap(ruleset.RulesetInfo); - - ScoreProcessor scoreProcessor = new ScoreProcessor(); - - var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap); - - var hudOverlay = new HUDOverlay(scoreProcessor, null, drawableRuleset, Array.Empty()); - - // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); - hudOverlay.ComboCounter.Current.Value = 1; - - // Apply a miss judgement - scoreProcessor.ApplyResult(new JudgementResult(new HitObject(), new Judgement()) { Type = HitResult.Good }); - - return new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - drawableRuleset, - new SkinEditor(hudOverlay), - } - }; - }); + skinEditor?.Expire(); + LoadComponentAsync(skinEditor = new SkinEditor(Player), Add); }); } - protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); + [Test] + public void TestToggleEditor() + { + AddToggleStep("toggle editor visibility", visible => skinEditor.ToggleVisibility()); + } + + protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs new file mode 100644 index 0000000000..086bcb19c3 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -0,0 +1,61 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Skinning.Editor; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneSkinEditorMultipleSkins : SkinnableTestScene + { + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create editor overlay", () => + { + SetContents(() => + { + var ruleset = new OsuRuleset(); + var working = CreateWorkingBeatmap(ruleset.RulesetInfo); + var beatmap = working.GetPlayableBeatmap(ruleset.RulesetInfo); + + ScoreProcessor scoreProcessor = new ScoreProcessor(); + + var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap); + + var hudOverlay = new HUDOverlay(scoreProcessor, null, drawableRuleset, Array.Empty()) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + + // Add any key just to display the key counter visually. + hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); + hudOverlay.ComboCounter.Current.Value = 1; + + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + drawableRuleset, + hudOverlay, + new SkinEditor(hudOverlay), + } + }; + }); + }); + } + + protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); + } +} diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs index 74d32bcb9f..4f81fad4ba 100644 --- a/osu.Game/Skinning/Editor/SkinEditor.cs +++ b/osu.Game/Skinning/Editor/SkinEditor.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.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.Cursor; namespace osu.Game.Skinning.Editor { - public class SkinEditor : CompositeDrawable + public class SkinEditor : VisibilityContainer { private readonly Drawable target; + private Container border; + + protected override bool StartHidden => true; public SkinEditor(Drawable target) { @@ -18,19 +24,67 @@ namespace osu.Game.Skinning.Editor RelativeSizeAxes = Axes.Both; } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - base.LoadComplete(); - InternalChild = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - Children = new[] + Children = new Drawable[] { - target, + border = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderColour = colours.Yellow, + BorderThickness = 5, + CornerRadius = 5, + Children = new Drawable[] + { + new Box + { + AlwaysPresent = true, + Alpha = 0, + RelativeSizeAxes = Axes.Both, + }, + } + }, new SkinBlueprintContainer(target), } }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + Show(); + } + + private const double transition_duration = 500; + private const float visible_target_scale = 0.8f; + + protected override void PopIn() + { + if (IsLoaded) + { + target.ScaleTo(visible_target_scale, transition_duration, Easing.OutQuint); + border.ScaleTo(visible_target_scale, transition_duration, Easing.OutQuint); + } + + this.FadeIn(transition_duration); + } + + protected override void PopOut() + { + if (IsLoaded) + { + target.ScaleTo(1, transition_duration, Easing.OutQuint); + border.ScaleTo(1, transition_duration, Easing.OutQuint); + } + + this.FadeOut(transition_duration, Easing.OutQuint); + } } } From 3c84b0d8c624db113873e8b53a4f1f6cf491ba0c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 14:07:15 +0900 Subject: [PATCH 082/267] Fix selection screen point being wrong since recent refactors --- osu.Game/Skinning/Editor/SkinBlueprint.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinBlueprint.cs b/osu.Game/Skinning/Editor/SkinBlueprint.cs index 674153cb26..2cee94b2c6 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprint.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprint.cs @@ -78,10 +78,10 @@ namespace osu.Game.Skinning.Editor public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => drawable.ReceivePositionalInputAt(screenSpacePos); - public override Vector2 ScreenSpaceSelectionPoint => drawable.ToScreenSpace(Vector2.Zero); + public override Vector2 ScreenSpaceSelectionPoint => drawable.Parent.ToScreenSpace(drawable.DrawPosition); public override Quad SelectionQuad => drawable.ScreenSpaceDrawQuad; - public override Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Component.Parent.ToLocalSpace(screenSpacePosition) - drawable.Position; + public override Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Component.Parent.ToLocalSpace(screenSpacePosition) - drawable.DrawPosition; } } From 434e63d6297c9e6db9ed3a70562faa519c67ac8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 14:14:04 +0900 Subject: [PATCH 083/267] Add skin customisation support to song progress display --- osu.Game/Screens/Play/SongProgress.cs | 57 +++++++++++++++++---------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 6c7cb9376c..db81633aea 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -14,6 +14,7 @@ using osu.Framework.Timing; using osu.Game.Configuration; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play.HUD; namespace osu.Game.Screens.Play { @@ -71,30 +72,38 @@ namespace osu.Game.Screens.Play public SongProgress() { - Masking = true; - Children = new Drawable[] { - info = new SongProgressInfo + new SongProgressDisplay { - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = info_height, - }, - graph = new SongProgressGraph - { - RelativeSizeAxes = Axes.X, - Origin = Anchor.BottomLeft, - Anchor = Anchor.BottomLeft, - Height = graph_height, - Margin = new MarginPadding { Bottom = bottom_bar_height }, - }, - bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size) - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - OnSeek = time => RequestSeek?.Invoke(time), + Masking = true, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Children = new Drawable[] + { + info = new SongProgressInfo + { + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = info_height, + }, + graph = new SongProgressGraph + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + Height = graph_height, + Margin = new MarginPadding { Bottom = bottom_bar_height }, + }, + bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + OnSeek = time => RequestSeek?.Invoke(time), + }, + } }, }; } @@ -175,5 +184,11 @@ namespace osu.Game.Screens.Play float finalMargin = bottom_bar_height + (AllowSeeking.Value ? handle_size.Y : 0) + (ShowGraph.Value ? graph_height : 0); info.TransformTo(nameof(info.Margin), new MarginPadding { Bottom = finalMargin }, transition_duration, Easing.In); } + + public class SongProgressDisplay : Container, ISkinnableComponent + { + // TODO: move actual implementation into this. + // exists for skin customisation purposes. + } } } From 1516e2ffef7228cff1f7d3c70ba7224dd9345a47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 15:29:25 +0900 Subject: [PATCH 084/267] Update blueprint implementation in line with #12625. --- osu.Game/Skinning/Editor/SkinBlueprint.cs | 4 +--- osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinBlueprint.cs b/osu.Game/Skinning/Editor/SkinBlueprint.cs index 2cee94b2c6..491a403325 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprint.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprint.cs @@ -78,10 +78,8 @@ namespace osu.Game.Skinning.Editor public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => drawable.ReceivePositionalInputAt(screenSpacePos); - public override Vector2 ScreenSpaceSelectionPoint => drawable.Parent.ToScreenSpace(drawable.DrawPosition); + public override Vector2 ScreenSpaceSelectionPoint => drawable.ScreenSpaceDrawQuad.Centre; public override Quad SelectionQuad => drawable.ScreenSpaceDrawQuad; - - public override Vector2 GetInstantDelta(Vector2 screenSpacePosition) => Component.Parent.ToLocalSpace(screenSpacePosition) - drawable.DrawPosition; } } diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 38404efd0c..466136f0a8 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; +using osu.Game.Extensions; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose.Components; @@ -107,7 +108,8 @@ namespace osu.Game.Skinning.Editor { foreach (var c in SelectedBlueprints) { - ((Drawable)c.Item).Position += moveEvent.InstantDelta; + Drawable drawable = (Drawable)c.Item; + drawable.Position += drawable.ScreenSpaceDeltaToParentSpace(moveEvent.ScreenSpaceDelta); } return true; From b460181f15ea13569fdce9a557cda060b6775634 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 16:16:52 +0900 Subject: [PATCH 085/267] Add note about rotation not working as expected --- osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 466136f0a8..17b459a916 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -88,6 +88,7 @@ namespace osu.Game.Skinning.Editor 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; From 141d3af302e1443af684b8658e8eca180d9e746a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 17:19:47 +0900 Subject: [PATCH 086/267] Add the ability to temporarily disable user scaling on a `ScalingContainer` --- .../Graphics/Containers/ScalingContainer.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 8f07c3a656..b691e372c5 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -36,6 +36,24 @@ namespace osu.Game.Graphics.Containers private BackgroundScreenStack backgroundStack; + private bool allowScaling = true; + + /// + /// Whether user scaling preferences should be applied. Enabled by default. + /// + public bool AllowScaling + { + get => allowScaling; + set + { + if (value == allowScaling) + return; + + allowScaling = value; + updateSize(); + } + } + /// /// Create a new instance. /// @@ -139,7 +157,7 @@ namespace osu.Game.Graphics.Containers backgroundStack?.FadeOut(fade_time); } - bool scaling = targetMode == null || scalingMode.Value == targetMode; + bool scaling = AllowScaling && (targetMode == null || scalingMode.Value == targetMode); var targetSize = scaling ? new Vector2(sizeX.Value, sizeY.Value) : Vector2.One; var targetPosition = scaling ? new Vector2(posX.Value, posY.Value) * (Vector2.One - targetSize) : Vector2.Zero; From b93604395673af6dc74631f6601a241d06aac53f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 17:20:22 +0900 Subject: [PATCH 087/267] Add the skin editor to the game --- .../Input/Bindings/GlobalActionContainer.cs | 6 +- osu.Game/OsuGame.cs | 8 ++ osu.Game/Skinning/Editor/SkinEditor.cs | 50 +++-------- .../Skinning/Editor/SkinEditorContainer.cs | 87 +++++++++++++++++++ 4 files changed, 110 insertions(+), 41 deletions(-) create mode 100644 osu.Game/Skinning/Editor/SkinEditorContainer.cs diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 6717de5658..ce945f3bf8 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -48,6 +48,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings), new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleBeatmapListing), new KeyBinding(new[] { InputKey.Control, InputKey.N }, GlobalAction.ToggleNotifications), + new KeyBinding(new[] { InputKey.Shift, InputKey.F2 }, GlobalAction.ToggleSkinEditor), new KeyBinding(InputKey.Escape, GlobalAction.Back), new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back), @@ -258,6 +259,9 @@ namespace osu.Game.Input.Bindings EditorNudgeLeft, [Description("Nudge selection right")] - EditorNudgeRight + EditorNudgeRight, + + [Description("Toggle skin editor")] + ToggleSkinEditor, } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 28f32ba455..67e0e6a81c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -51,6 +51,7 @@ using osu.Game.Utils; using LogLevel = osu.Framework.Logging.LogLevel; using osu.Game.Database; using osu.Game.IO; +using osu.Game.Skinning.Editor; namespace osu.Game { @@ -597,6 +598,8 @@ namespace osu.Game screenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays) { RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Children = new Drawable[] { receptor = new BackButton.Receptor(), @@ -616,6 +619,7 @@ namespace osu.Game logoContainer = new Container { RelativeSizeAxes = Axes.Both }, } }, + skinEditor = new SkinEditorContainer(screenContainer), overlayContent = new Container { RelativeSizeAxes = Axes.Both }, rightFloatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, leftFloatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, @@ -942,6 +946,8 @@ namespace osu.Game private ScalingContainer screenContainer; + private SkinEditorContainer skinEditor; + protected override bool OnExiting() { if (ScreenStack.CurrentScreen is Loader) @@ -968,6 +974,8 @@ namespace osu.Game protected virtual void ScreenChanged(IScreen current, IScreen newScreen) { + skinEditor.Reset(); + switch (newScreen) { case IntroScreen intro: diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs index 4f81fad4ba..fdef4d0fce 100644 --- a/osu.Game/Skinning/Editor/SkinEditor.cs +++ b/osu.Game/Skinning/Editor/SkinEditor.cs @@ -4,16 +4,16 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; +using osu.Framework.Input.Events; using osu.Game.Graphics.Cursor; namespace osu.Game.Skinning.Editor { - public class SkinEditor : VisibilityContainer + public class SkinEditor : FocusedOverlayContainer { + public const double TRANSITION_DURATION = 500; + private readonly Drawable target; - private Container border; protected override bool StartHidden => true; @@ -25,32 +25,13 @@ namespace osu.Game.Skinning.Editor } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { InternalChild = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - border = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderColour = colours.Yellow, - BorderThickness = 5, - CornerRadius = 5, - Children = new Drawable[] - { - new Box - { - AlwaysPresent = true, - Alpha = 0, - RelativeSizeAxes = Axes.Both, - }, - } - }, new SkinBlueprintContainer(target), } }; @@ -62,29 +43,18 @@ namespace osu.Game.Skinning.Editor Show(); } - private const double transition_duration = 500; - private const float visible_target_scale = 0.8f; + protected override bool OnHover(HoverEvent e) => true; + + protected override bool OnMouseDown(MouseDownEvent e) => true; protected override void PopIn() { - if (IsLoaded) - { - target.ScaleTo(visible_target_scale, transition_duration, Easing.OutQuint); - border.ScaleTo(visible_target_scale, transition_duration, Easing.OutQuint); - } - - this.FadeIn(transition_duration); + this.FadeIn(TRANSITION_DURATION, Easing.OutQuint); } protected override void PopOut() { - if (IsLoaded) - { - target.ScaleTo(1, transition_duration, Easing.OutQuint); - border.ScaleTo(1, transition_duration, Easing.OutQuint); - } - - this.FadeOut(transition_duration, Easing.OutQuint); + this.FadeOut(TRANSITION_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Skinning/Editor/SkinEditorContainer.cs b/osu.Game/Skinning/Editor/SkinEditorContainer.cs new file mode 100644 index 0000000000..f84b70d67a --- /dev/null +++ b/osu.Game/Skinning/Editor/SkinEditorContainer.cs @@ -0,0 +1,87 @@ +// 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.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; + +namespace osu.Game.Skinning.Editor +{ + /// + /// A container which handles loading a skin editor on user request. + /// + public class SkinEditorContainer : CompositeDrawable, IKeyBindingHandler + { + private readonly ScalingContainer target; + private SkinEditor skinEditor; + + private const float visible_target_scale = 0.8f; + + [Resolved] + private OsuColour colours { get; set; } + + public SkinEditorContainer(ScalingContainer target) + { + this.target = target; + RelativeSizeAxes = Axes.Both; + } + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.ToggleSkinEditor: + if (skinEditor == null) + { + LoadComponentAsync(skinEditor = new SkinEditor(target), AddInternal); + skinEditor.State.BindValueChanged(editorVisibilityChanged); + } + else + skinEditor.ToggleVisibility(); + + return true; + } + + return false; + } + + private void editorVisibilityChanged(ValueChangedEvent visibility) + { + if (visibility.NewValue == Visibility.Visible) + { + target.ScaleTo(visible_target_scale, SkinEditor.TRANSITION_DURATION, Easing.OutQuint); + + target.Masking = true; + target.BorderThickness = 5; + target.BorderColour = colours.Yellow; + target.AllowScaling = false; + } + else + { + target.BorderThickness = 0; + target.AllowScaling = true; + + target.ScaleTo(1, SkinEditor.TRANSITION_DURATION, Easing.OutQuint).OnComplete(_ => target.Masking = false); + } + } + + public void OnReleased(GlobalAction action) + { + } + + /// + /// Exit any existing skin editor due to the game state changing. + /// + public void Reset() + { + skinEditor?.Hide(); + skinEditor?.Expire(); + skinEditor = null; + } + } +} From a7982787d446198a2aa95f18eab524fcd3a59d46 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 17:26:55 +0900 Subject: [PATCH 088/267] Add basic header text --- osu.Game/Skinning/Editor/SkinEditor.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs index fdef4d0fce..532c3de7fb 100644 --- a/osu.Game/Skinning/Editor/SkinEditor.cs +++ b/osu.Game/Skinning/Editor/SkinEditor.cs @@ -5,6 +5,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; namespace osu.Game.Skinning.Editor @@ -15,6 +17,8 @@ namespace osu.Game.Skinning.Editor private readonly Drawable target; + private OsuTextFlowContainer headerText; + protected override bool StartHidden => true; public SkinEditor(Drawable target) @@ -25,16 +29,31 @@ namespace osu.Game.Skinning.Editor } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { InternalChild = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + headerText = new OsuTextFlowContainer() + { + TextAnchor = Anchor.TopCentre, + Padding = new MarginPadding(20), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X + }, new SkinBlueprintContainer(target), } }; + + headerText.AddParagraph("Skin editor (preview)", cp => cp.Font = OsuFont.Default.With(size: 24)); + headerText.AddParagraph("This is a preview of what is to come. Changes are lost on changing screens.", cp => + { + cp.Font = OsuFont.Default.With(size: 12); + cp.Colour = colours.Yellow; + }); } protected override void LoadComplete() From fb64f6faf205f8c3c5d46f52fabe016ac0782ea9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 17:40:58 +0900 Subject: [PATCH 089/267] Add ability to exit using game "back" binding --- osu.Game/Skinning/Editor/SkinEditorContainer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Skinning/Editor/SkinEditorContainer.cs b/osu.Game/Skinning/Editor/SkinEditorContainer.cs index f84b70d67a..adb1abefd1 100644 --- a/osu.Game/Skinning/Editor/SkinEditorContainer.cs +++ b/osu.Game/Skinning/Editor/SkinEditorContainer.cs @@ -35,6 +35,15 @@ namespace osu.Game.Skinning.Editor { switch (action) { + case GlobalAction.Back: + if (skinEditor?.State.Value == Visibility.Visible) + { + skinEditor.ToggleVisibility(); + return true; + } + + break; + case GlobalAction.ToggleSkinEditor: if (skinEditor == null) { From 63435ba5482b8c832ea5f1eab612054c5b9b1e6f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 17:41:07 +0900 Subject: [PATCH 090/267] Ensure toolbar doesn't overlap editor content --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 67e0e6a81c..77fb9c3b63 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -619,7 +619,6 @@ namespace osu.Game logoContainer = new Container { RelativeSizeAxes = Axes.Both }, } }, - skinEditor = new SkinEditorContainer(screenContainer), overlayContent = new Container { RelativeSizeAxes = Axes.Both }, rightFloatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, leftFloatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both }, @@ -689,6 +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(new LoginOverlay { From 8d056ff38f6685ada5be49654838be7be4ad49d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Apr 2021 18:23:22 +0900 Subject: [PATCH 091/267] Remove redundant parenthesis --- osu.Game/Skinning/Editor/SkinEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs index 532c3de7fb..562dd23224 100644 --- a/osu.Game/Skinning/Editor/SkinEditor.cs +++ b/osu.Game/Skinning/Editor/SkinEditor.cs @@ -36,7 +36,7 @@ namespace osu.Game.Skinning.Editor RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - headerText = new OsuTextFlowContainer() + headerText = new OsuTextFlowContainer { TextAnchor = Anchor.TopCentre, Padding = new MarginPadding(20), From 820408757a736d3ff3c9dc59cd933bcb1874990a Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 09:43:05 +0700 Subject: [PATCH 092/267] add OsuMarkdownListItem --- .../Markdown/OsuMarkdownListItem.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs new file mode 100644 index 0000000000..7b92a2210d --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -0,0 +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.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownListItem : FillFlowContainer + { + public OsuMarkdownListItem() + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + + Direction = FillDirection.Vertical; + Spacing = new Vector2(10, 10); + } + } +} From a24a27940408a6c6ddf082f9073b5b9db79c0eef Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 09:43:21 +0700 Subject: [PATCH 093/267] use OsuMarkdownListItem for ListItemBlock --- .../Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 56bf72656a..c7e9f267bd 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -21,6 +21,13 @@ namespace osu.Game.Graphics.Containers.Markdown // Don't parse YAML Frontmatter break; + case ListItemBlock listItemBlock: + var childContainer = CreateListItem(listItemBlock); + container.Add(childContainer); + foreach (var single in listItemBlock) + base.AddMarkdownComponent(single, childContainer, level); + break; + default: base.AddMarkdownComponent(markdownObject, container, level); break; @@ -37,6 +44,8 @@ namespace osu.Game.Graphics.Containers.Markdown protected override MarkdownTable CreateTable(Table table) => new OsuMarkdownTable(table); + protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock) => new OsuMarkdownListItem(); + protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) .UseEmojiAndSmiley() From 1e8b3f3a8c81ab996d4875f9ca55e65bce64fcb4 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 09:47:25 +0700 Subject: [PATCH 094/267] handle list padding in OsuMarkdownListItem Reference : https://github.com/ppy/osu-web/blob/5b0e3ac3ffce6b1aff8c9a8794db56603e885ef8/resources/assets/less/bem/osu-md.less#L193-L194 --- .../Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 6 ++++++ .../Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 3 +++ 2 files changed, 9 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index c7e9f267bd..0638767414 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -6,6 +6,7 @@ using Markdig.Extensions.AutoIdentifiers; using Markdig.Extensions.Tables; using Markdig.Extensions.Yaml; using Markdig.Syntax; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; @@ -44,6 +45,11 @@ namespace osu.Game.Graphics.Containers.Markdown protected override MarkdownTable CreateTable(Table table) => new OsuMarkdownTable(table); + protected override MarkdownList CreateList(ListBlock listBlock) => new MarkdownList + { + Padding = new MarginPadding(0) + }; + protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock) => new OsuMarkdownListItem(); protected override MarkdownPipeline CreateBuilder() diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 7b92a2210d..732817a1d5 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -9,6 +9,8 @@ namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownListItem : FillFlowContainer { + private const float default_left_padding = 20; + public OsuMarkdownListItem() { AutoSizeAxes = Axes.Y; @@ -16,6 +18,7 @@ namespace osu.Game.Graphics.Containers.Markdown Direction = FillDirection.Vertical; Spacing = new Vector2(10, 10); + Padding = new MarginPadding { Left = default_left_padding }; } } } From 010c51e6edea430569b1a15455880f9ec086f6af Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:12:43 +0700 Subject: [PATCH 095/267] change OsuMarkdownListItem to composite drawable --- .../Markdown/OsuMarkdownContainer.cs | 2 +- .../Containers/Markdown/OsuMarkdownListItem.cs | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 0638767414..fc4eecf297 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Graphics.Containers.Markdown var childContainer = CreateListItem(listItemBlock); container.Add(childContainer); foreach (var single in listItemBlock) - base.AddMarkdownComponent(single, childContainer, level); + base.AddMarkdownComponent(single, childContainer.Content, level); break; default: diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 732817a1d5..501da7721e 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -7,18 +7,28 @@ using osuTK; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownListItem : FillFlowContainer + public class OsuMarkdownListItem : CompositeDrawable { private const float default_left_padding = 20; + public FillFlowContainer Content { get; } + public OsuMarkdownListItem() { AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; - - Direction = FillDirection.Vertical; - Spacing = new Vector2(10, 10); Padding = new MarginPadding { Left = default_left_padding }; + + InternalChildren = new Drawable[] + { + Content = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10, 10), + } + }; } } } From e3cc4561abcc0b8a7ec9b0c53e36c3339cb8c6a9 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:35:40 +0700 Subject: [PATCH 096/267] add bullet marker in OsuMarkdownListItem --- .../Containers/Markdown/OsuMarkdownListItem.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 501da7721e..6b35321617 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Containers.Markdown; using osuTK; namespace osu.Game.Graphics.Containers.Markdown @@ -11,6 +13,9 @@ namespace osu.Game.Graphics.Containers.Markdown { private const float default_left_padding = 20; + [Resolved] + private IMarkdownTextComponent parentTextComponent { get; set; } + public FillFlowContainer Content { get; } public OsuMarkdownListItem() @@ -30,5 +35,18 @@ namespace osu.Game.Graphics.Containers.Markdown } }; } + + [BackgroundDependencyLoader] + private void load() + { + var marker = parentTextComponent.CreateSpriteText(); + marker.Text = "●"; + marker.Font = OsuFont.GetFont(size: marker.Font.Size / 2); + marker.Origin = Anchor.Centre; + marker.X = -default_left_padding / 2; + marker.Y = marker.Font.Size; + + AddInternal(marker); + } } } From f676526cf49c270698499983098ed0eca80c5a2d Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:39:48 +0700 Subject: [PATCH 097/267] add level in OsuMarkdownListItem --- .../Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 4 ++-- osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index fc4eecf297..1db47d6978 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics.Containers.Markdown break; case ListItemBlock listItemBlock: - var childContainer = CreateListItem(listItemBlock); + var childContainer = CreateListItem(listItemBlock, level); container.Add(childContainer); foreach (var single in listItemBlock) base.AddMarkdownComponent(single, childContainer.Content, level); @@ -50,7 +50,7 @@ namespace osu.Game.Graphics.Containers.Markdown Padding = new MarginPadding(0) }; - protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock) => new OsuMarkdownListItem(); + protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock, int level) => new OsuMarkdownListItem(level); protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 6b35321617..f9800d9262 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -11,6 +11,7 @@ namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownListItem : CompositeDrawable { + private readonly int level; private const float default_left_padding = 20; [Resolved] @@ -18,8 +19,10 @@ namespace osu.Game.Graphics.Containers.Markdown public FillFlowContainer Content { get; } - public OsuMarkdownListItem() + public OsuMarkdownListItem(int level) { + this.level = level; + AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; Padding = new MarginPadding { Left = default_left_padding }; From 781064ba9693c72adda2d84f8a81deba782f9888 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:40:06 +0700 Subject: [PATCH 098/267] create list marker based on its level --- .../Containers/Markdown/OsuMarkdownListItem.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index f9800d9262..7b7cb5837c 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -43,7 +43,7 @@ namespace osu.Game.Graphics.Containers.Markdown private void load() { var marker = parentTextComponent.CreateSpriteText(); - marker.Text = "●"; + marker.Text = createTextMarker(); marker.Font = OsuFont.GetFont(size: marker.Font.Size / 2); marker.Origin = Anchor.Centre; marker.X = -default_left_padding / 2; @@ -51,5 +51,20 @@ namespace osu.Game.Graphics.Containers.Markdown AddInternal(marker); } + + private string createTextMarker() + { + switch (level) + { + case 1: + return "●"; + + case 2: + return "○"; + + default: + return "■"; + } + } } } From 1582b0da881a0d7b308ab6730766a8d9457902ee Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:43:19 +0700 Subject: [PATCH 099/267] add ordered list test --- .../TestSceneOsuMarkdownContainer.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 11c06abee7..3367fccbf1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -128,5 +128,25 @@ Line below"; - Third item level 1"; }); } + + [Test] + public void TestOrderedList() + { + AddStep("Add Ordered List", () => + { + markdownContainer.Text = @"1. First item level 1 +2. Second item level 1 + 1. First item level 2 + 1. First item level 3 + 2. Second item level 3 + 3. Third item level 3 + 1. First item level 4 + 2. Second item level 4 + 3. Third item level 4 + 2. Second item level 2 + 3. Third item level 2 +3. Third item level 1"; + }); + } } } From 2a3479f30d845c1294fe3214da9fd4938da7f3f4 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:47:51 +0700 Subject: [PATCH 100/267] add order in OsuMarkdownListItem for ordered list --- .../Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 2 +- .../Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 1db47d6978..b765378e4c 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -50,7 +50,7 @@ namespace osu.Game.Graphics.Containers.Markdown Padding = new MarginPadding(0) }; - protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock, int level) => new OsuMarkdownListItem(level); + protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock, int level) => new OsuMarkdownListItem(level, listItemBlock.Order); protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 7b7cb5837c..361e503cd4 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -12,6 +12,8 @@ namespace osu.Game.Graphics.Containers.Markdown public class OsuMarkdownListItem : CompositeDrawable { private readonly int level; + private readonly int order; + private readonly bool isOrdered; private const float default_left_padding = 20; [Resolved] @@ -19,9 +21,11 @@ namespace osu.Game.Graphics.Containers.Markdown public FillFlowContainer Content { get; } - public OsuMarkdownListItem(int level) + public OsuMarkdownListItem(int level, int order) { this.level = level; + this.order = order; + isOrdered = order != 0; AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; From c0d9f9f8c687062d444a44edd02916b9a2ef5c2b Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:48:12 +0700 Subject: [PATCH 101/267] use order number as marker for ordered list --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 361e503cd4..b091e9ac07 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -58,6 +58,11 @@ namespace osu.Game.Graphics.Containers.Markdown private string createTextMarker() { + if (isOrdered) + { + return $"{order}."; + } + switch (level) { case 1: From e6579352f9a3dda275d6fc5f7c313bec11837235 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:56:41 +0700 Subject: [PATCH 102/267] add left padding for ordered list In osu-md.less, this rule style[1] removes padding left in ordered list. But in this rule style[2], pseudo element `::before` is used as marker or counter and has minimal width 30px. So we use this as left padding size. [1] https://github.com/ppy/osu-web/blob/5b0e3ac3ffce6b1aff8c9a8794db56603e885ef8/resources/assets/less/bem/osu-md.less#L196-L200 [2] https://github.com/ppy/osu-web/blob/5b0e3ac3ffce6b1aff8c9a8794db56603e885ef8/resources/assets/less/bem/osu-md.less#L210-L219 --- .../Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index b091e9ac07..b448ea154f 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -14,7 +14,9 @@ namespace osu.Game.Graphics.Containers.Markdown private readonly int level; private readonly int order; private readonly bool isOrdered; - private const float default_left_padding = 20; + + private const float ordered_left_padding = 30; + private const float unordered_left_padding = 20; [Resolved] private IMarkdownTextComponent parentTextComponent { get; set; } @@ -29,7 +31,7 @@ namespace osu.Game.Graphics.Containers.Markdown AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; - Padding = new MarginPadding { Left = default_left_padding }; + Padding = new MarginPadding { Left = isOrdered ? ordered_left_padding : unordered_left_padding }; InternalChildren = new Drawable[] { From cf53a05dfdfef6eb3c6b9f73cb12c7b20c01a802 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 10:59:23 +0700 Subject: [PATCH 103/267] change marker size and position for ordered list --- .../Containers/Markdown/OsuMarkdownListItem.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index b448ea154f..f020e3e2fc 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -50,10 +50,18 @@ namespace osu.Game.Graphics.Containers.Markdown { var marker = parentTextComponent.CreateSpriteText(); marker.Text = createTextMarker(); - marker.Font = OsuFont.GetFont(size: marker.Font.Size / 2); - marker.Origin = Anchor.Centre; - marker.X = -default_left_padding / 2; - marker.Y = marker.Font.Size; + + if (isOrdered) + { + marker.X = -ordered_left_padding; + } + else + { + marker.Font = OsuFont.GetFont(size: marker.Font.Size / 2); + marker.Origin = Anchor.Centre; + marker.X = -unordered_left_padding / 2; + marker.Y = marker.Font.Size; + } AddInternal(marker); } From cdef07b2eee4cb587fcda722febe81cd9b10366e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Apr 2021 13:09:57 +0900 Subject: [PATCH 104/267] Fix blueprints not hiding when deleting elements --- osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 17b459a916..0408ce74a6 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -20,7 +20,10 @@ namespace osu.Game.Skinning.Editor protected override void DeleteItems(IEnumerable items) { foreach (var i in items) - i.Hide(); + { + ((Drawable)i).Expire(); + SelectedItems.Remove(i); + } } protected override IEnumerable GetContextMenuItemsForSelection(IEnumerable> selection) From 3681db491caa5e03210c159682f3b3a921569447 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 11:21:20 +0700 Subject: [PATCH 105/267] add long mixed list test Copied from https://github.com/ppy/osu-wiki/blob/master/wiki/Tournaments/OWC/2020/en.md#tournament-rules --- .../TestSceneOsuMarkdownContainer.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 3367fccbf1..852a2e32e2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -148,5 +148,44 @@ Line below"; 3. Third item level 1"; }); } + + [Test] + public void TestLongMixedList() + { + AddStep("Add long mixed list", () => + { + markdownContainer.Text = @"1. The osu! World Cup is a country-based team tournament played on the osu! game mode. + - While this competition is planned as a 4 versus 4 setup, this may change depending on the number of incoming registrations. +2. Beatmap scoring is based on Score V2. +3. The beatmaps for each round will be announced by the map selectors in advance on the Sunday before the actual matches take place. Only these beatmaps will be used during the respective matches. + - One beatmap will be a tiebreaker beatmap. This beatmap will only be played in case of a tie. **The only exception to this is the Qualifiers pool.** +4. The match schedule will be settled by the Tournament Management (see the [scheduling instructions](#scheduling-instructions)). +5. If no staff or referee is available, the match will be postponed. +6. Use of the Visual Settings to alter background dim or disable beatmap elements like storyboards and skins are allowed. +7. If the beatmap ends in a draw, the map will be nullified and replayed. +8. If a player disconnects, their scores will not be counted towards their team's total. + - Disconnects within 30 seconds or 25% of the beatmap length (whichever happens first) after beatmap begin can be aborted and/or rematched. This is up to the referee's discretion. +9. Beatmaps cannot be reused in the same match unless the map was nullified. +10. If less than the minimum required players attend, the maximum time the match can be postponed is 10 minutes. +11. Exchanging players during a match is allowed without limitations. + - **If a map rematch is required, exchanging players is not allowed. With the referee's discretion, an exception can be made if the previous roster is unavailable to play.** +12. Lag is not a valid reason to nullify a beatmap. +13. All players are supposed to keep the match running fluently and without delays. Penalties can be issued to the players if they cause excessive match delays. +14. If a player disconnects between maps and the team cannot provide a replacement, the match can be delayed 10 minutes at maximum. +15. All players and referees must be treated with respect. Instructions of the referees and tournament Management are to be followed. Decisions labeled as final are not to be objected. +16. Disrupting the match by foul play, insulting and provoking other players or referees, delaying the match or other deliberate inappropriate misbehavior is strictly prohibited. +17. The multiplayer chatrooms are subject to the [osu! community rules](/wiki/Rules). + - Breaking the chat rules will result in a silence. Silenced players can not participate in multiplayer matches and must be exchanged for the time being. +18. **The seeding method will be revealed after all the teams have played their Qualifier rounds.** +19. Unexpected incidents are handled by the tournament management. Referees may allow higher tolerance depending on the circumstances. This is up to their discretion. +20. Penalties for violating the tournament rules may include: + - Exclusion of specific players for one beatmap + - Exclusion of specific players for an entire match + - Declaring the match as Lost by Default + - Disqualification from the entire tournament + - Disqualification from the current and future official tournaments until appealed + - Any modification of these rules will be announced."; + }); + } } } From 11d0f12455b1534efbd8edaef2c810e4dd61f2a2 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 11:36:51 +0700 Subject: [PATCH 106/267] change create text marker to virtual --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index f020e3e2fc..dce032d626 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.Containers.Markdown private void load() { var marker = parentTextComponent.CreateSpriteText(); - marker.Text = createTextMarker(); + marker.Text = CreateTextMarker(); if (isOrdered) { @@ -66,7 +66,7 @@ namespace osu.Game.Graphics.Containers.Markdown AddInternal(marker); } - private string createTextMarker() + protected virtual string CreateTextMarker() { if (isOrdered) { From fc4fa4f696c3c8fcf168a819a902454a89232b36 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 30 Apr 2021 11:48:37 +0700 Subject: [PATCH 107/267] use ListBlock IsOrdered to determine ordered or unordered list --- .../Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 2 +- .../Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index b765378e4c..02e674aaec 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -50,7 +50,7 @@ namespace osu.Game.Graphics.Containers.Markdown Padding = new MarginPadding(0) }; - protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock, int level) => new OsuMarkdownListItem(level, listItemBlock.Order); + protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock, int level) => new OsuMarkdownListItem(listItemBlock, level); protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index dce032d626..98b1fd1381 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.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 Markdig.Syntax; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,11 +24,11 @@ namespace osu.Game.Graphics.Containers.Markdown public FillFlowContainer Content { get; } - public OsuMarkdownListItem(int level, int order) + public OsuMarkdownListItem(ListItemBlock listItemBlock, int level) { this.level = level; - this.order = order; - isOrdered = order != 0; + this.order = listItemBlock.Order; + isOrdered = ((ListBlock)listItemBlock.Parent).IsOrdered; AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; From 88aaa9b3320124203abbbef8169b82133956e5dd Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Sun, 2 May 2021 22:35:30 +0700 Subject: [PATCH 108/267] add inline code colour Reference : https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/bem/osu-md.less#L12-L17 --- .../UserInterface/TestSceneOsuMarkdownContainer.cs | 9 +++++++++ .../Containers/Markdown/OsuMarkdownTextFlowContainer.cs | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 852a2e32e2..99bbc22125 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -59,6 +59,15 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + [Test] + public void TestInlineCode() + { + AddStep("Add inline code", () => + { + markdownContainer.Text = "This is `inline code` text"; + }); + } + [Test] public void TestFencedCodeBlock() { diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs index 7a6818b4c2..535e1fb9a0 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs @@ -2,13 +2,22 @@ // See the LICENCE file in the repository root for full licence text. using Markdig.Syntax.Inlines; +using osu.Framework.Allocation; using osu.Framework.Graphics.Containers.Markdown; +using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownTextFlowContainer : MarkdownTextFlowContainer { + [Resolved] + private OverlayColourProvider colourProvider { get; set; } + protected override void AddLinkText(string text, LinkInline linkInline) => AddDrawable(new OsuMarkdownLinkText(text, linkInline)); + + // TODO : Add background (colour B6) and change font to monospace + protected override void AddCodeInLine(CodeInline codeInline) + => AddText(codeInline.Content, t => { t.Colour = colourProvider.Light1; }); } } From 18bfcd7b222d9e13d9b6c07fdd20fed2aa30d8d0 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Sun, 2 May 2021 22:41:11 +0700 Subject: [PATCH 109/267] add hover colour to OsuMarkdownLinkText --- .../Containers/Markdown/OsuMarkdownLinkText.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs index 39b35fd84b..2efb60d125 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs @@ -5,12 +5,16 @@ using Markdig.Syntax.Inlines; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownLinkText : MarkdownLinkText { + [Resolved] + private OverlayColourProvider colourProvider { get; set; } + private SpriteText spriteText; public OsuMarkdownLinkText(string text, LinkInline linkInline) @@ -19,7 +23,7 @@ namespace osu.Game.Graphics.Containers.Markdown } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load() { spriteText.Colour = colourProvider.Light2; } @@ -28,5 +32,17 @@ namespace osu.Game.Graphics.Containers.Markdown { return spriteText = base.CreateSpriteText(); } + + protected override bool OnHover(HoverEvent e) + { + spriteText.Colour = colourProvider.Light1; + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + spriteText.Colour = colourProvider.Light2; + base.OnHoverLost(e); + } } } From b2130fc600d8cff184ba6e51bc3ef7dbeed2f44c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 3 May 2021 01:56:32 +0300 Subject: [PATCH 110/267] 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 111/267] 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 8a2926c0b54e41f72cc1ba9c7110655dac392da6 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 3 May 2021 09:18:45 +0700 Subject: [PATCH 112/267] change default font size to 14 Reference : - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/bem/osu-md.less#L9 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L161 --- .../Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 7 +++++++ .../Containers/Markdown/OsuMarkdownTextFlowContainer.cs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 02e674aaec..c4190d8c4f 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -9,6 +9,8 @@ using Markdig.Syntax; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.Containers.Markdown { @@ -35,6 +37,11 @@ namespace osu.Game.Graphics.Containers.Markdown } } + public override SpriteText CreateSpriteText() => new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14), + }; + public override MarkdownTextFlowContainer CreateTextFlow() => new OsuMarkdownTextFlowContainer(); protected override MarkdownFencedCodeBlock CreateFencedCodeBlock(FencedCodeBlock fencedCodeBlock) => new OsuMarkdownFencedCodeBlock(fencedCodeBlock); diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs index 535e1fb9a0..5165fe74a2 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs @@ -4,6 +4,8 @@ using Markdig.Syntax.Inlines; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown @@ -13,6 +15,11 @@ namespace osu.Game.Graphics.Containers.Markdown [Resolved] private OverlayColourProvider colourProvider { get; set; } + protected override SpriteText CreateSpriteText() => new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14), + }; + protected override void AddLinkText(string text, LinkInline linkInline) => AddDrawable(new OsuMarkdownLinkText(text, linkInline)); From b97d3f2af1f64453a0ee0585d21e322b6dfc96fa Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 3 May 2021 09:35:26 +0700 Subject: [PATCH 113/267] add heading test scene --- .../UserInterface/TestSceneOsuMarkdownContainer.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 99bbc22125..d64c243005 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -41,6 +41,19 @@ namespace osu.Game.Tests.Visual.UserInterface }; }); + [Test] + public void TestHeading() + { + AddStep("Add Heading", () => + { + markdownContainer.Text = @"# Header 1 +## Header 2 +### Header 3 +#### Header 4 +##### Header 5"; + }); + } + [Test] public void TestLink() { From b497785416df7d30523f11c37dd63f59766d370c Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 3 May 2021 09:35:55 +0700 Subject: [PATCH 114/267] add OsuMarkdownHeading --- .../Containers/Markdown/OsuMarkdownContainer.cs | 2 ++ .../Containers/Markdown/OsuMarkdownHeading.cs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index c4190d8c4f..3ad00e4df2 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -44,6 +44,8 @@ namespace osu.Game.Graphics.Containers.Markdown public override MarkdownTextFlowContainer CreateTextFlow() => new OsuMarkdownTextFlowContainer(); + protected override MarkdownHeading CreateHeading(HeadingBlock headingBlock) => new OsuMarkdownHeading(headingBlock); + protected override MarkdownFencedCodeBlock CreateFencedCodeBlock(FencedCodeBlock fencedCodeBlock) => new OsuMarkdownFencedCodeBlock(fencedCodeBlock); protected override MarkdownSeparator CreateSeparator(ThematicBreakBlock thematicBlock) => new OsuMarkdownSeparator(); diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs new file mode 100644 index 0000000000..bff0413e56 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -0,0 +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 Markdig.Syntax; +using osu.Framework.Graphics.Containers.Markdown; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownHeading : MarkdownHeading + { + public OsuMarkdownHeading(HeadingBlock headingBlock) + : base(headingBlock) + { + } + } +} From 3e7df3bf026b205d2922192e16567ebb05bdb02b Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 3 May 2021 09:35:59 +0700 Subject: [PATCH 115/267] change heading font size Heading 1 : 30px - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/base.less#L12-L16 Heading 2 : 26px - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/bem/osu-md.less#L133-L134 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L169 Heading 3 : 20px - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/bem/osu-md.less#L147-L148 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L170 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L154 Heading 4 : 18px - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/bem/osu-md.less#L160-L161 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L171 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L153 Heading 5 : 16px - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/bem/osu-md.less#L174-L175 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L172 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L152 Heading 6 : 14px - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/bem/osu-md.less#L183-L184 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L173 - https://github.com/ppy/osu-web/blob/31579d45aa464a439e943250ca0d5fa7e05a1eb6/resources/assets/less/variables.less#L150 --- .../Containers/Markdown/OsuMarkdownHeading.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs index bff0413e56..e7aa2b2512 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -12,5 +12,31 @@ namespace osu.Game.Graphics.Containers.Markdown : base(headingBlock) { } + + protected override float GetFontSizeByLevel(int level) + { + const float base_font_size = 14; + + switch (level) + { + case 1: + return 30 / base_font_size; + + case 2: + return 26 / base_font_size; + + case 3: + return 20 / base_font_size; + + case 4: + return 18 / base_font_size; + + case 5: + return 16 / base_font_size; + + default: + return 1; + } + } } } From 8c9cfb63013df07e0942e07fdb10918299cc034d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 14:28:35 +0900 Subject: [PATCH 116/267] 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 117/267] 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 118/267] 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 119/267] 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 120/267] 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 121/267] 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 122/267] 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 123/267] 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 124/267] 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 125/267] 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 126/267] 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 127/267] 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 128/267] 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 129/267] 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 625890381f306823600468a8e590241ab88694d6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 16:47:47 +0900 Subject: [PATCH 130/267] Update `ComboCounter` components to use DI to attach data source --- .../Visual/Gameplay/TestSceneComboCounter.cs | 24 +++++++------------ .../Visual/Gameplay/TestSceneHUDOverlay.cs | 12 ++++++---- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 20 ++++++---------- .../Screens/Play/HUD/DefaultComboCounter.cs | 7 +++++- .../Screens/Play/HUD/LegacyComboCounter.cs | 6 +++-- .../Screens/Play/HUD/SkinnableComboCounter.cs | 15 +----------- osu.Game/Screens/Play/HUDOverlay.cs | 12 ++++------ osu.Game/Screens/Play/Player.cs | 2 ++ 8 files changed, 41 insertions(+), 57 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneComboCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneComboCounter.cs index d0c2fb5064..b0a0b5189f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneComboCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneComboCounter.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Gameplay @@ -17,31 +19,21 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); + [Cached] + private ScoreProcessor scoreProcessor = new ScoreProcessor(); + [SetUpSteps] public void SetUpSteps() { - AddStep("Create combo counters", () => SetContents(() => - { - var comboCounter = new SkinnableComboCounter(); - comboCounter.Current.Value = 1; - return comboCounter; - })); + AddStep("Create combo counters", () => SetContents(() => new SkinnableComboCounter())); } [Test] public void TestComboCounterIncrementing() { - AddRepeatStep("increase combo", () => - { - foreach (var counter in comboCounters) - counter.Current.Value++; - }, 10); + AddRepeatStep("increase combo", () => scoreProcessor.Combo.Value++, 10); - AddStep("reset combo", () => - { - foreach (var counter in comboCounters) - counter.Current.Value = 0; - }); + AddStep("reset combo", () => scoreProcessor.Combo.Value = 0); } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 3cefb8623f..55c681b605 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; using osuTK.Input; @@ -19,6 +20,9 @@ namespace osu.Game.Tests.Visual.Gameplay { private HUDOverlay hudOverlay; + [Cached] + private ScoreProcessor scoreProcessor = new ScoreProcessor(); + // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; private FillFlowContainer keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().First(); @@ -31,9 +35,9 @@ namespace osu.Game.Tests.Visual.Gameplay { createNew(); - AddRepeatStep("increase combo", () => { hudOverlay.ComboCounter.Current.Value++; }, 10); + AddRepeatStep("increase combo", () => { scoreProcessor.Combo.Value++; }, 10); - AddStep("reset combo", () => { hudOverlay.ComboCounter.Current.Value = 0; }); + AddStep("reset combo", () => { scoreProcessor.Combo.Value = 0; }); } [Test] @@ -139,12 +143,12 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("create overlay", () => { - hudOverlay = new HUDOverlay(null, null, null, Array.Empty()); + hudOverlay = new HUDOverlay(scoreProcessor, null, null, Array.Empty()); // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); - hudOverlay.ComboCounter.Current.Value = 1; + scoreProcessor.Combo.Value = 1; action?.Invoke(hudOverlay); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index fec1610160..8131c77b4b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -14,6 +14,7 @@ using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; using osuTK.Input; @@ -23,6 +24,9 @@ namespace osu.Game.Tests.Visual.Gameplay { private HUDOverlay hudOverlay; + [Cached] + private ScoreProcessor scoreProcessor = new ScoreProcessor(); + private IEnumerable hudOverlays => CreatedDrawables.OfType(); // best way to check without exposing. @@ -37,17 +41,9 @@ namespace osu.Game.Tests.Visual.Gameplay { createNew(); - AddRepeatStep("increase combo", () => - { - foreach (var hud in hudOverlays) - hud.ComboCounter.Current.Value++; - }, 10); + AddRepeatStep("increase combo", () => scoreProcessor.Combo.Value++, 10); - AddStep("reset combo", () => - { - foreach (var hud in hudOverlays) - hud.ComboCounter.Current.Value = 0; - }); + AddStep("reset combo", () => scoreProcessor.Combo.Value = 0); } [Test] @@ -80,13 +76,11 @@ namespace osu.Game.Tests.Visual.Gameplay { SetContents(() => { - hudOverlay = new HUDOverlay(null, null, null, Array.Empty()); + hudOverlay = new HUDOverlay(scoreProcessor, null, null, Array.Empty()); // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); - hudOverlay.ComboCounter.Current.Value = 1; - action?.Invoke(hudOverlay); return hudOverlay; diff --git a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs index 63e7a88550..d0c26afe5e 100644 --- a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Scoring; using osuTK; namespace osu.Game.Screens.Play.HUD @@ -24,7 +25,11 @@ namespace osu.Game.Screens.Play.HUD } [BackgroundDependencyLoader] - private void load(OsuColour colours) => Colour = colours.BlueLighter; + private void load(OsuColour colours, ScoreProcessor scoreProcessor) + { + Colour = colours.BlueLighter; + Current.BindTo(scoreProcessor.Combo); + } protected override void Update() { diff --git a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs index b4604c0d01..58a30aea94 100644 --- a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using osuTK; @@ -79,7 +80,7 @@ namespace osu.Game.Screens.Play.HUD } [BackgroundDependencyLoader] - private void load() + private void load(ScoreProcessor scoreProcessor) { InternalChildren = new[] { @@ -95,7 +96,8 @@ namespace osu.Game.Screens.Play.HUD }, }; - Current.ValueChanged += combo => updateCount(combo.NewValue == 0); + Current.BindTo(scoreProcessor.Combo); + Current.BindValueChanged(combo => updateCount(combo.NewValue == 0), true); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs index c04c50141a..c62f1460c9 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableComboCounter.cs @@ -1,29 +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 osu.Framework.Bindables; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableComboCounter : SkinnableDrawable, IComboCounter + public class SkinnableComboCounter : SkinnableDrawable { - public Bindable Current { get; } = new Bindable(); - public SkinnableComboCounter() : base(new HUDSkinComponent(HUDSkinComponents.ComboCounter), skinComponent => new DefaultComboCounter()) { CentreComponent = false; } - - private IComboCounter skinnedCounter; - - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - - skinnedCounter = Drawable as IComboCounter; - skinnedCounter?.Current.BindTo(Current); - } } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 669c920017..83897c5167 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -34,7 +34,6 @@ namespace osu.Game.Screens.Play public float TopScoringElementsHeight { get; private set; } public readonly KeyCounterDisplay KeyCounter; - public readonly SkinnableComboCounter ComboCounter; public readonly SkinnableScoreCounter ScoreCounter; public readonly SkinnableAccuracyCounter AccuracyCounter; public readonly SkinnableHealthDisplay HealthDisplay; @@ -106,7 +105,7 @@ namespace osu.Game.Screens.Play HealthDisplay = CreateHealthDisplay(), AccuracyCounter = CreateAccuracyCounter(), ScoreCounter = CreateScoreCounter(), - ComboCounter = CreateComboCounter(), + CreateComboCounter(), HitErrorDisplay = CreateHitErrorDisplayOverlay(), } }, @@ -276,13 +275,13 @@ namespace osu.Game.Screens.Play Progress.BindDrawableRuleset(drawableRuleset); } - protected virtual SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter(); + protected SkinnableAccuracyCounter CreateAccuracyCounter() => new SkinnableAccuracyCounter(); - protected virtual SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter(); + protected SkinnableScoreCounter CreateScoreCounter() => new SkinnableScoreCounter(); - protected virtual SkinnableComboCounter CreateComboCounter() => new SkinnableComboCounter(); + protected SkinnableComboCounter CreateComboCounter() => new SkinnableComboCounter(); - protected virtual SkinnableHealthDisplay CreateHealthDisplay() => new SkinnableHealthDisplay(); + protected SkinnableHealthDisplay CreateHealthDisplay() => new SkinnableHealthDisplay(); protected virtual FailingLayer CreateFailingLayer() => new FailingLayer { @@ -323,7 +322,6 @@ namespace osu.Game.Screens.Play { ScoreCounter?.Current.BindTo(processor.TotalScore); AccuracyCounter?.Current.BindTo(processor.Accuracy); - ComboCounter?.Current.BindTo(processor.Combo); if (HealthDisplay is IHealthDisplay shd) { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 27a4fcc291..c9d7bbf4c1 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -202,6 +202,8 @@ namespace osu.Game.Screens.Play ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); + dependencies.CacheAs(ScoreProcessor); + HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); From 840c22a3b17bd01dea5b79c4a6bdd0e124b04241 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 3 May 2021 12:16:40 +0300 Subject: [PATCH 131/267] Add back mis-removed fade transform --- .../Compose/Components/SelectionBoxDragHandleContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs index 151c169a33..7db2cdbbf5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (activeHandle?.InOperation == true || activeHandle?.IsHovered == true) return; - displayedRotationHandle?.Hide(); + displayedRotationHandle?.FadeOut(SelectionBoxControl.TRANSFORM_DURATION, Easing.OutQuint); displayedRotationHandle = null; activeHandle = allDragHandles.SingleOrDefault(h => h.InOperation); @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (activeHandle != null) { displayedRotationHandle = getCorrespondingRotationHandle(activeHandle, rotationHandles); - displayedRotationHandle?.Show(); + displayedRotationHandle?.FadeIn(SelectionBoxControl.TRANSFORM_DURATION, Easing.OutQuint); } } From b28e1569caad7b6a1781dc32129f57a9d74cc92c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 20:09:48 +0900 Subject: [PATCH 132/267] 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 ca4b860920c2bd7f1efe518e65347904ab8fd7a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 May 2021 20:11:24 +0900 Subject: [PATCH 133/267] Move `BindValueChanged` call to `LoadComplete` --- osu.Game/Screens/Play/HUD/LegacyComboCounter.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs index 58a30aea94..0bccbd0338 100644 --- a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs @@ -97,7 +97,6 @@ namespace osu.Game.Screens.Play.HUD }; Current.BindTo(scoreProcessor.Combo); - Current.BindValueChanged(combo => updateCount(combo.NewValue == 0), true); } protected override void LoadComplete() @@ -111,7 +110,7 @@ namespace osu.Game.Screens.Play.HUD popOutCount.Origin = Origin; popOutCount.Anchor = Anchor; - updateCount(false); + Current.BindValueChanged(combo => updateCount(combo.NewValue == 0), true); } private void updateCount(bool rolling) From 356b1e9a2dd3492039fd7f0bd1e1112856ca2e55 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 4 May 2021 05:43:59 +0700 Subject: [PATCH 134/267] add emphases test --- .../UserInterface/TestSceneOsuMarkdownContainer.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index d64c243005..9fb14efe4d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -41,6 +41,20 @@ namespace osu.Game.Tests.Visual.UserInterface }; }); + [Test] + public void TestEmphases() + { + AddStep("Emphases", () => + { + markdownContainer.Text = @"_italic with underscore_ +*italic with asterisk* +__bold with underscore__ +**bold with asterisk** +*__italic with asterisk, bold with underscore__* +_**italic with underscore, bold with asterisk**_"; + }); + } + [Test] public void TestHeading() { From bfc328c5ab94eda41bfb5b81e84c66ca975373c0 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 4 May 2021 09:09:51 +0700 Subject: [PATCH 135/267] change font weight for bold text --- .../Containers/Markdown/OsuMarkdownTextFlowContainer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs index 5165fe74a2..517143c2db 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs @@ -26,5 +26,12 @@ namespace osu.Game.Graphics.Containers.Markdown // TODO : Add background (colour B6) and change font to monospace protected override void AddCodeInLine(CodeInline codeInline) => AddText(codeInline.Content, t => { t.Colour = colourProvider.Light1; }); + + protected override SpriteText CreateEmphasisedSpriteText(bool bold, bool italic) + { + var spriteText = CreateSpriteText(); + spriteText.Font = spriteText.Font.With(weight: bold ? FontWeight.Bold : FontWeight.Regular, italics: italic); + return spriteText; + } } } From 63381ff4f2a62335e851f266f84f8f422ec68e01 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 4 May 2021 09:34:21 +0700 Subject: [PATCH 136/267] change heading font weight h1 and h2 : Semi Bold (600) - https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/bem/osu-md.less#L111 - https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/bem/osu-md.less#L135 The rest of heading : Bold (700) - https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/bem/osu-md.less#L97 --- .../Containers/Markdown/OsuMarkdownHeading.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs index e7aa2b2512..f71c6753f4 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -3,16 +3,25 @@ using Markdig.Syntax; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownHeading : MarkdownHeading { + private readonly int level; + public OsuMarkdownHeading(HeadingBlock headingBlock) : base(headingBlock) { + level = headingBlock.Level; } + public override MarkdownTextFlowContainer CreateTextFlow() => new HeadingTextFlowContainer + { + Weight = GetFontWeightByLevel(level), + }; + protected override float GetFontSizeByLevel(int level) { const float base_font_size = 14; @@ -38,5 +47,30 @@ namespace osu.Game.Graphics.Containers.Markdown return 1; } } + + protected virtual FontWeight GetFontWeightByLevel(int level) + { + switch (level) + { + case 1: + case 2: + return FontWeight.SemiBold; + + default: + return FontWeight.Bold; + } + } + + private class HeadingTextFlowContainer : OsuMarkdownTextFlowContainer + { + public FontWeight Weight { get; set; } + + protected override SpriteText CreateSpriteText() + { + var spriteText = base.CreateSpriteText(); + spriteText.Font = spriteText.Font.With(weight: Weight); + return spriteText; + } + } } } From fd7a6b3a7c953c682154395abc517607dfff66bf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 3 May 2021 12:19:34 +0300 Subject: [PATCH 137/267] Finish transforms on controls load complete --- osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 38ed23fa13..9cba07e267 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -54,7 +54,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void LoadComplete() { base.LoadComplete(); + UpdateHoverState(); + FinishTransforms(true); } protected override bool OnHover(HoverEvent e) From 5f33c3514ec43a3df22ade1dc86e2a8b384c0c83 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 4 May 2021 06:37:18 +0300 Subject: [PATCH 138/267] Move selection box control internal events to drag handles --- .../Compose/Components/SelectionBoxControl.cs | 7 ------- .../Components/SelectionBoxDragHandle.cs | 20 +++++++++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 9cba07e267..4406cc055d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -22,9 +22,6 @@ namespace osu.Game.Screens.Edit.Compose.Components public event Action OperationStarted; public event Action OperationEnded; - internal event Action HoverGained; - internal event Action HoverLost; - private Circle circle; /// @@ -62,14 +59,11 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnHover(HoverEvent e) { UpdateHoverState(); - HoverGained?.Invoke(); return true; } protected override void OnHoverLost(HoverLostEvent e) { - base.OnHoverLost(e); - HoverLost?.Invoke(); UpdateHoverState(); } @@ -89,7 +83,6 @@ namespace osu.Game.Screens.Edit.Compose.Components { HandlingMouse = false; UpdateHoverState(); - base.OnMouseUp(e); } protected virtual void UpdateHoverState() diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs index d7e58df748..ed7c451b7e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs @@ -29,5 +29,25 @@ namespace osu.Game.Screens.Edit.Compose.Components UpdateHoverState(); base.OnDragEnd(e); } + + #region Internal events for SelectionBoxDragHandleContainer + + internal event Action HoverGained; + internal event Action HoverLost; + + protected override bool OnHover(HoverEvent e) + { + bool result = base.OnHover(e); + HoverGained?.Invoke(); + return result; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + HoverLost?.Invoke(); + } + + #endregion } } From b2a0c2b5631ac3a3e5d746909d141fafbf655ce3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 4 May 2021 06:40:43 +0300 Subject: [PATCH 139/267] Consider drag handles active using mouse down instead of when dragged --- .../Compose/Components/SelectionBoxButton.cs | 2 +- .../Compose/Components/SelectionBoxControl.cs | 29 +++++-------------- .../Components/SelectionBoxDragHandle.cs | 15 ++++++++++ .../SelectionBoxDragHandleContainer.cs | 8 ++--- .../Components/SelectionBoxRotationHandle.cs | 2 +- 5 files changed, 29 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs index fbbebe3288..43cbbb617b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void UpdateHoverState() { base.UpdateHoverState(); - icon.FadeColour(!HandlingMouse && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint); + icon.FadeColour(!IsHeld && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint); } public string TooltipText { get; } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 4406cc055d..159886648e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -25,9 +25,9 @@ namespace osu.Game.Screens.Edit.Compose.Components private Circle circle; /// - /// Whether this control is currently being operated on by the user. + /// Whether the user is currently holding the control with mouse. /// - public bool InOperation { get; private set; } + public bool IsHeld { get; private set; } [Resolved] protected OsuColour Colours { get; private set; } @@ -67,44 +67,31 @@ namespace osu.Game.Screens.Edit.Compose.Components UpdateHoverState(); } - /// - /// Whether this control is currently handling mouse down input. - /// - protected bool HandlingMouse { get; private set; } - protected override bool OnMouseDown(MouseDownEvent e) { - HandlingMouse = true; + IsHeld = true; UpdateHoverState(); return true; } protected override void OnMouseUp(MouseUpEvent e) { - HandlingMouse = false; + IsHeld = false; UpdateHoverState(); } protected virtual void UpdateHoverState() { - if (HandlingMouse) + if (IsHeld) circle.FadeColour(Colours.GrayF, TRANSFORM_DURATION, Easing.OutQuint); else circle.FadeColour(IsHovered ? Colours.Red : Colours.YellowDark, TRANSFORM_DURATION, Easing.OutQuint); - this.ScaleTo(HandlingMouse || IsHovered ? 1.5f : 1, TRANSFORM_DURATION, Easing.OutQuint); + this.ScaleTo(IsHeld || IsHovered ? 1.5f : 1, TRANSFORM_DURATION, Easing.OutQuint); } - protected void OnOperationStarted() - { - InOperation = true; - OperationStarted?.Invoke(); - } + protected void OnOperationStarted() => OperationStarted?.Invoke(); - protected void OnOperationEnded() - { - InOperation = false; - OperationEnded?.Invoke(); - } + protected void OnOperationEnded() => OperationEnded?.Invoke(); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs index ed7c451b7e..3c1741e24d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs @@ -34,6 +34,8 @@ namespace osu.Game.Screens.Edit.Compose.Components internal event Action HoverGained; internal event Action HoverLost; + internal event Action MouseDown; + internal event Action MouseUp; protected override bool OnHover(HoverEvent e) { @@ -48,6 +50,19 @@ namespace osu.Game.Screens.Edit.Compose.Components HoverLost?.Invoke(); } + protected override bool OnMouseDown(MouseDownEvent e) + { + bool result = base.OnMouseDown(e); + MouseDown?.Invoke(); + return result; + } + + protected override void OnMouseUp(MouseUpEvent e) + { + base.OnMouseUp(e); + MouseUp?.Invoke(); + } + #endregion } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs index 7db2cdbbf5..c78514b7db 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs @@ -62,8 +62,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { handle.HoverGained += updateRotationHandlesVisibility; handle.HoverLost += updateRotationHandlesVisibility; - handle.OperationStarted += updateRotationHandlesVisibility; - handle.OperationEnded += updateRotationHandlesVisibility; + handle.MouseDown += updateRotationHandlesVisibility; + handle.MouseUp += updateRotationHandlesVisibility; allDragHandles.Add(handle); } @@ -72,13 +72,13 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updateRotationHandlesVisibility() { - if (activeHandle?.InOperation == true || activeHandle?.IsHovered == true) + if (activeHandle?.IsHeld == true || activeHandle?.IsHovered == true) return; displayedRotationHandle?.FadeOut(SelectionBoxControl.TRANSFORM_DURATION, Easing.OutQuint); displayedRotationHandle = null; - activeHandle = allDragHandles.SingleOrDefault(h => h.InOperation); + activeHandle = allDragHandles.SingleOrDefault(h => h.IsHeld); activeHandle ??= allDragHandles.SingleOrDefault(h => h.IsHovered); if (activeHandle != null) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 6303caf9ed..65a54292ab 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void UpdateHoverState() { base.UpdateHoverState(); - icon.FadeColour(!HandlingMouse && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint); + icon.FadeColour(!IsHeld && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint); } } } From 8abff4881b731819535c9f603dc820c193abb010 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 4 May 2021 07:31:52 +0300 Subject: [PATCH 140/267] Hide the corresponding rotation handle when holding scale handle --- .../Editing/TestSceneComposeSelectBox.cs | 29 +++++++++++++++---- .../SelectionBoxDragHandleContainer.cs | 10 +++++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs index 914b8b6f27..efcd7864d7 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Framework.Threading; using osu.Game.Screens.Edit.Compose.Components; using osuTK; using osuTK.Input; @@ -40,6 +41,7 @@ namespace osu.Game.Tests.Visual.Editing }; InputManager.MoveMouseTo(selectionBox); + InputManager.ReleaseButton(MouseButton.Left); }); private bool handleScale(Vector2 amount, Anchor reference) @@ -127,26 +129,41 @@ namespace osu.Game.Tests.Visual.Editing } [Test] - public void TestDraggingScaleHandleKeepsCorrespondingRotationHandleShown() + public void TestHoldingScaleHandleHidesCorrespondingRotationHandle() { SelectionBoxRotationHandle rotationHandle = null; AddStep("retrieve rotation handle", () => rotationHandle = this.ChildrenOfType().First()); AddAssert("rotation handle hidden", () => rotationHandle.Alpha == 0); - AddStep("hover over and hold closest scale handle", () => + AddStep("hover over closest scale handle", () => { InputManager.MoveMouseTo(this.ChildrenOfType().Single(s => s.Anchor == rotationHandle.Anchor)); - InputManager.PressButton(MouseButton.Left); }); AddUntilStep("rotation handle shown", () => rotationHandle.Alpha == 1); + AddStep("hold scale handle", () => InputManager.PressButton(MouseButton.Left)); + AddUntilStep("rotation handle hidden", () => rotationHandle.Alpha == 0); - AddStep("drag to centre", () => InputManager.MoveMouseTo(selectionBox)); - AddAssert("rotation handle still shown", () => rotationHandle.Alpha > 0); + int i; + ScheduledDelegate mouseMove = null; + AddStep("start dragging", () => + { + i = 0; + + mouseMove = Scheduler.AddDelayed(() => + { + InputManager.MoveMouseTo(selectionBox.ScreenSpaceDrawQuad.TopLeft + Vector2.One * (5 * ++i)); + }, 100, true); + }); + AddAssert("rotation handle still hidden", () => rotationHandle.Alpha == 0); + + AddStep("end dragging", () => mouseMove.Cancel()); + AddAssert("rotation handle still hidden", () => rotationHandle.Alpha == 0); AddStep("unhold left", () => InputManager.ReleaseButton(MouseButton.Left)); + AddUntilStep("rotation handle shown", () => rotationHandle.Alpha == 1); AddStep("move mouse away", () => InputManager.MoveMouseTo(selectionBox, new Vector2(20))); - AddUntilStep("handle hidden", () => rotationHandle.Alpha == 0); + AddUntilStep("rotation handle hidden", () => rotationHandle.Alpha == 0); } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs index c78514b7db..456f72878d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs @@ -72,13 +72,19 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updateRotationHandlesVisibility() { - if (activeHandle?.IsHeld == true || activeHandle?.IsHovered == true) + // if the active handle is a rotation handle and is held or hovered, + // then no need to perform any updates to the rotation handles visibility. + if (activeHandle is SelectionBoxRotationHandle && (activeHandle?.IsHeld == true || activeHandle?.IsHovered == true)) return; displayedRotationHandle?.FadeOut(SelectionBoxControl.TRANSFORM_DURATION, Easing.OutQuint); displayedRotationHandle = null; - activeHandle = allDragHandles.SingleOrDefault(h => h.IsHeld); + // if the active handle is not a rotation handle but is held, then keep the rotation handle hidden. + if (activeHandle?.IsHeld == true) + return; + + activeHandle = rotationHandles.SingleOrDefault(h => h.IsHeld || h.IsHovered); activeHandle ??= allDragHandles.SingleOrDefault(h => h.IsHovered); if (activeHandle != null) From e00af3e71d2f2f754e641698dede05e3ac089b5b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 4 May 2021 09:45:58 +0300 Subject: [PATCH 141/267] 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 142/267] 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 143/267] 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 144/267] 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 145/267] 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 146/267] 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 147/267] 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 148/267] 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 149/267] 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 150/267] 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 151/267] 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 152/267] 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 153/267] 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 154/267] 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 155/267] 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 12c1ded7a8f3c6c6e76cee5125d15a57530e70f7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 5 May 2021 00:28:49 +0300 Subject: [PATCH 156/267] Fix test scene broken on master --- osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs index efcd7864d7..e383aa8008 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs @@ -30,6 +30,8 @@ namespace osu.Game.Tests.Visual.Editing { selectionBox = new SelectionBox { + RelativeSizeAxes = Axes.Both, + CanRotate = true, CanScaleX = true, CanScaleY = true, From 1472960319ecdd6f4627bdfd7aff9896b6bdcfe1 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Tue, 4 May 2021 21:35:36 -0400 Subject: [PATCH 157/267] 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 158/267] 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 159/267] 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 160/267] 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 161/267] 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 162/267] 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 163/267] 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 164/267] 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 165/267] 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 166/267] 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 167/267] 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 168/267] 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 169/267] 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 170/267] 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 171/267] 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 172/267] 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 173/267] 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 174/267] 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 175/267] 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() { From 2a67361dc01963e10e850ac5523858578c613f67 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 5 May 2021 21:50:11 +0300 Subject: [PATCH 176/267] OnOperation -> TriggerOperation --- .../Screens/Edit/Compose/Components/SelectionBoxButton.cs | 4 ++-- .../Screens/Edit/Compose/Components/SelectionBoxControl.cs | 4 ++-- .../Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs index 43cbbb617b..3b1dae6c3d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs @@ -46,9 +46,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnClick(ClickEvent e) { - OnOperationStarted(); + TriggerOperationStarted(); Action?.Invoke(); - OnOperationEnded(); + TriggerOperatoinEnded(); return true; } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 159886648e..40d367bb80 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -90,8 +90,8 @@ namespace osu.Game.Screens.Edit.Compose.Components this.ScaleTo(IsHeld || IsHovered ? 1.5f : 1, TRANSFORM_DURATION, Easing.OutQuint); } - protected void OnOperationStarted() => OperationStarted?.Invoke(); + protected void TriggerOperationStarted() => OperationStarted?.Invoke(); - protected void OnOperationEnded() => OperationEnded?.Invoke(); + protected void TriggerOperatoinEnded() => OperationEnded?.Invoke(); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs index 3c1741e24d..65a95951cf 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs @@ -12,7 +12,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDragStart(DragStartEvent e) { - OnOperationStarted(); + TriggerOperationStarted(); return true; } @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void OnDragEnd(DragEndEvent e) { - OnOperationEnded(); + TriggerOperatoinEnded(); UpdateHoverState(); base.OnDragEnd(e); From 266d8d828297b9381520023a47bbe670ffce548e Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 05:13:39 +0700 Subject: [PATCH 177/267] move list item constant position --- .../Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 98b1fd1381..84565a577a 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -12,13 +12,13 @@ namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownListItem : CompositeDrawable { + private const float ordered_left_padding = 30; + private const float unordered_left_padding = 20; + private readonly int level; private readonly int order; private readonly bool isOrdered; - private const float ordered_left_padding = 30; - private const float unordered_left_padding = 20; - [Resolved] private IMarkdownTextComponent parentTextComponent { get; set; } From 3ddf551b0360322fb15d9802949ed35997624b94 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 05:13:54 +0700 Subject: [PATCH 178/267] remove unused this --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 84565a577a..a6274de3da 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Containers.Markdown public OsuMarkdownListItem(ListItemBlock listItemBlock, int level) { this.level = level; - this.order = listItemBlock.Order; + order = listItemBlock.Order; isOrdered = ((ListBlock)listItemBlock.Parent).IsOrdered; AutoSizeAxes = Axes.Y; From 99e0cc9bbe4106362a854caae272c929a4ac6e88 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 05:15:32 +0700 Subject: [PATCH 179/267] rename CreateTextMarker to GetTextMarker --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index a6274de3da..a4941ef785 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -50,7 +50,7 @@ namespace osu.Game.Graphics.Containers.Markdown private void load() { var marker = parentTextComponent.CreateSpriteText(); - marker.Text = CreateTextMarker(); + marker.Text = GetTextMarker(); if (isOrdered) { @@ -67,7 +67,7 @@ namespace osu.Game.Graphics.Containers.Markdown AddInternal(marker); } - protected virtual string CreateTextMarker() + protected virtual string GetTextMarker() { if (isOrdered) { From 9bb80492c534bc162cb28085bb6631c07e9fc6bf Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 05:29:29 +0700 Subject: [PATCH 180/267] add level and isOrdered parameter --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index a4941ef785..a7582cb4b3 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -50,7 +50,7 @@ namespace osu.Game.Graphics.Containers.Markdown private void load() { var marker = parentTextComponent.CreateSpriteText(); - marker.Text = GetTextMarker(); + marker.Text = GetTextMarker(level, isOrdered); if (isOrdered) { @@ -67,7 +67,7 @@ namespace osu.Game.Graphics.Containers.Markdown AddInternal(marker); } - protected virtual string GetTextMarker() + protected virtual string GetTextMarker(int level, bool isOrdered) { if (isOrdered) { From 4567abe3dbd39c1f26ce42003edd7b021a7c385d Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 05:32:07 +0700 Subject: [PATCH 181/267] add xmldoc for GetTextMarker --- .../Graphics/Containers/Markdown/OsuMarkdownListItem.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index a7582cb4b3..b586bb7f30 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -67,6 +67,12 @@ namespace osu.Game.Graphics.Containers.Markdown AddInternal(marker); } + /// + /// Get text marker based on and . + /// + /// The markdown level of current list item. + /// Is true if the list item is an ordered list. + /// protected virtual string GetTextMarker(int level, bool isOrdered) { if (isOrdered) From cfd28c51bbbb827c0394282ec144ebdf3a9557f6 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 05:35:16 +0700 Subject: [PATCH 182/267] change block quote backgroudn width Reference : https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/base.less#L7-L10 --- .../Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs index 869cba82f2..d9b516892b 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs @@ -26,7 +26,9 @@ namespace osu.Game.Graphics.Containers.Markdown protected override Drawable CreateBackground() { - return background = base.CreateBackground(); + background = base.CreateBackground(); + background.Width = 2; + return background; } public override MarkdownTextFlowContainer CreateTextFlow() From 550e6c0fbb5e670d77dcc384c5dfbe3aba07f99b Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 05:36:46 +0700 Subject: [PATCH 183/267] change quote block margin padding to use vertical and horizontal --- .../Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs index d9b516892b..07bb72c2e6 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs @@ -36,10 +36,8 @@ namespace osu.Game.Graphics.Containers.Markdown var textFlow = base.CreateTextFlow(); textFlow.Margin = new MarginPadding { - Top = 10, - Bottom = 10, - Left = 20, - Right = 20, + Vertical = 10, + Horizontal = 20, }; return textFlow; } From 0d3ca8dde197428a2eef2ec2bc4d49d614ccea28 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 08:43:38 +0700 Subject: [PATCH 184/267] change font weight of table header --- .../Markdown/OsuMarkdownTableCell.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs index d8b9145228..fca85e02a8 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown @@ -30,7 +31,6 @@ namespace osu.Game.Graphics.Containers.Markdown RelativeSizeAxes = Axes.X, }; - // TODO : Change font weight to 700 for heading if (isHeading) { border.Colour = colourProvider.Background3; @@ -48,5 +48,23 @@ namespace osu.Game.Graphics.Containers.Markdown AddInternal(border); } + + public override MarkdownTextFlowContainer CreateTextFlow() => new TableCellTextFlowContainer + { + Weight = isHeading ? FontWeight.Bold : FontWeight.Regular, + Padding = new MarginPadding(10), + }; + + private class TableCellTextFlowContainer : OsuMarkdownTextFlowContainer + { + public FontWeight Weight { get; set; } + + protected override SpriteText CreateSpriteText() + { + var spriteText = base.CreateSpriteText(); + spriteText.Font = spriteText.Font.With(weight: Weight); + return spriteText; + } + } } } From d4658c609b61d3f15cccbe840023bb6003efc91c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 5 May 2021 22:43:16 -0700 Subject: [PATCH 185/267] Fix warning text of bg source setting not being updated when user with supporter signs in/out --- .../Settings/Sections/UserInterface/MainMenuSettings.cs | 4 ++-- 1 file 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 7c4c88f344..5f703ed5a4 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -57,11 +57,11 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { base.LoadComplete(); - backgroundSourceDropdown.Current.BindValueChanged(source => + user.BindValueChanged(u => { const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag."; - backgroundSourceDropdown.WarningText = user.Value?.IsSupporter != true ? not_supporter_note : string.Empty; + backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? not_supporter_note : string.Empty; }, true); } } From ee23124bb14409ac6c4833df20b1259ecca888d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 May 2021 15:17:53 +0900 Subject: [PATCH 186/267] Remove no-longer-used interface --- .../Screens/Play/HUD/DefaultComboCounter.cs | 2 +- osu.Game/Screens/Play/HUD/IComboCounter.cs | 19 ------------------- .../Screens/Play/HUD/LegacyComboCounter.cs | 2 +- 3 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 osu.Game/Screens/Play/HUD/IComboCounter.cs diff --git a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs index d0c26afe5e..5a975c1b80 100644 --- a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public class DefaultComboCounter : RollingCounter, IComboCounter + public class DefaultComboCounter : RollingCounter { private readonly Vector2 offset = new Vector2(20, 5); diff --git a/osu.Game/Screens/Play/HUD/IComboCounter.cs b/osu.Game/Screens/Play/HUD/IComboCounter.cs deleted file mode 100644 index ff235bf04e..0000000000 --- a/osu.Game/Screens/Play/HUD/IComboCounter.cs +++ /dev/null @@ -1,19 +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 osu.Framework.Bindables; -using osu.Framework.Graphics; - -namespace osu.Game.Screens.Play.HUD -{ - /// - /// An interface providing a set of methods to update a combo counter. - /// - public interface IComboCounter : IDrawable - { - /// - /// The current combo to be displayed. - /// - Bindable Current { get; } - } -} diff --git a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs index 0bccbd0338..8ecd960de1 100644 --- a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Play.HUD /// /// Uses the 'x' symbol and has a pop-out effect while rolling over. /// - public class LegacyComboCounter : CompositeDrawable, IComboCounter + public class LegacyComboCounter : CompositeDrawable { public Bindable Current { get; } = new BindableInt { MinValue = 0, }; From af75c9ac82ab73f43188284eef35a67b7bf1dbfd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 May 2021 16:08:28 +0900 Subject: [PATCH 187/267] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 5aee9e15cc..99cda7693d 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1e0eabfff7..e448972066 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -29,7 +29,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index e26e727e69..43ed2d7dc8 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From b6560a616a22f07e248f2063cd0d78f1fbbac180 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 15:00:12 +0700 Subject: [PATCH 188/267] add comment for base font size heading --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs index f71c6753f4..a7fecc6e25 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -24,6 +24,9 @@ namespace osu.Game.Graphics.Containers.Markdown protected override float GetFontSizeByLevel(int level) { + // Reference for this font size + // https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/bem/osu-md.less#L9 + // https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/variables.less#L161 const float base_font_size = 14; switch (level) From e7c563fb671f8c2eee44de363e6c04971dad6cd3 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 15:11:45 +0700 Subject: [PATCH 189/267] simplify `CreateTextFlow` in quote block --- .../Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs index 07bb72c2e6..f8b8a1c2a2 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs @@ -33,13 +33,11 @@ namespace osu.Game.Graphics.Containers.Markdown public override MarkdownTextFlowContainer CreateTextFlow() { - var textFlow = base.CreateTextFlow(); - textFlow.Margin = new MarginPadding + return base.CreateTextFlow().With(f => f.Margin = new MarginPadding { Vertical = 10, Horizontal = 20, - }; - return textFlow; + }); } } } From 91283d41ceef2c9564d024b20d3ea893e38198e6 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 15:13:43 +0700 Subject: [PATCH 190/267] add paragraph test --- .../UserInterface/TestSceneOsuMarkdownContainer.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 9fb14efe4d..dc41f184f2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -95,6 +95,19 @@ _**italic with underscore, bold with asterisk**_"; }); } + [Test] + public void TestParagraph() + { + AddStep("Add paragraph", () => + { + markdownContainer.Text = @"first paragraph + +second paragraph + +third paragraph"; + }); + } + [Test] public void TestFencedCodeBlock() { From ba634cbf11174ad90003405b0ff4a3c49cad7016 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 15:13:59 +0700 Subject: [PATCH 191/267] change line spacing to 21 We use margin bottom in osu-web markdown paragraph[1] as reference for this line spacing value. The value from osu-web itself is 1.5em[2]. Because the base font size of the paragraph is 14px[3][4], the actual value is 14 * 1.5 = 21px [1] https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/bem/osu-md.less#L230 [2] https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/variables.less#L58 [3] https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/bem/osu-md.less#L9 [4] https://github.com/ppy/osu-web/blob/376cac43a051b9c85ce95e2c446099be187b3e45/resources/assets/less/variables.less#L161 --- .../Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 3ad00e4df2..c66f3fbca2 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -16,6 +16,11 @@ namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownContainer : MarkdownContainer { + public OsuMarkdownContainer() + { + LineSpacing = 21; + } + protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level) { switch (markdownObject) From 39067e6926e0950303e137140dded1f2eb2f5dd7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 May 2021 17:19:18 +0900 Subject: [PATCH 192/267] Fix slider input handling potentially being offset after composer area resize Closes https://github.com/ppy/osu/issues/12671. --- .../Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index 1c3d270c95..6e22c35ab3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -26,6 +26,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { AccentColour = Color4.Transparent }; + + // SliderSelectionBlueprint relies on calling ReceivePositionalInputAt on this drawable to determine whether selection should occur. + // Without AlwaysPresent, a movement in a parent container (ie. the editor composer area resizing) could cause incorrect input handling. + AlwaysPresent = true; } [BackgroundDependencyLoader] From 010f6258705e86c47ad208c519362daa80e6c346 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 17:05:41 +0700 Subject: [PATCH 193/267] use derived component in OsuMarkdownFencedCodeBlock --- .../Markdown/OsuMarkdownFencedCodeBlock.cs | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs index ddd88dd915..0d67849060 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs @@ -12,33 +12,34 @@ namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownFencedCodeBlock : MarkdownFencedCodeBlock { - private Box background; - private MarkdownTextFlowContainer textFlow; - + // TODO : change to monospace font for this component public OsuMarkdownFencedCodeBlock(FencedCodeBlock fencedCodeBlock) : base(fencedCodeBlock) { } - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - // TODO : Change to monospace font to match with osu-web - background.Colour = colourProvider.Background6; - textFlow.Colour = colourProvider.Light1; - } + protected override Drawable CreateBackground() => new CodeBlockBackground(); - protected override Drawable CreateBackground() + public override MarkdownTextFlowContainer CreateTextFlow() => new CodeBlockTextFlowContainer(); + + private class CodeBlockBackground : Box { - return background = new Box + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) { - RelativeSizeAxes = Axes.Both, - }; + RelativeSizeAxes = Axes.Both; + Colour = colourProvider.Background6; + } } - public override MarkdownTextFlowContainer CreateTextFlow() + private class CodeBlockTextFlowContainer : OsuMarkdownTextFlowContainer { - return textFlow = base.CreateTextFlow(); + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Colour = colourProvider.Light1; + Margin = new MarginPadding(10); + } } } } From 7b43730fe61791017693d058a101487057d218a3 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 17:13:46 +0700 Subject: [PATCH 194/267] add QuoteBackground in OsuMarkdownQuoteBlock --- .../Markdown/OsuMarkdownQuoteBlock.cs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs index f8b8a1c2a2..9935c81537 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs @@ -5,31 +5,19 @@ using Markdig.Syntax; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Shapes; using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownQuoteBlock : MarkdownQuoteBlock { - private Drawable background; - public OsuMarkdownQuoteBlock(QuoteBlock quoteBlock) : base(quoteBlock) { } - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - background.Colour = colourProvider.Content2; - } - - protected override Drawable CreateBackground() - { - background = base.CreateBackground(); - background.Width = 2; - return background; - } + protected override Drawable CreateBackground() => new QuoteBackground(); public override MarkdownTextFlowContainer CreateTextFlow() { @@ -39,5 +27,18 @@ namespace osu.Game.Graphics.Containers.Markdown Horizontal = 20, }); } + + private class QuoteBackground : Box + { + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + RelativeSizeAxes = Axes.Y; + Width = 2; + Colour = colourProvider.Content2; + } + } } } From 92022f2cba0240a6fe25bc5607eeb2ff9e5e9225 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 6 May 2021 17:17:14 +0700 Subject: [PATCH 195/267] add Separator component in OsuMarkdownSeparator --- .../Markdown/OsuMarkdownSeparator.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs index 9b28200452..28a87c9f21 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs @@ -4,23 +4,24 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Shapes; using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { public class OsuMarkdownSeparator : MarkdownSeparator { - private Drawable separator; + protected override Drawable CreateSeparator() => new Separator(); - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private class Separator : Box { - separator.Colour = colourProvider.Background3; - } - - protected override Drawable CreateSeparator() - { - return separator = base.CreateSeparator(); + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + RelativeSizeAxes = Axes.X; + Height = 1; + Colour = colourProvider.Background3; + } } } } From 9be36230f9bd5825aafc5b5f664480d76bdf43fb Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 6 May 2021 21:43:30 +0900 Subject: [PATCH 196/267] Introduce AutoGenerator subclass for frame based replay generation --- osu.Game/Rulesets/Replays/AutoGenerator.cs | 27 +++++------- .../Rulesets/Replays/FramedAutoGenerator.cs | 44 +++++++++++++++++++ 2 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 osu.Game/Rulesets/Replays/FramedAutoGenerator.cs diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index b3c609f2f4..4bdd5b094d 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// 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; @@ -7,34 +7,27 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Replays { - public abstract class AutoGenerator : IAutoGenerator + public abstract class AutoGenerator { /// - /// Creates the auto replay and returns it. - /// Every subclass of OsuAutoGeneratorBase should implement this! + /// The default duration of a key press in milliseconds. /// - public abstract Replay Generate(); - - #region Parameters + public const double KEY_UP_DELAY = 50; /// - /// The beatmap we're making. + /// The beatmap the autoplay is generated for. /// - protected IBeatmap Beatmap; - - #endregion + protected IBeatmap Beatmap { get; } protected AutoGenerator(IBeatmap beatmap) { Beatmap = beatmap; } - #region Constants - - // Shared amongst all modes - public const double KEY_UP_DELAY = 50; - - #endregion + /// + /// Generate the replay of the autoplay. + /// + public abstract Replay Generate(); protected virtual HitObject GetNextObject(int currentIndex) { diff --git a/osu.Game/Rulesets/Replays/FramedAutoGenerator.cs b/osu.Game/Rulesets/Replays/FramedAutoGenerator.cs new file mode 100644 index 0000000000..091eb00232 --- /dev/null +++ b/osu.Game/Rulesets/Replays/FramedAutoGenerator.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Replays; + +namespace osu.Game.Rulesets.Replays +{ + public abstract class FramedAutoGenerator : AutoGenerator + where TFrame : ReplayFrame + { + /// + /// The replay frames of the autoplay. + /// + protected readonly List Frames = new List(); + + protected TFrame? LastFrame => Frames.Count == 0 ? null : Frames[^1]; + + protected FramedAutoGenerator(IBeatmap beatmap) + : base(beatmap) + { + } + + public sealed override Replay Generate() + { + Frames.Clear(); + GenerateFrames(); + + return new Replay + { + Frames = Frames.OrderBy(frame => frame.Time).Cast().ToList() + }; + } + + /// + /// Generate the replay frames of the autoplay and populate . + /// + protected abstract void GenerateFrames(); + } +} From ea35b72436d6c38a477d3ae3e8dfb11b15653248 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 6 May 2021 22:56:21 +0900 Subject: [PATCH 197/267] Remove unused IAutoGenerator interface --- osu.Game/Rulesets/Replays/IAutoGenerator.cs | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 osu.Game/Rulesets/Replays/IAutoGenerator.cs diff --git a/osu.Game/Rulesets/Replays/IAutoGenerator.cs b/osu.Game/Rulesets/Replays/IAutoGenerator.cs deleted file mode 100644 index b1905e2b6f..0000000000 --- a/osu.Game/Rulesets/Replays/IAutoGenerator.cs +++ /dev/null @@ -1,12 +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 osu.Game.Replays; - -namespace osu.Game.Rulesets.Replays -{ - public interface IAutoGenerator - { - Replay Generate(); - } -} From cf39178099c9178e5ef9136bfdabc6dbcdf5cc02 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 6 May 2021 21:53:34 +0900 Subject: [PATCH 198/267] Use FramedAutoGenerator in Taiko, Catch, Mania OsuAutoGenerator is not included in this change because it uses SortedList-like thing --- .../Replays/CatchAutoGenerator.cs | 20 ++++--------------- .../Replays/ManiaAutoGenerator.cs | 15 ++++---------- .../Replays/TaikoAutoGenerator.cs | 14 +++---------- 3 files changed, 11 insertions(+), 38 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 10230b6b78..2e1e4f7e77 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using osu.Framework.Utils; using osu.Game.Beatmaps; -using osu.Game.Replays; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; @@ -13,26 +12,19 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Catch.Replays { - internal class CatchAutoGenerator : AutoGenerator + internal class CatchAutoGenerator : FramedAutoGenerator { - public const double RELEASE_DELAY = 20; - public new CatchBeatmap Beatmap => (CatchBeatmap)base.Beatmap; public CatchAutoGenerator(IBeatmap beatmap) : base(beatmap) { - Replay = new Replay(); } - protected Replay Replay; - - private CatchReplayFrame currentFrame; - - public override Replay Generate() + protected override void GenerateFrames() { if (Beatmap.HitObjects.Count == 0) - return Replay; + return; // todo: add support for HT DT const double dash_speed = Catcher.BASE_SPEED; @@ -119,15 +111,11 @@ namespace osu.Game.Rulesets.Catch.Replays } } } - - return Replay; } private void addFrame(double time, float? position = null, bool dashing = false) { - var last = currentFrame; - currentFrame = new CatchReplayFrame(time, position, dashing, last); - Replay.Frames.Add(currentFrame); + Frames.Add(new CatchReplayFrame(time, position, dashing, LastFrame)); } } } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index ada84dfac2..4fd105025c 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; @@ -11,7 +10,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Mania.Replays { - internal class ManiaAutoGenerator : AutoGenerator + internal class ManiaAutoGenerator : FramedAutoGenerator { public const double RELEASE_DELAY = 20; @@ -22,8 +21,6 @@ namespace osu.Game.Rulesets.Mania.Replays public ManiaAutoGenerator(ManiaBeatmap beatmap) : base(beatmap) { - Replay = new Replay(); - columnActions = new ManiaAction[Beatmap.TotalColumns]; var normalAction = ManiaAction.Key1; @@ -43,12 +40,10 @@ namespace osu.Game.Rulesets.Mania.Replays } } - protected Replay Replay; - - public override Replay Generate() + protected override void GenerateFrames() { if (Beatmap.HitObjects.Count == 0) - return Replay; + return; var pointGroups = generateActionPoints().GroupBy(a => a.Time).OrderBy(g => g.First().Time); @@ -70,10 +65,8 @@ namespace osu.Game.Rulesets.Mania.Replays } } - Replay.Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray())); + Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray())); } - - return Replay; } private IEnumerable generateActionPoints() diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index fa0134aa94..bd2b7338de 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -2,10 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Replays; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Taiko.Beatmaps; @@ -13,7 +11,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Replays { - public class TaikoAutoGenerator : AutoGenerator + public class TaikoAutoGenerator : FramedAutoGenerator { public new TaikoBeatmap Beatmap => (TaikoBeatmap)base.Beatmap; @@ -22,16 +20,12 @@ namespace osu.Game.Rulesets.Taiko.Replays public TaikoAutoGenerator(IBeatmap beatmap) : base(beatmap) { - Replay = new Replay(); } - protected Replay Replay; - protected List Frames => Replay.Frames; - - public override Replay Generate() + protected override void GenerateFrames() { if (Beatmap.HitObjects.Count == 0) - return Replay; + return; bool hitButton = true; @@ -128,8 +122,6 @@ namespace osu.Game.Rulesets.Taiko.Replays hitButton = !hitButton; } - - return Replay; } } } From 95c74c906a33084142a71bd16b58d4063f237bfb Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 6 May 2021 21:57:03 +0900 Subject: [PATCH 199/267] Use FramedAutoGenerator in template projects --- .../Replays/EmptyFreeformAutoGenerator.cs | 12 ++---------- .../Replays/PippidonAutoGenerator.cs | 12 ++---------- .../Replays/EmptyScrollingAutoGenerator.cs | 12 ++---------- .../Replays/PippidonAutoGenerator.cs | 12 ++---------- 4 files changed, 8 insertions(+), 40 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Replays/EmptyFreeformAutoGenerator.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Replays/EmptyFreeformAutoGenerator.cs index 6d8d4215a2..5d61136f54 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Replays/EmptyFreeformAutoGenerator.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Replays/EmptyFreeformAutoGenerator.cs @@ -1,28 +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.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Replays; using osu.Game.Rulesets.EmptyFreeform.Objects; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.EmptyFreeform.Replays { - public class EmptyFreeformAutoGenerator : AutoGenerator + public class EmptyFreeformAutoGenerator : FramedAutoGenerator { - protected Replay Replay; - protected List Frames => Replay.Frames; - public new Beatmap Beatmap => (Beatmap)base.Beatmap; public EmptyFreeformAutoGenerator(IBeatmap beatmap) : base(beatmap) { - Replay = new Replay(); } - public override Replay Generate() + protected override void GenerateFrames() { Frames.Add(new EmptyFreeformReplayFrame()); @@ -35,8 +29,6 @@ namespace osu.Game.Rulesets.EmptyFreeform.Replays // todo: add required inputs and extra frames. }); } - - return Replay; } } } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs index 9c54b82e38..f795d7ef21 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs @@ -1,28 +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.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Replays; using osu.Game.Rulesets.Pippidon.Objects; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Pippidon.Replays { - public class PippidonAutoGenerator : AutoGenerator + public class PippidonAutoGenerator : FramedAutoGenerator { - protected Replay Replay; - protected List Frames => Replay.Frames; - public new Beatmap Beatmap => (Beatmap)base.Beatmap; public PippidonAutoGenerator(IBeatmap beatmap) : base(beatmap) { - Replay = new Replay(); } - public override Replay Generate() + protected override void GenerateFrames() { Frames.Add(new PippidonReplayFrame()); @@ -34,8 +28,6 @@ namespace osu.Game.Rulesets.Pippidon.Replays Position = hitObject.Position, }); } - - return Replay; } } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Replays/EmptyScrollingAutoGenerator.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Replays/EmptyScrollingAutoGenerator.cs index 7923918842..ab27fd4dcd 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Replays/EmptyScrollingAutoGenerator.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Replays/EmptyScrollingAutoGenerator.cs @@ -1,28 +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.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Replays; using osu.Game.Rulesets.EmptyScrolling.Objects; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.EmptyScrolling.Replays { - public class EmptyScrollingAutoGenerator : AutoGenerator + public class EmptyScrollingAutoGenerator : FramedAutoGenerator { - protected Replay Replay; - protected List Frames => Replay.Frames; - public new Beatmap Beatmap => (Beatmap)base.Beatmap; public EmptyScrollingAutoGenerator(IBeatmap beatmap) : base(beatmap) { - Replay = new Replay(); } - public override Replay Generate() + protected override void GenerateFrames() { Frames.Add(new EmptyScrollingReplayFrame()); @@ -34,8 +28,6 @@ namespace osu.Game.Rulesets.EmptyScrolling.Replays // todo: add required inputs and extra frames. }); } - - return Replay; } } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs index bd99cdcdbd..df2cfb8731 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs @@ -2,29 +2,23 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Replays; using osu.Game.Rulesets.Pippidon.Objects; using osu.Game.Rulesets.Pippidon.UI; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Pippidon.Replays { - public class PippidonAutoGenerator : AutoGenerator + public class PippidonAutoGenerator : FramedAutoGenerator { - protected Replay Replay; - protected List Frames => Replay.Frames; - public new Beatmap Beatmap => (Beatmap)base.Beatmap; public PippidonAutoGenerator(IBeatmap beatmap) : base(beatmap) { - Replay = new Replay(); } - public override Replay Generate() + protected override void GenerateFrames() { int currentLane = 0; @@ -55,8 +49,6 @@ namespace osu.Game.Rulesets.Pippidon.Replays currentLane = hitObject.Lane; } - - return Replay; } private void addFrame(double time, PippidonAction direction) From 207f7f1e563ce252eb88affc19cdd09544d80212 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 7 May 2021 00:31:12 +0900 Subject: [PATCH 200/267] Rename FramedAutoGenerator -> AutoGenerator --- .../Replays/EmptyFreeformAutoGenerator.cs | 2 +- .../Replays/PippidonAutoGenerator.cs | 2 +- .../Replays/EmptyScrollingAutoGenerator.cs | 2 +- .../Replays/PippidonAutoGenerator.cs | 2 +- .../Replays/CatchAutoGenerator.cs | 2 +- .../Replays/ManiaAutoGenerator.cs | 2 +- .../Replays/TaikoAutoGenerator.cs | 2 +- osu.Game/Rulesets/Replays/AutoGenerator.cs | 36 +++++++++++++++ .../Rulesets/Replays/FramedAutoGenerator.cs | 44 ------------------- 9 files changed, 43 insertions(+), 51 deletions(-) delete mode 100644 osu.Game/Rulesets/Replays/FramedAutoGenerator.cs diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Replays/EmptyFreeformAutoGenerator.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Replays/EmptyFreeformAutoGenerator.cs index 5d61136f54..62f394d1ce 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Replays/EmptyFreeformAutoGenerator.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Replays/EmptyFreeformAutoGenerator.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.EmptyFreeform.Replays { - public class EmptyFreeformAutoGenerator : FramedAutoGenerator + public class EmptyFreeformAutoGenerator : AutoGenerator { public new Beatmap Beatmap => (Beatmap)base.Beatmap; diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs index f795d7ef21..612288257d 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Pippidon.Replays { - public class PippidonAutoGenerator : FramedAutoGenerator + public class PippidonAutoGenerator : AutoGenerator { public new Beatmap Beatmap => (Beatmap)base.Beatmap; diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Replays/EmptyScrollingAutoGenerator.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Replays/EmptyScrollingAutoGenerator.cs index ab27fd4dcd..1058f756f3 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Replays/EmptyScrollingAutoGenerator.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Replays/EmptyScrollingAutoGenerator.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.EmptyScrolling.Replays { - public class EmptyScrollingAutoGenerator : FramedAutoGenerator + public class EmptyScrollingAutoGenerator : AutoGenerator { public new Beatmap Beatmap => (Beatmap)base.Beatmap; diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs index df2cfb8731..724026273d 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Replays/PippidonAutoGenerator.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Pippidon.Replays { - public class PippidonAutoGenerator : FramedAutoGenerator + public class PippidonAutoGenerator : AutoGenerator { public new Beatmap Beatmap => (Beatmap)base.Beatmap; diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 2e1e4f7e77..a81703119a 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Catch.Replays { - internal class CatchAutoGenerator : FramedAutoGenerator + internal class CatchAutoGenerator : AutoGenerator { public new CatchBeatmap Beatmap => (CatchBeatmap)base.Beatmap; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 4fd105025c..517b708691 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Mania.Replays { - internal class ManiaAutoGenerator : FramedAutoGenerator + internal class ManiaAutoGenerator : AutoGenerator { public const double RELEASE_DELAY = 20; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index bd2b7338de..5fd281f9fa 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Replays { - public class TaikoAutoGenerator : FramedAutoGenerator + public class TaikoAutoGenerator : AutoGenerator { public new TaikoBeatmap Beatmap => (TaikoBeatmap)base.Beatmap; diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index 4bdd5b094d..6ce857b14b 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -1,6 +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 System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Replays; using osu.Game.Rulesets.Objects; @@ -37,4 +40,37 @@ namespace osu.Game.Rulesets.Replays return Beatmap.HitObjects[currentIndex + 1]; } } + + public abstract class AutoGenerator : AutoGenerator + where TFrame : ReplayFrame + { + /// + /// The replay frames of the autoplay. + /// + protected readonly List Frames = new List(); + + [CanBeNull] + protected TFrame LastFrame => Frames.Count == 0 ? null : Frames[^1]; + + protected AutoGenerator(IBeatmap beatmap) + : base(beatmap) + { + } + + public sealed override Replay Generate() + { + Frames.Clear(); + GenerateFrames(); + + return new Replay + { + Frames = Frames.OrderBy(frame => frame.Time).Cast().ToList() + }; + } + + /// + /// Generate the replay frames of the autoplay and populate . + /// + protected abstract void GenerateFrames(); + } } diff --git a/osu.Game/Rulesets/Replays/FramedAutoGenerator.cs b/osu.Game/Rulesets/Replays/FramedAutoGenerator.cs deleted file mode 100644 index 091eb00232..0000000000 --- a/osu.Game/Rulesets/Replays/FramedAutoGenerator.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable enable - -using System.Collections.Generic; -using System.Linq; -using osu.Game.Beatmaps; -using osu.Game.Replays; - -namespace osu.Game.Rulesets.Replays -{ - public abstract class FramedAutoGenerator : AutoGenerator - where TFrame : ReplayFrame - { - /// - /// The replay frames of the autoplay. - /// - protected readonly List Frames = new List(); - - protected TFrame? LastFrame => Frames.Count == 0 ? null : Frames[^1]; - - protected FramedAutoGenerator(IBeatmap beatmap) - : base(beatmap) - { - } - - public sealed override Replay Generate() - { - Frames.Clear(); - GenerateFrames(); - - return new Replay - { - Frames = Frames.OrderBy(frame => frame.Time).Cast().ToList() - }; - } - - /// - /// Generate the replay frames of the autoplay and populate . - /// - protected abstract void GenerateFrames(); - } -} From 54fe10c82a855a16c88f8781a9ae12dc42df7b0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 10:36:03 +0900 Subject: [PATCH 201/267] Refactor `SliderSelectionBlueprint` to not reference blueprint pieces for input handling --- .../Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs | 6 ------ .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index 6e22c35ab3..ece9c7a757 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -26,10 +26,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { AccentColour = Color4.Transparent }; - - // SliderSelectionBlueprint relies on calling ReceivePositionalInputAt on this drawable to determine whether selection should occur. - // Without AlwaysPresent, a movement in a parent container (ie. the editor composer area resizing) could cause incorrect input handling. - AlwaysPresent = true; } [BackgroundDependencyLoader] @@ -54,7 +50,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } public void RecyclePath() => body.RecyclePath(); - - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => body.ReceivePositionalInputAt(screenSpacePos); } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 88fcb1e715..32d2fba25e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -240,10 +240,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)), }; - public override Vector2 ScreenSpaceSelectionPoint => BodyPiece.ToScreenSpace(BodyPiece.PathStartLocation); + public override Vector2 ScreenSpaceSelectionPoint => this.ToScreenSpace(slider.HitObject.StackedPosition); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => - BodyPiece.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos)) == true; + slider.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos)) == true; protected virtual SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new SliderCircleSelectionBlueprint(slider, position); } From 84da24700204724cde9a8b90506b078add49c964 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 May 2021 05:32:55 +0300 Subject: [PATCH 202/267] Fix editor clock using the wrong beatmap track on creation --- osu.Game/Screens/Edit/Editor.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index da0e9ebbaf..138d8cfaff 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -145,7 +145,7 @@ namespace osu.Game.Screens.Edit // Todo: should probably be done at a DrawableRuleset level to share logic with Player. clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false }; - UpdateClockSource(); + updateClockSource(loadableBeatmap); dependencies.CacheAs(clock); AddInternal(clock); @@ -308,9 +308,11 @@ namespace osu.Game.Screens.Edit /// /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state. /// - public void UpdateClockSource() + public void UpdateClockSource() => updateClockSource(Beatmap.Value); + + private void updateClockSource(WorkingBeatmap beatmap) { - var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); + var sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock(); clock.ChangeSource(sourceClock); } From 539643c72b390b1c40b8fb8340b37f33ef91d7d5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 May 2021 07:18:43 +0300 Subject: [PATCH 203/267] Set loadable beatmap track to clock immediately in BDL This reverts commit 84da24700204724cde9a8b90506b078add49c964. Use loadable beatmap track for clock directly in BDL --- osu.Game/Screens/Edit/Editor.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 138d8cfaff..a4c331c4e0 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -144,8 +144,7 @@ namespace osu.Game.Screens.Edit // Todo: should probably be done at a DrawableRuleset level to share logic with Player. clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false }; - - updateClockSource(loadableBeatmap); + clock.ChangeSource(loadableBeatmap.Track); dependencies.CacheAs(clock); AddInternal(clock); @@ -308,11 +307,9 @@ namespace osu.Game.Screens.Edit /// /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state. /// - public void UpdateClockSource() => updateClockSource(Beatmap.Value); - - private void updateClockSource(WorkingBeatmap beatmap) + public void UpdateClockSource() { - var sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock(); + var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); clock.ChangeSource(sourceClock); } From f9d99a98826525b58d8a076f772da6a9a77329ec Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 May 2021 07:25:14 +0300 Subject: [PATCH 204/267] Mark `WorkingBeatmap.Track` as not null --- osu.Game/Beatmaps/WorkingBeatmap.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index e0eeaf6db0..bef258753e 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -298,6 +298,7 @@ namespace osu.Game.Beatmaps /// Get the loaded audio track instance. must have first been called. /// This generally happens via MusicController when changing the global beatmap. /// + [NotNull] public Track Track { get From 71547bece0dcd99cfbe6ba95bd2e42066b6eb686 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 May 2021 07:43:06 +0300 Subject: [PATCH 205/267] Remove any null-coalescing/conditionals in `WorkingBeatmap.Track` usages --- osu.Game/Screens/Edit/Editor.cs | 9 ++------- osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index a4c331c4e0..434683a016 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -17,7 +17,6 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; @@ -307,11 +306,7 @@ namespace osu.Game.Screens.Edit /// /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state. /// - public void UpdateClockSource() - { - var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); - clock.ChangeSource(sourceClock); - } + public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track); protected void Save() { @@ -582,7 +577,7 @@ namespace osu.Game.Screens.Edit private void resetTrack(bool seekToStart = false) { - Beatmap.Value.Track?.Stop(); + Beatmap.Value.Track.Stop(); if (seekToStart) { diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 79cfee8518..34393fba7d 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit; @@ -46,7 +45,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(ValueChangedEvent e) { Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; - Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock()); + Clock.ChangeSource(e.NewValue.Track); Clock.ProcessFrame(); } From 37f44d2e37602ec557ed7fda6ca7afced0bfec81 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 May 2021 08:27:56 +0300 Subject: [PATCH 206/267] Revert wrong not-null track changes This reverts commit f9d99a98826525b58d8a076f772da6a9a77329ec. This reverts commit 71547bece0dcd99cfbe6ba95bd2e42066b6eb686. --- osu.Game/Beatmaps/WorkingBeatmap.cs | 1 - osu.Game/Screens/Edit/Editor.cs | 9 +++++++-- osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index bef258753e..e0eeaf6db0 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -298,7 +298,6 @@ namespace osu.Game.Beatmaps /// Get the loaded audio track instance. must have first been called. /// This generally happens via MusicController when changing the global beatmap. /// - [NotNull] public Track Track { get diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 434683a016..a4c331c4e0 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -17,6 +17,7 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; @@ -306,7 +307,11 @@ namespace osu.Game.Screens.Edit /// /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state. /// - public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track); + public void UpdateClockSource() + { + var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); + clock.ChangeSource(sourceClock); + } protected void Save() { @@ -577,7 +582,7 @@ namespace osu.Game.Screens.Edit private void resetTrack(bool seekToStart = false) { - Beatmap.Value.Track.Stop(); + Beatmap.Value.Track?.Stop(); if (seekToStart) { diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 34393fba7d..79cfee8518 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Events; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit; @@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(ValueChangedEvent e) { Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; - Clock.ChangeSource(e.NewValue.Track); + Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock()); Clock.ProcessFrame(); } From b1134c3857980e5f473dc3ba3f57d1ab7bdcabdb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 May 2021 08:30:50 +0300 Subject: [PATCH 207/267] Guard against potentially null track if ever --- osu.Game/Screens/Edit/Editor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index a4c331c4e0..78d5c24108 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -144,7 +144,7 @@ namespace osu.Game.Screens.Edit // Todo: should probably be done at a DrawableRuleset level to share logic with Player. clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false }; - clock.ChangeSource(loadableBeatmap.Track); + clock.ChangeSource((IAdjustableClock)loadableBeatmap.Track ?? new StopwatchClock()); dependencies.CacheAs(clock); AddInternal(clock); From bdfe44ddca7235cd7a42bac8015f2e55b13bf905 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 13:19:30 +0700 Subject: [PATCH 208/267] change OsuMarkdownListItem to abstract class --- .../Markdown/OsuMarkdownListItem.cs | 72 +++---------------- 1 file changed, 10 insertions(+), 62 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index b586bb7f30..8c4c3e1da2 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -1,41 +1,34 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using Markdig.Syntax; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Sprites; using osuTK; namespace osu.Game.Graphics.Containers.Markdown { - public class OsuMarkdownListItem : CompositeDrawable + public abstract class OsuMarkdownListItem : CompositeDrawable { - private const float ordered_left_padding = 30; - private const float unordered_left_padding = 20; - - private readonly int level; - private readonly int order; - private readonly bool isOrdered; - [Resolved] private IMarkdownTextComponent parentTextComponent { get; set; } - public FillFlowContainer Content { get; } + public FillFlowContainer Content { get; private set; } - public OsuMarkdownListItem(ListItemBlock listItemBlock, int level) + protected OsuMarkdownListItem() { - this.level = level; - order = listItemBlock.Order; - isOrdered = ((ListBlock)listItemBlock.Parent).IsOrdered; - AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; - Padding = new MarginPadding { Left = isOrdered ? ordered_left_padding : unordered_left_padding }; + } + [BackgroundDependencyLoader] + private void load() + { InternalChildren = new Drawable[] { + CreateMarker(), Content = new FillFlowContainer { AutoSizeAxes = Axes.Y, @@ -46,51 +39,6 @@ namespace osu.Game.Graphics.Containers.Markdown }; } - [BackgroundDependencyLoader] - private void load() - { - var marker = parentTextComponent.CreateSpriteText(); - marker.Text = GetTextMarker(level, isOrdered); - - if (isOrdered) - { - marker.X = -ordered_left_padding; - } - else - { - marker.Font = OsuFont.GetFont(size: marker.Font.Size / 2); - marker.Origin = Anchor.Centre; - marker.X = -unordered_left_padding / 2; - marker.Y = marker.Font.Size; - } - - AddInternal(marker); - } - - /// - /// Get text marker based on and . - /// - /// The markdown level of current list item. - /// Is true if the list item is an ordered list. - /// - protected virtual string GetTextMarker(int level, bool isOrdered) - { - if (isOrdered) - { - return $"{order}."; - } - - switch (level) - { - case 1: - return "●"; - - case 2: - return "○"; - - default: - return "■"; - } - } + protected virtual SpriteText CreateMarker() => parentTextComponent.CreateSpriteText(); } } From dfcf760b7be0592eb4212e3fdc9bc21073eaaa59 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 13:20:06 +0700 Subject: [PATCH 209/267] add OsuMarkdownOrderedListItem --- .../Markdown/OsuMarkdownOrderedListItem.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs new file mode 100644 index 0000000000..8fedb189b2 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs @@ -0,0 +1,27 @@ +// 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.Graphics; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownOrderedListItem : OsuMarkdownListItem + { + private const float left_padding = 30; + + private readonly int order; + + public OsuMarkdownOrderedListItem(int order) + { + this.order = order; + Padding = new MarginPadding { Left = left_padding }; + } + + protected override SpriteText CreateMarker() => base.CreateMarker().With(t => + { + t.X = -left_padding; + t.Text = $"{order}."; + }); + } +} From 9233248a0ba84919802e8dbae203a5a95b2fceaa Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 13:20:20 +0700 Subject: [PATCH 210/267] add OsuMarkdownUnorderedListItem --- .../Markdown/OsuMarkdownUnorderedListItem.cs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs new file mode 100644 index 0000000000..8bfaf8ad21 --- /dev/null +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs @@ -0,0 +1,51 @@ +// 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.Graphics; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Graphics.Containers.Markdown +{ + public class OsuMarkdownUnorderedListItem : OsuMarkdownListItem + { + private const float left_padding = 20; + + private readonly int level; + + public OsuMarkdownUnorderedListItem(int level) + { + this.level = level; + + Padding = new MarginPadding { Left = left_padding }; + } + + protected override SpriteText CreateMarker() => base.CreateMarker().With(t => + { + t.Text = GetTextMarker(level); + t.Font = t.Font.With(size: t.Font.Size / 2); + t.Origin = Anchor.Centre; + t.X = -left_padding / 2; + t.Y = t.Font.Size; + }); + + /// + /// Get text marker based on + /// + /// The markdown level of current list item. + /// + protected virtual string GetTextMarker(int level) + { + switch (level) + { + case 1: + return "●"; + + case 2: + return "○"; + + default: + return "■"; + } + } + } +} From 5b003750f87044d16288b7b992023cc8011bf832 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 13:20:48 +0700 Subject: [PATCH 211/267] change CreateListItem method in OsuMarkdownContainer --- .../Containers/Markdown/OsuMarkdownContainer.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index c66f3fbca2..6facf4e26c 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -30,7 +30,8 @@ namespace osu.Game.Graphics.Containers.Markdown break; case ListItemBlock listItemBlock: - var childContainer = CreateListItem(listItemBlock, level); + var isOrdered = ((ListBlock)listItemBlock.Parent).IsOrdered; + var childContainer = CreateListItem(listItemBlock, level, isOrdered); container.Add(childContainer); foreach (var single in listItemBlock) base.AddMarkdownComponent(single, childContainer.Content, level); @@ -64,7 +65,13 @@ namespace osu.Game.Graphics.Containers.Markdown Padding = new MarginPadding(0) }; - protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock, int level) => new OsuMarkdownListItem(listItemBlock, level); + protected virtual OsuMarkdownListItem CreateListItem(ListItemBlock listItemBlock, int level, bool isOrdered) + { + if (isOrdered) + return new OsuMarkdownOrderedListItem(listItemBlock.Order); + + return new OsuMarkdownUnorderedListItem(level); + } protected override MarkdownPipeline CreateBuilder() => new MarkdownPipelineBuilder().UseAutoIdentifiers(AutoIdentifierOptions.GitHub) From 7c4e54a1d43990996e015affd03911514dc18952 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 May 2021 09:53:54 +0300 Subject: [PATCH 212/267] Unrevert null-colaescing/conditionals removal --- osu.Game/Screens/Edit/Editor.cs | 8 ++------ osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 +-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 78d5c24108..50dcb84235 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -307,11 +307,7 @@ namespace osu.Game.Screens.Edit /// /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state. /// - public void UpdateClockSource() - { - var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); - clock.ChangeSource(sourceClock); - } + public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track); protected void Save() { @@ -582,7 +578,7 @@ namespace osu.Game.Screens.Edit private void resetTrack(bool seekToStart = false) { - Beatmap.Value.Track?.Stop(); + Beatmap.Value.Track.Stop(); if (seekToStart) { diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 79cfee8518..34393fba7d 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit; @@ -46,7 +45,7 @@ namespace osu.Game.Tests.Visual private void beatmapChanged(ValueChangedEvent e) { Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; - Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock()); + Clock.ChangeSource(e.NewValue.Track); Clock.ProcessFrame(); } From fc2a527e9d419040697cd4e075c7ae04d1cd2c82 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 7 May 2021 09:54:58 +0300 Subject: [PATCH 213/267] Revert "Guard against potentially null track if ever" This reverts commit b1134c3857980e5f473dc3ba3f57d1ab7bdcabdb. --- osu.Game/Screens/Edit/Editor.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 50dcb84235..434683a016 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -17,7 +17,6 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; @@ -144,7 +143,7 @@ namespace osu.Game.Screens.Edit // Todo: should probably be done at a DrawableRuleset level to share logic with Player. clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false }; - clock.ChangeSource((IAdjustableClock)loadableBeatmap.Track ?? new StopwatchClock()); + clock.ChangeSource(loadableBeatmap.Track); dependencies.CacheAs(clock); AddInternal(clock); From a2e4fb5b6b0cc7cd97fa439a9e2e1b13dcb6f10e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 16:10:57 +0900 Subject: [PATCH 214/267] Update `ScoreCounter` components to bind outwards --- .../TestSceneSkinnableScoreCounter.cs | 26 ++++------ .../Graphics/UserInterface/ScoreCounter.cs | 3 +- .../Screens/Play/HUD/DefaultScoreCounter.cs | 3 +- .../Screens/Play/HUD/GameplayScoreCounter.cs | 46 ++++++++++++++++++ osu.Game/Screens/Play/HUD/IScoreCounter.cs | 25 ---------- .../Screens/Play/HUD/SkinnableScoreCounter.cs | 47 +------------------ osu.Game/Screens/Play/HUDOverlay.cs | 1 - osu.Game/Skinning/LegacyScoreCounter.cs | 4 +- 8 files changed, 60 insertions(+), 95 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs delete mode 100644 osu.Game/Screens/Play/HUD/IScoreCounter.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs index e212ceeba7..4f2183711e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs @@ -4,10 +4,12 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Gameplay @@ -18,37 +20,27 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); + [Cached] + private ScoreProcessor scoreProcessor = new ScoreProcessor(); + [SetUpSteps] public void SetUpSteps() { - AddStep("Create combo counters", () => SetContents(() => - { - var comboCounter = new SkinnableScoreCounter(); - comboCounter.Current.Value = 1; - return comboCounter; - })); + AddStep("Create score counters", () => SetContents(() => new SkinnableScoreCounter())); } [Test] public void TestScoreCounterIncrementing() { - AddStep(@"Reset all", delegate - { - foreach (var s in scoreCounters) - s.Current.Value = 0; - }); + AddStep(@"Reset all", () => scoreProcessor.TotalScore.Value = 0); - AddStep(@"Hit! :D", delegate - { - foreach (var s in scoreCounters) - s.Current.Value += 300; - }); + AddStep(@"Hit! :D", () => scoreProcessor.TotalScore.Value += 300); } [Test] public void TestVeryLargeScore() { - AddStep("set large score", () => scoreCounters.ForEach(counter => counter.Current.Value = 1_000_000_000)); + AddStep("set large score", () => scoreCounters.ForEach(counter => scoreProcessor.TotalScore.Value = 1_000_000_000)); } } } diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index d75e49a4ce..5747c846eb 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -4,11 +4,10 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Screens.Play.HUD; namespace osu.Game.Graphics.UserInterface { - public abstract class ScoreCounter : RollingCounter, IScoreCounter + public abstract class ScoreCounter : RollingCounter { protected override double RollingDuration => 1000; protected override Easing RollingEasing => Easing.Out; diff --git a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs index 1dcfe2e067..84db605d53 100644 --- a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs @@ -4,11 +4,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Play.HUD { - public class DefaultScoreCounter : ScoreCounter + public class DefaultScoreCounter : GameplayScoreCounter { public DefaultScoreCounter() : base(6) diff --git a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs new file mode 100644 index 0000000000..e09630d2c4 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs @@ -0,0 +1,46 @@ +// 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.Allocation; +using osu.Framework.Bindables; +using osu.Game.Configuration; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Screens.Play.HUD +{ + public abstract class GameplayScoreCounter : ScoreCounter + { + private Bindable scoreDisplayMode; + + protected GameplayScoreCounter(int leading = 0, bool useCommaSeparator = false) + : base(leading, useCommaSeparator) + { + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config, ScoreProcessor scoreProcessor) + { + scoreDisplayMode = config.GetBindable(OsuSetting.ScoreDisplayMode); + scoreDisplayMode.BindValueChanged(scoreMode => + { + switch (scoreMode.NewValue) + { + case ScoringMode.Standardised: + RequiredDisplayDigits.Value = 6; + break; + + case ScoringMode.Classic: + RequiredDisplayDigits.Value = 8; + break; + + default: + throw new ArgumentOutOfRangeException(nameof(scoreMode)); + } + }, true); + + Current.BindTo(scoreProcessor.TotalScore); + } + } +} diff --git a/osu.Game/Screens/Play/HUD/IScoreCounter.cs b/osu.Game/Screens/Play/HUD/IScoreCounter.cs deleted file mode 100644 index 7f5e81d5ef..0000000000 --- a/osu.Game/Screens/Play/HUD/IScoreCounter.cs +++ /dev/null @@ -1,25 +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 osu.Framework.Bindables; -using osu.Framework.Graphics; - -namespace osu.Game.Screens.Play.HUD -{ - /// - /// An interface providing a set of methods to update a score counter. - /// - public interface IScoreCounter : IDrawable - { - /// - /// The current score to be displayed. - /// - Bindable Current { get; } - - /// - /// The number of digits required to display most sane scores. - /// This may be exceeded in very rare cases, but is useful to pad or space the display to avoid it jumping around. - /// - Bindable RequiredDisplayDigits { get; } - } -} diff --git a/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs index b46f5684b1..cc9a712e97 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableScoreCounter.cs @@ -1,61 +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 osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Game.Configuration; -using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableScoreCounter : SkinnableDrawable, IScoreCounter + public class SkinnableScoreCounter : SkinnableDrawable { - public Bindable Current { get; } = new Bindable(); - - private Bindable scoreDisplayMode; - - public Bindable RequiredDisplayDigits { get; } = new Bindable(); - public SkinnableScoreCounter() : base(new HUDSkinComponent(HUDSkinComponents.ScoreCounter), _ => new DefaultScoreCounter()) { CentreComponent = false; } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - scoreDisplayMode = config.GetBindable(OsuSetting.ScoreDisplayMode); - scoreDisplayMode.BindValueChanged(scoreMode => - { - switch (scoreMode.NewValue) - { - case ScoringMode.Standardised: - RequiredDisplayDigits.Value = 6; - break; - - case ScoringMode.Classic: - RequiredDisplayDigits.Value = 8; - break; - - default: - throw new ArgumentOutOfRangeException(nameof(scoreMode)); - } - }, true); - } - - private IScoreCounter skinnedCounter; - - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - - skinnedCounter = Drawable as IScoreCounter; - - skinnedCounter?.Current.BindTo(Current); - skinnedCounter?.RequiredDisplayDigits.BindTo(RequiredDisplayDigits); - } } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 83897c5167..c887fb78e0 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -320,7 +320,6 @@ namespace osu.Game.Screens.Play protected virtual void BindScoreProcessor(ScoreProcessor processor) { - ScoreCounter?.Current.BindTo(processor.TotalScore); AccuracyCounter?.Current.BindTo(processor.Accuracy); if (HealthDisplay is IHealthDisplay shd) diff --git a/osu.Game/Skinning/LegacyScoreCounter.cs b/osu.Game/Skinning/LegacyScoreCounter.cs index 1d330ef495..e385caf304 100644 --- a/osu.Game/Skinning/LegacyScoreCounter.cs +++ b/osu.Game/Skinning/LegacyScoreCounter.cs @@ -4,12 +4,12 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Play.HUD; using osuTK; namespace osu.Game.Skinning { - public class LegacyScoreCounter : ScoreCounter + public class LegacyScoreCounter : GameplayScoreCounter { private readonly ISkin skin; From ad398165a2d38870173df9b82034691d8c9c8d4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 16:26:54 +0900 Subject: [PATCH 215/267] Update `AccuracyCounter` components to use DI to attach data source --- .../TestSceneSkinnableAccuracyCounter.cs | 26 ++++++------------- .../Play/HUD/DefaultAccuracyCounter.cs | 3 +-- .../Play/HUD/GameplayAccuracyCounter.cs | 18 +++++++++++++ osu.Game/Screens/Play/HUD/IAccuracyCounter.cs | 19 -------------- .../Play/HUD/SkinnableAccuracyCounter.cs | 12 +-------- osu.Game/Skinning/LegacyAccuracyCounter.cs | 3 +-- 6 files changed, 29 insertions(+), 52 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs delete mode 100644 osu.Game/Screens/Play/HUD/IAccuracyCounter.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs index 709929dcb0..34356184a2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Gameplay @@ -17,33 +19,21 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); + [Cached] + private ScoreProcessor scoreProcessor = new ScoreProcessor(); + [SetUpSteps] public void SetUpSteps() { - AddStep("Create combo counters", () => SetContents(() => - { - var accuracyCounter = new SkinnableAccuracyCounter(); - - accuracyCounter.Current.Value = 1; - - return accuracyCounter; - })); + AddStep("Create combo counters", () => SetContents(() => new SkinnableAccuracyCounter())); } [Test] public void TestChangingAccuracy() { - AddStep(@"Reset all", delegate - { - foreach (var s in accuracyCounters) - s.Current.Value = 1; - }); + AddStep(@"Reset all", () => scoreProcessor.Accuracy.Value = 1); - AddStep(@"Hit! :D", delegate - { - foreach (var s in accuracyCounters) - s.Current.Value -= 0.023f; - }); + AddStep(@"Hit! :D", () => scoreProcessor.Accuracy.Value -= 0.23); } } } diff --git a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs index d5d8ec570a..be1a4ad6b3 100644 --- a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs @@ -4,12 +4,11 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osuTK; namespace osu.Game.Screens.Play.HUD { - public class DefaultAccuracyCounter : PercentageCounter, IAccuracyCounter + public class DefaultAccuracyCounter : GameplayAccuracyCounter { private readonly Vector2 offset = new Vector2(-20, 5); diff --git a/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs new file mode 100644 index 0000000000..7a63084812 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs @@ -0,0 +1,18 @@ +// 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.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Screens.Play.HUD +{ + public abstract class GameplayAccuracyCounter : PercentageCounter + { + [BackgroundDependencyLoader] + private void load(ScoreProcessor scoreProcessor) + { + Current.BindTo(scoreProcessor.Accuracy); + } + } +} diff --git a/osu.Game/Screens/Play/HUD/IAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/IAccuracyCounter.cs deleted file mode 100644 index 0199250a08..0000000000 --- a/osu.Game/Screens/Play/HUD/IAccuracyCounter.cs +++ /dev/null @@ -1,19 +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 osu.Framework.Bindables; -using osu.Framework.Graphics; - -namespace osu.Game.Screens.Play.HUD -{ - /// - /// An interface providing a set of methods to update a accuracy counter. - /// - public interface IAccuracyCounter : IDrawable - { - /// - /// The current accuracy to be displayed. - /// - Bindable Current { get; } - } -} diff --git a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs index 76c9c30813..17c2493d2d 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs @@ -6,7 +6,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableAccuracyCounter : SkinnableDrawable, IAccuracyCounter + public class SkinnableAccuracyCounter : SkinnableDrawable { public Bindable Current { get; } = new Bindable(); @@ -15,15 +15,5 @@ namespace osu.Game.Screens.Play.HUD { CentreComponent = false; } - - private IAccuracyCounter skinnedCounter; - - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - - skinnedCounter = Drawable as IAccuracyCounter; - skinnedCounter?.Current.BindTo(Current); - } } } diff --git a/osu.Game/Skinning/LegacyAccuracyCounter.cs b/osu.Game/Skinning/LegacyAccuracyCounter.cs index 7d6f1dc916..638faa8f2b 100644 --- a/osu.Game/Skinning/LegacyAccuracyCounter.cs +++ b/osu.Game/Skinning/LegacyAccuracyCounter.cs @@ -4,14 +4,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; using osuTK; namespace osu.Game.Skinning { - public class LegacyAccuracyCounter : PercentageCounter, IAccuracyCounter + public class LegacyAccuracyCounter : GameplayAccuracyCounter { private readonly ISkin skin; From 3524cb792444dd1f400a8e54bb0d4ce425d48b4f Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 14:36:35 +0700 Subject: [PATCH 216/267] simplify CreateSpriteText in markdown heading --- .../Graphics/Containers/Markdown/OsuMarkdownHeading.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs index a7fecc6e25..40eb4cad15 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using Markdig.Syntax; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Sprites; @@ -68,12 +69,7 @@ namespace osu.Game.Graphics.Containers.Markdown { public FontWeight Weight { get; set; } - protected override SpriteText CreateSpriteText() - { - var spriteText = base.CreateSpriteText(); - spriteText.Font = spriteText.Font.With(weight: Weight); - return spriteText; - } + protected override SpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = t.Font.With(weight: Weight)); } } } From 17b8963cf8db3f908359905bded8907f49398503 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 14:38:19 +0700 Subject: [PATCH 217/267] simplify CreateSpriteText in markdown table cell --- .../Graphics/Containers/Markdown/OsuMarkdownTableCell.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs index fca85e02a8..763c9d7536 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs @@ -59,12 +59,7 @@ namespace osu.Game.Graphics.Containers.Markdown { public FontWeight Weight { get; set; } - protected override SpriteText CreateSpriteText() - { - var spriteText = base.CreateSpriteText(); - spriteText.Font = spriteText.Font.With(weight: Weight); - return spriteText; - } + protected override SpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = t.Font.With(weight: Weight)); } } } From 79a1d7b2b39d018b231abc2508ab1c1494acd39d Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 14:40:01 +0700 Subject: [PATCH 218/267] simplify CreateEmphasisedSpriteText --- .../Containers/Markdown/OsuMarkdownTextFlowContainer.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs index 517143c2db..1550b8401d 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs @@ -3,6 +3,7 @@ using Markdig.Syntax.Inlines; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; @@ -28,10 +29,6 @@ namespace osu.Game.Graphics.Containers.Markdown => AddText(codeInline.Content, t => { t.Colour = colourProvider.Light1; }); protected override SpriteText CreateEmphasisedSpriteText(bool bold, bool italic) - { - var spriteText = CreateSpriteText(); - spriteText.Font = spriteText.Font.With(weight: bold ? FontWeight.Bold : FontWeight.Regular, italics: italic); - return spriteText; - } + => CreateSpriteText().With(t => t.Font = t.Font.With(weight: bold ? FontWeight.Bold : FontWeight.Regular, italics: italic)); } } From 64e9c5e9ba50924903ec6e280b68552d878e00f5 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 14:41:27 +0700 Subject: [PATCH 219/267] add return xmldoc in markdown unordered list --- .../Containers/Markdown/OsuMarkdownUnorderedListItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs index 8bfaf8ad21..5d1e114781 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.Containers.Markdown /// Get text marker based on /// /// The markdown level of current list item. - /// + /// The marker string of this list item protected virtual string GetTextMarker(int level) { switch (level) From d92e593ddddd425c4984e25346581af3d6da50f1 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 14:47:46 +0700 Subject: [PATCH 220/267] extract out table head and body border into separate component --- .../Markdown/OsuMarkdownTableCell.cs | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs index 763c9d7536..5949bf074b 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs @@ -26,27 +26,10 @@ namespace osu.Game.Graphics.Containers.Markdown [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - var border = new Box - { - RelativeSizeAxes = Axes.X, - }; - if (isHeading) - { - border.Colour = colourProvider.Background3; - border.Height = 2; - border.Anchor = Anchor.BottomLeft; - border.Origin = Anchor.BottomLeft; - } + AddInternal(new TableHeadBorder()); else - { - border.Colour = colourProvider.Background4; - border.Height = 1; - border.Anchor = Anchor.TopLeft; - border.Origin = Anchor.TopLeft; - } - - AddInternal(border); + AddInternal(new TableBodyBorder()); } public override MarkdownTextFlowContainer CreateTextFlow() => new TableCellTextFlowContainer @@ -55,6 +38,30 @@ namespace osu.Game.Graphics.Containers.Markdown Padding = new MarginPadding(10), }; + private class TableHeadBorder : Box + { + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Colour = colourProvider.Background3; + RelativeSizeAxes = Axes.X; + Height = 2; + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + } + } + + private class TableBodyBorder : Box + { + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Colour = colourProvider.Background4; + RelativeSizeAxes = Axes.X; + Height = 1; + } + } + private class TableCellTextFlowContainer : OsuMarkdownTextFlowContainer { public FontWeight Weight { get; set; } From 22677cfeaf7aea4657a1040d80eecdf12b3b1746 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Fri, 7 May 2021 14:54:46 +0700 Subject: [PATCH 221/267] add CreateBorder method in markdown table cell --- .../Containers/Markdown/OsuMarkdownTableCell.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs index 5949bf074b..ac7d07e283 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs @@ -24,12 +24,9 @@ namespace osu.Game.Graphics.Containers.Markdown } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load() { - if (isHeading) - AddInternal(new TableHeadBorder()); - else - AddInternal(new TableBodyBorder()); + AddInternal(CreateBorder(isHeading)); } public override MarkdownTextFlowContainer CreateTextFlow() => new TableCellTextFlowContainer @@ -38,6 +35,14 @@ namespace osu.Game.Graphics.Containers.Markdown Padding = new MarginPadding(10), }; + protected virtual Box CreateBorder(bool isHeading) + { + if (isHeading) + return new TableHeadBorder(); + + return new TableBodyBorder(); + } + private class TableHeadBorder : Box { [BackgroundDependencyLoader] From 9d27b11e499e634cf3276b1023bb8ac9db9cdf18 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 17:10:31 +0900 Subject: [PATCH 222/267] Update skin editor test scene to cache a `ScoreProcessor` --- .../Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 086bcb19c3..2424d24bc6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; @@ -17,6 +18,9 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneSkinEditorMultipleSkins : SkinnableTestScene { + [Cached] + private readonly ScoreProcessor scoreProcessor = new ScoreProcessor(); + [SetUpSteps] public void SetUpSteps() { @@ -28,8 +32,6 @@ namespace osu.Game.Tests.Visual.Gameplay var working = CreateWorkingBeatmap(ruleset.RulesetInfo); var beatmap = working.GetPlayableBeatmap(ruleset.RulesetInfo); - ScoreProcessor scoreProcessor = new ScoreProcessor(); - var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap); var hudOverlay = new HUDOverlay(scoreProcessor, null, drawableRuleset, Array.Empty()) @@ -40,7 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); - hudOverlay.ComboCounter.Current.Value = 1; + scoreProcessor.Combo.Value = 1; return new Container { From 755588258e90883f22a89cee219d6e44373b5887 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 16:56:24 +0900 Subject: [PATCH 223/267] Update `HealthDisplay` components to use DI to attach data source --- .../Visual/Gameplay/TestSceneFailingLayer.cs | 35 ++++++++++++++++--- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 5 ++- .../TestSceneSkinEditorMultipleSkins.cs | 3 +- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 +- .../TestSceneSkinnableHealthDisplay.cs | 21 ++++++----- .../Screens/Play/HUD/DefaultHealthDisplay.cs | 2 +- osu.Game/Screens/Play/HUD/FailingLayer.cs | 11 +----- osu.Game/Screens/Play/HUD/HealthDisplay.cs | 33 ++++++++++++----- osu.Game/Screens/Play/HUD/IHealthDisplay.cs | 26 -------------- .../Play/HUD/SkinnableHealthDisplay.cs | 15 +------- osu.Game/Screens/Play/HUDOverlay.cs | 22 +----------- osu.Game/Screens/Play/Player.cs | 4 ++- osu.Game/Skinning/LegacyHealthDisplay.cs | 12 ++----- 13 files changed, 81 insertions(+), 110 deletions(-) delete mode 100644 osu.Game/Screens/Play/HUD/IHealthDisplay.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs index 5a1a9d3d87..e426726def 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; @@ -22,22 +23,30 @@ namespace osu.Game.Tests.Visual.Gameplay [SetUpSteps] public void SetUpSteps() + { + } + + private void create(HealthProcessor healthProcessor) { AddStep("create layer", () => { - Child = layer = new FailingLayer(); - layer.BindHealthProcessor(new DrainingHealthProcessor(1)); + Child = new HealthProcessorContainer(healthProcessor) + { + Child = layer = new FailingLayer() + }; + layer.ShowHealth.BindTo(showHealth); }); AddStep("show health", () => showHealth.Value = true); AddStep("enable layer", () => config.SetValue(OsuSetting.FadePlayfieldWhenHealthLow, true)); - AddUntilStep("layer is visible", () => layer.IsPresent); } [Test] public void TestLayerFading() { + create(new DrainingHealthProcessor(1)); + AddSliderStep("current health", 0.0, 1.0, 1.0, val => { if (layer != null) @@ -53,6 +62,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLayerDisabledViaConfig() { + create(new DrainingHealthProcessor(1)); + AddUntilStep("layer is visible", () => layer.IsPresent); AddStep("disable layer", () => config.SetValue(OsuSetting.FadePlayfieldWhenHealthLow, false)); AddStep("set health to 0.10", () => layer.Current.Value = 0.1); AddUntilStep("layer is not visible", () => !layer.IsPresent); @@ -61,7 +72,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLayerVisibilityWithAccumulatingProcessor() { - AddStep("bind accumulating processor", () => layer.BindHealthProcessor(new AccumulatingHealthProcessor(1))); + create(new AccumulatingHealthProcessor(1)); + AddUntilStep("layer is not visible", () => !layer.IsPresent); AddStep("set health to 0.10", () => layer.Current.Value = 0.1); AddUntilStep("layer is not visible", () => !layer.IsPresent); } @@ -69,7 +81,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLayerVisibilityWithDrainingProcessor() { - AddStep("bind accumulating processor", () => layer.BindHealthProcessor(new DrainingHealthProcessor(1))); + create(new DrainingHealthProcessor(1)); AddStep("set health to 0.10", () => layer.Current.Value = 0.1); AddWaitStep("wait for potential fade", 10); AddAssert("layer is still visible", () => layer.IsPresent); @@ -78,6 +90,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLayerVisibilityWithDifferentOptions() { + create(new DrainingHealthProcessor(1)); + AddStep("set health to 0.10", () => layer.Current.Value = 0.1); AddStep("don't show health", () => showHealth.Value = false); @@ -96,5 +110,16 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("enable FadePlayfieldWhenHealthLow", () => config.SetValue(OsuSetting.FadePlayfieldWhenHealthLow, true)); AddUntilStep("layer fade is visible", () => layer.IsPresent); } + + private class HealthProcessorContainer : Container + { + [Cached(typeof(HealthProcessor))] + private readonly HealthProcessor healthProcessor; + + public HealthProcessorContainer(HealthProcessor healthProcessor) + { + this.healthProcessor = healthProcessor; + } + } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 55c681b605..a451df026b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -23,6 +23,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Cached] private ScoreProcessor scoreProcessor = new ScoreProcessor(); + [Cached] + private HealthProcessor healthProcessor = new DrainingHealthProcessor(1); + // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; private FillFlowContainer keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().First(); @@ -143,7 +146,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("create overlay", () => { - hudOverlay = new HUDOverlay(scoreProcessor, null, null, Array.Empty()); + hudOverlay = new HUDOverlay(scoreProcessor, null, Array.Empty()); // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 086bcb19c3..270216564f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Gameplay var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap); - var hudOverlay = new HUDOverlay(scoreProcessor, null, drawableRuleset, Array.Empty()) + var hudOverlay = new HUDOverlay(scoreProcessor, drawableRuleset, Array.Empty()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -40,7 +40,6 @@ namespace osu.Game.Tests.Visual.Gameplay // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); - hudOverlay.ComboCounter.Current.Value = 1; return new Container { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 8131c77b4b..12ce20f58e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Gameplay { SetContents(() => { - hudOverlay = new HUDOverlay(scoreProcessor, null, null, Array.Empty()); + hudOverlay = new HUDOverlay(scoreProcessor, null, Array.Empty()); // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs index 5bac8582d7..f06236d0a8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs @@ -4,11 +4,13 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Gameplay @@ -19,6 +21,9 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); + [Cached] + private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); + [SetUpSteps] public void SetUpSteps() { @@ -28,8 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); AddStep(@"Reset all", delegate { - foreach (var s in healthDisplays) - s.Current.Value = 1; + healthProcessor.Health.Value = 1; }); } @@ -38,23 +42,18 @@ namespace osu.Game.Tests.Visual.Gameplay { AddRepeatStep(@"decrease hp", delegate { - foreach (var healthDisplay in healthDisplays) - healthDisplay.Current.Value -= 0.08f; + healthProcessor.Health.Value = 0.08f; }, 10); AddRepeatStep(@"increase hp without flash", delegate { - foreach (var healthDisplay in healthDisplays) - healthDisplay.Current.Value += 0.1f; + healthProcessor.Health.Value = 0.1f; }, 3); AddRepeatStep(@"increase hp with flash", delegate { - foreach (var healthDisplay in healthDisplays) - { - healthDisplay.Current.Value += 0.1f; - healthDisplay.Flash(new JudgementResult(null, new OsuJudgement())); - } + healthProcessor.Health.Value = 0.1f; + healthProcessor.ApplyResult(new JudgementResult(null, new OsuJudgement())); }, 3); } } diff --git a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs index e3cd71691d..27f81467cb 100644 --- a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Play.HUD GlowColour = colours.BlueDarker; } - public override void Flash(JudgementResult result) => Scheduler.AddOnce(flash); + protected override void Flash(JudgementResult result) => Scheduler.AddOnce(flash); private void flash() { diff --git a/osu.Game/Screens/Play/HUD/FailingLayer.cs b/osu.Game/Screens/Play/HUD/FailingLayer.cs index 847b8a53cf..e071337f34 100644 --- a/osu.Game/Screens/Play/HUD/FailingLayer.cs +++ b/osu.Game/Screens/Play/HUD/FailingLayer.cs @@ -39,7 +39,6 @@ namespace osu.Game.Screens.Play.HUD private readonly Container boxes; private Bindable fadePlayfieldWhenHealthLow; - private HealthProcessor healthProcessor; public FailingLayer() { @@ -88,18 +87,10 @@ namespace osu.Game.Screens.Play.HUD updateState(); } - public override void BindHealthProcessor(HealthProcessor processor) - { - base.BindHealthProcessor(processor); - - healthProcessor = processor; - updateState(); - } - private void updateState() { // Don't display ever if the ruleset is not using a draining health display. - var showLayer = healthProcessor is DrainingHealthProcessor && fadePlayfieldWhenHealthLow.Value && ShowHealth.Value; + var showLayer = HealthProcessor is DrainingHealthProcessor && fadePlayfieldWhenHealthLow.Value && ShowHealth.Value; this.FadeTo(showLayer ? 1 : 0, fade_time, Easing.OutQuint); } diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index 5c43e00192..2292f64989 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.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.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; @@ -11,26 +12,42 @@ namespace osu.Game.Screens.Play.HUD { /// /// A container for components displaying the current player health. - /// Gets bound automatically to the when inserted to hierarchy. + /// Gets bound automatically to the when inserted to hierarchy. /// - public abstract class HealthDisplay : Container, IHealthDisplay + public abstract class HealthDisplay : Container { + [Resolved] + protected HealthProcessor HealthProcessor { get; private set; } + public Bindable Current { get; } = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; - public virtual void Flash(JudgementResult result) + protected virtual void Flash(JudgementResult result) { } - /// - /// Bind the tracked fields of to this health display. - /// - public virtual void BindHealthProcessor(HealthProcessor processor) + [BackgroundDependencyLoader] + private void load() { - Current.BindTo(processor.Health); + Current.BindTo(HealthProcessor.Health); + + HealthProcessor.NewJudgement += onNewJudgement; + } + + private void onNewJudgement(JudgementResult judgement) + { + if (judgement.IsHit && judgement.Type != HitResult.IgnoreHit) Flash(judgement); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (HealthProcessor != null) + HealthProcessor.NewJudgement -= onNewJudgement; } } } diff --git a/osu.Game/Screens/Play/HUD/IHealthDisplay.cs b/osu.Game/Screens/Play/HUD/IHealthDisplay.cs deleted file mode 100644 index b1a64bd844..0000000000 --- a/osu.Game/Screens/Play/HUD/IHealthDisplay.cs +++ /dev/null @@ -1,26 +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 osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Judgements; - -namespace osu.Game.Screens.Play.HUD -{ - /// - /// An interface providing a set of methods to update a health display. - /// - public interface IHealthDisplay : IDrawable - { - /// - /// The current health to be displayed. - /// - Bindable Current { get; } - - /// - /// Flash the display for a specified result type. - /// - /// The result type. - void Flash(JudgementResult result); - } -} diff --git a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs index 1f91f5e50f..ef0affa417 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs @@ -3,13 +3,12 @@ using System; using osu.Framework.Bindables; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public class SkinnableHealthDisplay : SkinnableDrawable, IHealthDisplay + public class SkinnableHealthDisplay : SkinnableDrawable { public Bindable Current { get; } = new BindableDouble(1) { @@ -17,8 +16,6 @@ namespace osu.Game.Screens.Play.HUD MaxValue = 1 }; - public void Flash(JudgementResult result) => skinnedCounter?.Flash(result); - private HealthProcessor processor; public void BindHealthProcessor(HealthProcessor processor) @@ -36,15 +33,5 @@ namespace osu.Game.Screens.Play.HUD { CentreComponent = false; } - - private IHealthDisplay skinnedCounter; - - protected override void SkinChanged(ISkinSource skin, bool allowFallback) - { - base.SkinChanged(skin, allowFallback); - - skinnedCounter = Drawable as IHealthDisplay; - skinnedCounter?.Current.BindTo(Current); - } } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 83897c5167..31a6bc7678 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -47,7 +47,6 @@ namespace osu.Game.Screens.Play public Bindable ShowHealthbar = new Bindable(true); private readonly ScoreProcessor scoreProcessor; - private readonly HealthProcessor healthProcessor; private readonly DrawableRuleset drawableRuleset; private readonly IReadOnlyList mods; @@ -75,10 +74,9 @@ namespace osu.Game.Screens.Play private IEnumerable hideTargets => new Drawable[] { visibilityContainer, KeyCounter, topRightElements }; - public HUDOverlay(ScoreProcessor scoreProcessor, HealthProcessor healthProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) + public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) { this.scoreProcessor = scoreProcessor; - this.healthProcessor = healthProcessor; this.drawableRuleset = drawableRuleset; this.mods = mods; @@ -161,9 +159,6 @@ namespace osu.Game.Screens.Play if (scoreProcessor != null) BindScoreProcessor(scoreProcessor); - if (healthProcessor != null) - BindHealthProcessor(healthProcessor); - if (drawableRuleset != null) { BindDrawableRuleset(drawableRuleset); @@ -322,21 +317,6 @@ namespace osu.Game.Screens.Play { ScoreCounter?.Current.BindTo(processor.TotalScore); AccuracyCounter?.Current.BindTo(processor.Accuracy); - - if (HealthDisplay is IHealthDisplay shd) - { - processor.NewJudgement += judgement => - { - if (judgement.IsHit && judgement.Type != HitResult.IgnoreHit) - shd.Flash(judgement); - }; - } - } - - protected virtual void BindHealthProcessor(HealthProcessor processor) - { - HealthDisplay?.BindHealthProcessor(processor); - FailingLayer?.BindHealthProcessor(processor); } public bool OnPressed(GlobalAction action) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 951ce334f6..1538899281 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -208,6 +208,8 @@ namespace osu.Game.Screens.Play HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); + dependencies.CacheAs(HealthProcessor); + if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); @@ -343,7 +345,7 @@ namespace osu.Game.Screens.Play // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(), - HUDOverlay = new HUDOverlay(ScoreProcessor, HealthProcessor, DrawableRuleset, Mods.Value) + HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, Mods.Value) { HoldToQuit = { diff --git a/osu.Game/Skinning/LegacyHealthDisplay.cs b/osu.Game/Skinning/LegacyHealthDisplay.cs index 2e29abf453..c1979efbc2 100644 --- a/osu.Game/Skinning/LegacyHealthDisplay.cs +++ b/osu.Game/Skinning/LegacyHealthDisplay.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Skinning { - public class LegacyHealthDisplay : CompositeDrawable, IHealthDisplay, ISkinnableComponent + public class LegacyHealthDisplay : HealthDisplay { private const double epic_cutoff = 0.5; @@ -28,12 +28,6 @@ namespace osu.Game.Skinning private bool isNewStyle; - public Bindable Current { get; } = new BindableDouble(1) - { - MinValue = 0, - MaxValue = 1 - }; - public LegacyHealthDisplay(Skin skin) { this.skin = skin; @@ -83,7 +77,7 @@ namespace osu.Game.Skinning marker.Position = fill.Position + new Vector2(fill.DrawWidth, isNewStyle ? fill.DrawHeight / 2 : 0); } - public void Flash(JudgementResult result) => marker.Flash(result); + protected override void Flash(JudgementResult result) => marker.Flash(result); private static Texture getTexture(Skin skin, string name) => skin.GetTexture($"scorebar-{name}"); @@ -254,7 +248,7 @@ namespace osu.Game.Skinning Main.ScaleTo(1.4f).Then().ScaleTo(1, 200, Easing.Out); } - public class LegacyHealthPiece : CompositeDrawable, IHealthDisplay + public class LegacyHealthPiece : CompositeDrawable { public Bindable Current { get; } = new Bindable(); From 84a4ff333eec332a3c5dbd9b167f15b17fc6db7a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 17:10:31 +0900 Subject: [PATCH 224/267] Update skin editor test scene to cache a `ScoreProcessor` --- .../Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 270216564f..d50d4aa920 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; @@ -17,6 +18,9 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneSkinEditorMultipleSkins : SkinnableTestScene { + [Cached] + private readonly ScoreProcessor scoreProcessor = new ScoreProcessor(); + [SetUpSteps] public void SetUpSteps() { @@ -28,8 +32,6 @@ namespace osu.Game.Tests.Visual.Gameplay var working = CreateWorkingBeatmap(ruleset.RulesetInfo); var beatmap = working.GetPlayableBeatmap(ruleset.RulesetInfo); - ScoreProcessor scoreProcessor = new ScoreProcessor(); - var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap); var hudOverlay = new HUDOverlay(scoreProcessor, drawableRuleset, Array.Empty()) @@ -40,6 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); + scoreProcessor.Combo.Value = 1; return new Container { From 8e78cac05826b2e01959e3971a8043d0f53cf9df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 17:31:29 +0900 Subject: [PATCH 225/267] Fix `HealthProcessor` cached as derived type in test --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index a451df026b..accb2ba1d9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Cached] private ScoreProcessor scoreProcessor = new ScoreProcessor(); - [Cached] + [Cached(typeof(HealthProcessor))] private HealthProcessor healthProcessor = new DrainingHealthProcessor(1); // best way to check without exposing. From 6c255a05726faed8e6244ded666cee31966a5f72 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 17:47:33 +0900 Subject: [PATCH 226/267] Fix drain start time being weirdly incorrect --- osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs | 8 ++++---- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs index e426726def..99facb2731 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLayerFading() { - create(new DrainingHealthProcessor(1)); + create(new DrainingHealthProcessor(0)); AddSliderStep("current health", 0.0, 1.0, 1.0, val => { @@ -62,7 +62,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLayerDisabledViaConfig() { - create(new DrainingHealthProcessor(1)); + create(new DrainingHealthProcessor(0)); AddUntilStep("layer is visible", () => layer.IsPresent); AddStep("disable layer", () => config.SetValue(OsuSetting.FadePlayfieldWhenHealthLow, false)); AddStep("set health to 0.10", () => layer.Current.Value = 0.1); @@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLayerVisibilityWithDrainingProcessor() { - create(new DrainingHealthProcessor(1)); + create(new DrainingHealthProcessor(0)); AddStep("set health to 0.10", () => layer.Current.Value = 0.1); AddWaitStep("wait for potential fade", 10); AddAssert("layer is still visible", () => layer.IsPresent); @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestLayerVisibilityWithDifferentOptions() { - create(new DrainingHealthProcessor(1)); + create(new DrainingHealthProcessor(0)); AddStep("set health to 0.10", () => layer.Current.Value = 0.1); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index accb2ba1d9..861d4a4f7f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Gameplay private ScoreProcessor scoreProcessor = new ScoreProcessor(); [Cached(typeof(HealthProcessor))] - private HealthProcessor healthProcessor = new DrainingHealthProcessor(1); + private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; From 3044b1c432621823fb9bd25b5190b38988ff8696 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 17:47:38 +0900 Subject: [PATCH 227/267] Add missing cache rules --- .../Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs | 3 +++ .../Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 3 +++ .../Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index d50d4aa920..ac5599cc27 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -21,6 +21,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Cached] private readonly ScoreProcessor scoreProcessor = new ScoreProcessor(); + [Cached(typeof(HealthProcessor))] + private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); + [SetUpSteps] public void SetUpSteps() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 12ce20f58e..7a960a09fc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -27,6 +27,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Cached] private ScoreProcessor scoreProcessor = new ScoreProcessor(); + [Cached(typeof(HealthProcessor))] + private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); + private IEnumerable hudOverlays => CreatedDrawables.OfType(); // best way to check without exposing. diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs index f06236d0a8..2d6a6d95c7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; @@ -21,7 +22,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); - [Cached] + [Cached(typeof(HealthProcessor))] private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); [SetUpSteps] @@ -53,7 +54,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddRepeatStep(@"increase hp with flash", delegate { healthProcessor.Health.Value = 0.1f; - healthProcessor.ApplyResult(new JudgementResult(null, new OsuJudgement())); + healthProcessor.ApplyResult(new JudgementResult(new HitCircle(), new OsuJudgement())); }, 3); } } From 1cb10c2a2243bde4f0fcc85a5d6de338a34f28bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 17:27:34 +0900 Subject: [PATCH 228/267] Remove unnecessary binding logic from `HUDOverlay` --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- .../TestSceneSkinEditorMultipleSkins.cs | 2 +- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 +- osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 6 +++--- osu.Game/Screens/Play/HUDOverlay.cs | 21 ++++--------------- osu.Game/Screens/Play/Player.cs | 2 +- 6 files changed, 11 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 861d4a4f7f..b7e92a79a0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -146,7 +146,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("create overlay", () => { - hudOverlay = new HUDOverlay(scoreProcessor, null, Array.Empty()); + hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index ac5599cc27..c7c93b8892 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Gameplay var drawableRuleset = ruleset.CreateDrawableRulesetWith(beatmap); - var hudOverlay = new HUDOverlay(scoreProcessor, drawableRuleset, Array.Empty()) + var hudOverlay = new HUDOverlay(drawableRuleset, Array.Empty()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 7a960a09fc..c92e9dcfd5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.Gameplay { SetContents(() => { - hudOverlay = new HUDOverlay(scoreProcessor, null, Array.Empty()); + hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 37d10a5320..998a9fb7e7 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -22,11 +22,11 @@ namespace osu.Game.Screens.Play.HUD private readonly HitWindows hitWindows; - private readonly ScoreProcessor processor; + [Resolved] + private ScoreProcessor processor { get; set; } - public HitErrorDisplay(ScoreProcessor processor, HitWindows hitWindows) + public HitErrorDisplay(HitWindows hitWindows) { - this.processor = processor; this.hitWindows = hitWindows; RelativeSizeAxes = Axes.Both; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index fd1aea016b..22812b779f 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -14,7 +14,6 @@ using osu.Game.Input.Bindings; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play.HUD; using osuTK; @@ -39,14 +38,11 @@ namespace osu.Game.Screens.Play public readonly SkinnableHealthDisplay HealthDisplay; public readonly SongProgress Progress; public readonly ModDisplay ModDisplay; - public readonly HitErrorDisplay HitErrorDisplay; public readonly HoldForMenuButton HoldToQuit; public readonly PlayerSettingsOverlay PlayerSettingsOverlay; - public readonly FailingLayer FailingLayer; public Bindable ShowHealthbar = new Bindable(true); - private readonly ScoreProcessor scoreProcessor; private readonly DrawableRuleset drawableRuleset; private readonly IReadOnlyList mods; @@ -74,9 +70,8 @@ namespace osu.Game.Screens.Play private IEnumerable hideTargets => new Drawable[] { visibilityContainer, KeyCounter, topRightElements }; - public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, IReadOnlyList mods) + public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList mods) { - this.scoreProcessor = scoreProcessor; this.drawableRuleset = drawableRuleset; this.mods = mods; @@ -84,7 +79,7 @@ namespace osu.Game.Screens.Play Children = new Drawable[] { - FailingLayer = CreateFailingLayer(), + CreateFailingLayer(), visibilityContainer = new Container { RelativeSizeAxes = Axes.Both, @@ -104,7 +99,7 @@ namespace osu.Game.Screens.Play AccuracyCounter = CreateAccuracyCounter(), ScoreCounter = CreateScoreCounter(), CreateComboCounter(), - HitErrorDisplay = CreateHitErrorDisplayOverlay(), + CreateHitErrorDisplayOverlay(), } }, }, @@ -156,9 +151,6 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader(true)] private void load(OsuConfigManager config, NotificationOverlay notificationOverlay) { - if (scoreProcessor != null) - BindScoreProcessor(scoreProcessor); - if (drawableRuleset != null) { BindDrawableRuleset(drawableRuleset); @@ -309,15 +301,10 @@ namespace osu.Game.Screens.Play AutoSizeAxes = Axes.Both, }; - protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(scoreProcessor, drawableRuleset?.FirstAvailableHitWindows); + protected virtual HitErrorDisplay CreateHitErrorDisplayOverlay() => new HitErrorDisplay(drawableRuleset?.FirstAvailableHitWindows); protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); - protected virtual void BindScoreProcessor(ScoreProcessor processor) - { - AccuracyCounter?.Current.BindTo(processor.Accuracy); - } - public bool OnPressed(GlobalAction action) { switch (action) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 1538899281..116cf3cc99 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -345,7 +345,7 @@ namespace osu.Game.Screens.Play // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(), - HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, Mods.Value) + HUDOverlay = new HUDOverlay(DrawableRuleset, Mods.Value) { HoldToQuit = { From 111b501ced835f83a4001fc3948eb26816c08364 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 7 May 2021 18:04:38 +0900 Subject: [PATCH 229/267] Revert accidental removal of UTF-8 BOM --- osu.Game/Rulesets/Replays/AutoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index 6ce857b14b..83e85146d4 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// 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; From 9fe6e1096ab9d9264f97f52ba8ed7ae504983d0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 18:11:08 +0900 Subject: [PATCH 230/267] Remove cruft from `SkinnableHealthDisplay` --- .../Play/HUD/SkinnableHealthDisplay.cs | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs index ef0affa417..3ba6a33276 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableHealthDisplay.cs @@ -1,33 +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 System; -using osu.Framework.Bindables; -using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { public class SkinnableHealthDisplay : SkinnableDrawable { - public Bindable Current { get; } = new BindableDouble(1) - { - MinValue = 0, - MaxValue = 1 - }; - - private HealthProcessor processor; - - public void BindHealthProcessor(HealthProcessor processor) - { - if (this.processor != null) - throw new InvalidOperationException("Can't bind to a processor more than once"); - - this.processor = processor; - - Current.BindTo(processor.Health); - } - public SkinnableHealthDisplay() : base(new HUDSkinComponent(HUDSkinComponents.HealthDisplay), _ => new DefaultHealthDisplay()) { From a1aeac567710b95f27b07daede58b9a1ad56ab45 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 18:11:59 +0900 Subject: [PATCH 231/267] Remove remaining cruft from `SkinnableAccuracyCounter` --- osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs index 17c2493d2d..fcb8fca35d 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs @@ -1,15 +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.Bindables; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { public class SkinnableAccuracyCounter : SkinnableDrawable { - public Bindable Current { get; } = new Bindable(); - public SkinnableAccuracyCounter() : base(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter), _ => new DefaultAccuracyCounter()) { From 5b2f786f971ef65100be176ebc828b87e87f8c3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 May 2021 19:16:00 +0900 Subject: [PATCH 232/267] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 99cda7693d..80b1c5b52f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e448972066..29189781a7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -29,7 +29,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 43ed2d7dc8..c4eb7aefba 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 8c564a69ed1978e2e11be2d93806c57a759c5800 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Fri, 7 May 2021 20:59:20 -0400 Subject: [PATCH 233/267] Fix InvalidOperationException when exiting a map at the end --- .../Visual/Gameplay/TestSceneStoryboardWithOutro.cs | 10 ++++++++++ osu.Game/Screens/Play/Player.cs | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 4138a81ebd..e1dc6e3b42 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -133,6 +133,16 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration); } + [Test] + public void TestPerformExitNoOutro() + { + CreateTest(null); + AddStep("disable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, false)); + AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + AddStep("exit via pause", () => Player.ExitViaPause()); + AddAssert("score shown", () => Player.IsScoreShown); + } + protected override bool AllowFail => true; protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 88e617245b..0a2f9f0d18 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -542,7 +542,11 @@ 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) + { + completionProgressDelegate?.Cancel(); + completionProgressDelegate = null; updateCompletionState(true); + } } this.Exit(); From df630d94282250064ba396d06b518b3ab369447d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 8 May 2021 14:53:19 +0200 Subject: [PATCH 234/267] Trim redundant `this` qualifier --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 32d2fba25e..d57acd005b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)), }; - public override Vector2 ScreenSpaceSelectionPoint => this.ToScreenSpace(slider.HitObject.StackedPosition); + public override Vector2 ScreenSpaceSelectionPoint => ToScreenSpace(slider.HitObject.StackedPosition); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => slider.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos)) == true; From 63e267a3beefbb0c7344521af93d1a340a5a454c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 8 May 2021 23:32:52 +0900 Subject: [PATCH 235/267] Revert "Trim redundant `this` qualifier" This reverts commit df630d94282250064ba396d06b518b3ab369447d. --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index d57acd005b..32d2fba25e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)), }; - public override Vector2 ScreenSpaceSelectionPoint => ToScreenSpace(slider.HitObject.StackedPosition); + public override Vector2 ScreenSpaceSelectionPoint => this.ToScreenSpace(slider.HitObject.StackedPosition); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => slider.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos)) == true; From 01d732bb65202f66737d478457d62f1af1cd1884 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 8 May 2021 23:33:03 +0900 Subject: [PATCH 236/267] Revert "Refactor `SliderSelectionBlueprint` to not reference blueprint pieces for input handling" This reverts commit 54fe10c82a855a16c88f8781a9ae12dc42df7b0e. --- .../Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs | 6 ++++++ .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index ece9c7a757..6e22c35ab3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -26,6 +26,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { AccentColour = Color4.Transparent }; + + // SliderSelectionBlueprint relies on calling ReceivePositionalInputAt on this drawable to determine whether selection should occur. + // Without AlwaysPresent, a movement in a parent container (ie. the editor composer area resizing) could cause incorrect input handling. + AlwaysPresent = true; } [BackgroundDependencyLoader] @@ -50,5 +54,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } public void RecyclePath() => body.RecyclePath(); + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => body.ReceivePositionalInputAt(screenSpacePos); } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 32d2fba25e..88fcb1e715 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -240,10 +240,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)), }; - public override Vector2 ScreenSpaceSelectionPoint => this.ToScreenSpace(slider.HitObject.StackedPosition); + public override Vector2 ScreenSpaceSelectionPoint => BodyPiece.ToScreenSpace(BodyPiece.PathStartLocation); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => - slider.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos)) == true; + BodyPiece.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos)) == true; protected virtual SliderCircleSelectionBlueprint CreateCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position) => new SliderCircleSelectionBlueprint(slider, position); } From fe86ee629ed8b7a7a36eb7048064192cf9584672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 8 May 2021 16:30:08 +0200 Subject: [PATCH 237/267] Fix temp files from beatmap listing imports not being cleaned up As reported in #12718, it turns out that temporary files from beatmap set downloads performed via the beatmap listing overlay could remain in the user's filesystem even after the download has concluded. The reason for the issue is a failure in component integration. In the case of online downloads, files are first downloaded to a temporary directory (`C:/Temp` or `/tmp`), with a randomly generated filename, which ends in an extension of `.tmp`. On the other side, `ArchiveModelManager`s have a `ShouldDeleteArchive()` method, which determines whether a file should be deleted after importing. At the time of writing, in the case of beatmap imports the file is only automatically cleaned up if the extension of the file is equal to `.osz`, which was not the case for temporary files. As it turns out, `APIDownloadRequest` has a facility for adjusting the file's extension, via the protected `FileExtension` property. Therefore, use it in the case of `DownloadBeatmapSetRequest` to specify `.osz`, which then will make sure that the `ShouldDeleteArchive()` check in `BeatmapManager` picks it up for clean-up. --- osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index e8871bef05..2898955de7 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -23,6 +23,8 @@ namespace osu.Game.Online.API.Requests return req; } + protected override string FileExtension => ".osz"; + protected override string Target => $@"beatmapsets/{Model.OnlineBeatmapSetID}/download{(noVideo ? "?noVideo=1" : "")}"; } } From 25312b3e88d47b2cbc9ce327d2c6d05954b39d72 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 8 May 2021 11:45:31 -0400 Subject: [PATCH 238/267] Don't restart completion delegate on exit, revert exit behavior to lazer --- .../Visual/Gameplay/TestSceneStoryboardWithOutro.cs | 2 +- osu.Game/Screens/Play/Player.cs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index e1dc6e3b42..70b1d3ef85 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -140,7 +140,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("disable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, false)); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("exit via pause", () => Player.ExitViaPause()); - AddAssert("score shown", () => Player.IsScoreShown); + AddAssert("score not shown", () => !Player.IsScoreShown); } protected override bool AllowFail => true; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0a2f9f0d18..557dd2a78a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -541,10 +541,8 @@ 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) + if (prepareScoreForDisplayTask != null && completionProgressDelegate == null) { - completionProgressDelegate?.Cancel(); - completionProgressDelegate = null; updateCompletionState(true); } } From c3bf6a0287c16682e71a750728c40cfc2a99b06f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 8 May 2021 21:01:37 +0200 Subject: [PATCH 239/267] Remove weird vestigial `Current` reimplementation Has no functional purpose anymore since the changes in the HUD element data binding flow. --- osu.Game/Skinning/LegacyScoreCounter.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Skinning/LegacyScoreCounter.cs b/osu.Game/Skinning/LegacyScoreCounter.cs index 21112aa107..ecb907e601 100644 --- a/osu.Game/Skinning/LegacyScoreCounter.cs +++ b/osu.Game/Skinning/LegacyScoreCounter.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.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Play.HUD; @@ -16,8 +15,6 @@ namespace osu.Game.Skinning protected override double RollingDuration => 1000; protected override Easing RollingEasing => Easing.Out; - public new Bindable Current { get; } = new Bindable(); - public LegacyScoreCounter(ISkin skin) : base(6) { @@ -26,9 +23,6 @@ namespace osu.Game.Skinning this.skin = skin; - // base class uses int for display, but externally we bind to ScoreProcessor as a double for now. - Current.BindValueChanged(v => base.Current.Value = (int)v.NewValue); - Scale = new Vector2(0.96f); Margin = new MarginPadding(10); } From efb9164658a127093cf39672466bafbb89268e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 8 May 2021 21:35:12 +0200 Subject: [PATCH 240/267] Restore previous test scene logic --- .../Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs index 34356184a2..6a8a2187f9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs @@ -1,8 +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.Collections.Generic; -using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Testing; @@ -15,8 +13,6 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneSkinnableAccuracyCounter : SkinnableTestScene { - private IEnumerable accuracyCounters => CreatedDrawables.OfType(); - protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); [Cached] @@ -25,7 +21,8 @@ namespace osu.Game.Tests.Visual.Gameplay [SetUpSteps] public void SetUpSteps() { - AddStep("Create combo counters", () => SetContents(() => new SkinnableAccuracyCounter())); + AddStep("Set initial accuracy", () => scoreProcessor.Accuracy.Value = 1); + AddStep("Create accuracy counters", () => SetContents(() => new SkinnableAccuracyCounter())); } [Test] @@ -33,7 +30,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep(@"Reset all", () => scoreProcessor.Accuracy.Value = 1); - AddStep(@"Hit! :D", () => scoreProcessor.Accuracy.Value -= 0.23); + AddStep(@"Miss :(", () => scoreProcessor.Accuracy.Value -= 0.023); } } } From 67cea6e762f8dd2ff0e886bc2fc1ea6c79c56ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 8 May 2021 21:38:03 +0200 Subject: [PATCH 241/267] Remove explicit binding to accuracy counter from overlay --- osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs | 3 --- osu.Game/Screens/Play/HUDOverlay.cs | 2 -- 2 files changed, 5 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs index 17c2493d2d..fcb8fca35d 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableAccuracyCounter.cs @@ -1,15 +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.Bindables; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { public class SkinnableAccuracyCounter : SkinnableDrawable { - public Bindable Current { get; } = new Bindable(); - public SkinnableAccuracyCounter() : base(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter), _ => new DefaultAccuracyCounter()) { diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index c887fb78e0..e9b376c433 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -320,8 +320,6 @@ namespace osu.Game.Screens.Play protected virtual void BindScoreProcessor(ScoreProcessor processor) { - AccuracyCounter?.Current.BindTo(processor.Accuracy); - if (HealthDisplay is IHealthDisplay shd) { processor.NewJudgement += judgement => From 342c5a5938253c961bfc97d2e1239f74ba20f4d9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 9 May 2021 04:49:40 +0300 Subject: [PATCH 242/267] Add tests to indicate the issue --- .../Visual/Online/TestSceneNewsOverlay.cs | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 6ebe8fcc07..f10b385c61 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -2,7 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -14,21 +17,34 @@ namespace osu.Game.Tests.Visual.Online { private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; - private NewsOverlay news; + private NewsOverlay overlay; [SetUp] - public void SetUp() => Schedule(() => Child = news = new NewsOverlay()); + public void SetUp() => Schedule(() => Child = overlay = new NewsOverlay()); [Test] public void TestRequest() { setUpNewsResponse(responseExample); - AddStep("Show", () => news.Show()); - AddStep("Show article", () => news.ShowArticle("article")); + AddStep("Show", () => overlay.Show()); + AddStep("Show article", () => overlay.ShowArticle("article")); } - private void setUpNewsResponse(GetNewsResponse r) - => AddStep("set up response", () => + [Test] + public void TestCursorRequest() + { + setUpNewsResponse(responseWithCursor, "Set up cursor response"); + AddStep("Show", () => overlay.Show()); + AddAssert("Show More button is visible", () => showMoreButton.Alpha == 1); + setUpNewsResponse(responseWithNoCursor, "Set up no cursor response"); + AddStep("Click Show More", () => showMoreButton.Click()); + AddAssert("Show More button is hidden", () => showMoreButton.Alpha == 0); + } + + private ShowMoreButton showMoreButton => overlay.ChildrenOfType().First(); + + private void setUpNewsResponse(GetNewsResponse r, string testName = "Set up response") + => AddStep(testName, () => { dummyAPI.HandleRequest = request => { @@ -40,7 +56,7 @@ namespace osu.Game.Tests.Visual.Online }; }); - private GetNewsResponse responseExample => new GetNewsResponse + private static GetNewsResponse responseExample => new GetNewsResponse { NewsPosts = new[] { @@ -62,5 +78,37 @@ namespace osu.Game.Tests.Visual.Online } } }; + + private static GetNewsResponse responseWithCursor => new GetNewsResponse + { + NewsPosts = new[] + { + new APINewsPost + { + Title = "This post has an image which starts with \"/\" and has many authors!", + Preview = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + Author = "someone, someone1, someone2, someone3, someone4", + FirstImage = "/help/wiki/shared/news/banners/monthly-beatmapping-contest.png", + PublishedAt = DateTimeOffset.Now + } + }, + Cursor = new Cursor() + }; + + private static GetNewsResponse responseWithNoCursor => new GetNewsResponse + { + NewsPosts = new[] + { + new APINewsPost + { + Title = "This post has a full-url image! (HTML entity: &)", + Preview = "boom (HTML entity: &)", + Author = "user (HTML entity: &)", + FirstImage = "https://assets.ppy.sh/artists/88/header.jpg", + PublishedAt = DateTimeOffset.Now + } + }, + Cursor = null + }; } } From dde9fd28e6872e2afe41670861ffb7ec510b74b9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 9 May 2021 04:57:24 +0300 Subject: [PATCH 243/267] Hide ShowMore button if there's nothing to load --- osu.Game/Overlays/News/Displays/FrontPageDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/News/Displays/FrontPageDisplay.cs b/osu.Game/Overlays/News/Displays/FrontPageDisplay.cs index 0f177f151a..a1bc6c650b 100644 --- a/osu.Game/Overlays/News/Displays/FrontPageDisplay.cs +++ b/osu.Game/Overlays/News/Displays/FrontPageDisplay.cs @@ -100,7 +100,7 @@ namespace osu.Game.Overlays.News.Displays { content.Add(loaded); showMore.IsLoading = false; - showMore.Show(); + showMore.Alpha = lastCursor == null ? 0 : 1; }, (cancellationToken = new CancellationTokenSource()).Token); } From ae2b5a0806c3b0cad6dba614f1273d9d121cf0f6 Mon Sep 17 00:00:00 2001 From: Christine Chen Date: Sat, 8 May 2021 22:42:14 -0400 Subject: [PATCH 244/267] Actually test that player was exited --- 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 70b1d3ef85..0ac8e01482 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -140,7 +140,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("disable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, false)); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("exit via pause", () => Player.ExitViaPause()); - AddAssert("score not shown", () => !Player.IsScoreShown); + AddAssert("player exited", () => Stack.CurrentScreen == null); } protected override bool AllowFail => true; From 0818deac17110c65ae22005c5616c55e67913847 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 9 May 2021 06:06:34 +0300 Subject: [PATCH 245/267] Fix potential test scene failure due to showMoreButton not being loaded in time --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index f10b385c61..46454879da 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -35,6 +35,7 @@ namespace osu.Game.Tests.Visual.Online { setUpNewsResponse(responseWithCursor, "Set up cursor response"); AddStep("Show", () => overlay.Show()); + AddUntilStep("Show more button is ready", () => showMoreButton != null); AddAssert("Show More button is visible", () => showMoreButton.Alpha == 1); setUpNewsResponse(responseWithNoCursor, "Set up no cursor response"); AddStep("Click Show More", () => showMoreButton.Click()); From 8868439ce46b042b2eae1bd7fc48614ac30d9197 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 9 May 2021 06:49:12 +0300 Subject: [PATCH 246/267] Another approach to fix test scene failure --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 46454879da..0be09d1fcc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -36,10 +36,10 @@ namespace osu.Game.Tests.Visual.Online setUpNewsResponse(responseWithCursor, "Set up cursor response"); AddStep("Show", () => overlay.Show()); AddUntilStep("Show more button is ready", () => showMoreButton != null); - AddAssert("Show More button is visible", () => showMoreButton.Alpha == 1); + AddAssert("Show More button is visible", () => showMoreButton?.Alpha == 1); setUpNewsResponse(responseWithNoCursor, "Set up no cursor response"); - AddStep("Click Show More", () => showMoreButton.Click()); - AddAssert("Show More button is hidden", () => showMoreButton.Alpha == 0); + AddStep("Click Show More", () => showMoreButton?.Click()); + AddAssert("Show More button is hidden", () => showMoreButton?.Alpha == 0); } private ShowMoreButton showMoreButton => overlay.ChildrenOfType().First(); From f0c1784d05a56dea2082473ca02063c1721bdad1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 9 May 2021 09:12:37 +0300 Subject: [PATCH 247/267] Use FirstOrDefault instead of First --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 0be09d1fcc..ba692a7769 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Show More button is hidden", () => showMoreButton?.Alpha == 0); } - private ShowMoreButton showMoreButton => overlay.ChildrenOfType().First(); + private ShowMoreButton showMoreButton => overlay.ChildrenOfType().FirstOrDefault(); private void setUpNewsResponse(GetNewsResponse r, string testName = "Set up response") => AddStep(testName, () => From 879c08e6667024694dde3b8bb095b00185a3f3c3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 9 May 2021 10:06:36 +0300 Subject: [PATCH 248/267] Use UntilStep instead of Assert to check button visibility --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index ba692a7769..93a5b6fc59 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -35,11 +35,10 @@ namespace osu.Game.Tests.Visual.Online { setUpNewsResponse(responseWithCursor, "Set up cursor response"); AddStep("Show", () => overlay.Show()); - AddUntilStep("Show more button is ready", () => showMoreButton != null); - AddAssert("Show More button is visible", () => showMoreButton?.Alpha == 1); + AddUntilStep("Show More button is visible", () => showMoreButton?.Alpha == 1); setUpNewsResponse(responseWithNoCursor, "Set up no cursor response"); AddStep("Click Show More", () => showMoreButton?.Click()); - AddAssert("Show More button is hidden", () => showMoreButton?.Alpha == 0); + AddUntilStep("Show More button is hidden", () => showMoreButton?.Alpha == 0); } private ShowMoreButton showMoreButton => overlay.ChildrenOfType().FirstOrDefault(); From 8964d51de984f3089f5016d184e58b5ba222654e Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 9 May 2021 14:10:38 -0700 Subject: [PATCH 249/267] Add ability to sort by source in song select --- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 1 + osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 3 +++ osu.Game/Screens/Select/Filter/SortMode.cs | 5 ++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 5731b1ac2c..643f4131dc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -304,6 +304,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"Sort by BPM", () => config.SetValue(OsuSetting.SongSelectSortingMode, SortMode.BPM)); AddStep(@"Sort by Length", () => config.SetValue(OsuSetting.SongSelectSortingMode, SortMode.Length)); AddStep(@"Sort by Difficulty", () => config.SetValue(OsuSetting.SongSelectSortingMode, SortMode.Difficulty)); + AddStep(@"Sort by Source", () => config.SetValue(OsuSetting.SongSelectSortingMode, SortMode.Source)); } [Test] diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index bf045ed612..635f1d8e1e 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -82,6 +82,9 @@ namespace osu.Game.Screens.Select.Carousel case SortMode.Difficulty: return compareUsingAggregateMax(otherSet, b => b.StarDifficulty); + + case SortMode.Source: + return string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.OrdinalIgnoreCase); } } diff --git a/osu.Game/Screens/Select/Filter/SortMode.cs b/osu.Game/Screens/Select/Filter/SortMode.cs index be76fbc3ba..db0e6812b8 100644 --- a/osu.Game/Screens/Select/Filter/SortMode.cs +++ b/osu.Game/Screens/Select/Filter/SortMode.cs @@ -29,6 +29,9 @@ namespace osu.Game.Screens.Select.Filter RankAchieved, [Description("Title")] - Title + Title, + + [Description("Source")] + Source, } } From a21718f1cd89139f684835de8d2dd7d432da2de6 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 9 May 2021 14:26:45 -0700 Subject: [PATCH 250/267] Move source case to a better spot --- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 635f1d8e1e..00c2c2cb4a 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -71,6 +71,9 @@ namespace osu.Game.Screens.Select.Carousel case SortMode.Author: return string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.OrdinalIgnoreCase); + case SortMode.Source: + return string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.OrdinalIgnoreCase); + case SortMode.DateAdded: return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); @@ -82,9 +85,6 @@ namespace osu.Game.Screens.Select.Carousel case SortMode.Difficulty: return compareUsingAggregateMax(otherSet, b => b.StarDifficulty); - - case SortMode.Source: - return string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.OrdinalIgnoreCase); } } From a71e52da4caf53c88b772263d4b7fb89090a34ec Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 9 May 2021 15:39:59 -0700 Subject: [PATCH 251/267] Fix enum ordering after adding source --- osu.Game/Screens/Select/Filter/SortMode.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Filter/SortMode.cs b/osu.Game/Screens/Select/Filter/SortMode.cs index db0e6812b8..18c5d713e1 100644 --- a/osu.Game/Screens/Select/Filter/SortMode.cs +++ b/osu.Game/Screens/Select/Filter/SortMode.cs @@ -28,10 +28,10 @@ namespace osu.Game.Screens.Select.Filter [Description("Rank Achieved")] RankAchieved, - [Description("Title")] - Title, - [Description("Source")] Source, + + [Description("Title")] + Title, } } From ab6239fd5f4545077162a2adec8352c789426cf0 Mon Sep 17 00:00:00 2001 From: Susko3 <16479013+Susko3@users.noreply.github.com> Date: Mon, 10 May 2021 00:51:58 +0200 Subject: [PATCH 252/267] change math for displaying volume "MAX" --- osu.Game/Overlays/Volume/VolumeMeter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index f1f21bec49..a15076581e 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -204,7 +204,7 @@ namespace osu.Game.Overlays.Volume { displayVolume = value; - if (displayVolume > 0.99f) + if (displayVolume >= 0.995f) { text.Text = "MAX"; maxGlow.EffectColour = meterColour.Opacity(2f); From 132bb7832d31e2c30719c65dd4da18d8fbbc2691 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 12:06:33 +0900 Subject: [PATCH 253/267] Fix some regressions when updating test scenes --- .../Visual/Gameplay/TestSceneFailingLayer.cs | 7 ++----- .../Gameplay/TestSceneSkinnableHealthDisplay.cs | 11 +++++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs index 99facb2731..ebc431a78b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Configuration; @@ -21,17 +22,13 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private OsuConfigManager config { get; set; } - [SetUpSteps] - public void SetUpSteps() - { - } - private void create(HealthProcessor healthProcessor) { AddStep("create layer", () => { Child = new HealthProcessorContainer(healthProcessor) { + RelativeSizeAxes = Axes.Both, Child = layer = new FailingLayer() }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs index 2d6a6d95c7..4f50613416 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs @@ -43,18 +43,21 @@ namespace osu.Game.Tests.Visual.Gameplay { AddRepeatStep(@"decrease hp", delegate { - healthProcessor.Health.Value = 0.08f; + healthProcessor.Health.Value -= 0.08f; }, 10); AddRepeatStep(@"increase hp without flash", delegate { - healthProcessor.Health.Value = 0.1f; + healthProcessor.Health.Value += 0.1f; }, 3); AddRepeatStep(@"increase hp with flash", delegate { - healthProcessor.Health.Value = 0.1f; - healthProcessor.ApplyResult(new JudgementResult(new HitCircle(), new OsuJudgement())); + healthProcessor.Health.Value += 0.1f; + healthProcessor.ApplyResult(new JudgementResult(new HitCircle(), new OsuJudgement()) + { + Type = HitResult.Perfect + }); }, 3); } } From 1bbbe8042099a5b1c3b659b1b899e2970651425c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 12:20:22 +0900 Subject: [PATCH 254/267] Fix missing instances of `HealthProcessor` caching --- .../Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs | 1 + osu.Game/Screens/Play/Player.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 7c65601d50..ac5599cc27 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -18,6 +18,7 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneSkinEditorMultipleSkins : SkinnableTestScene { + [Cached] private readonly ScoreProcessor scoreProcessor = new ScoreProcessor(); [Cached(typeof(HealthProcessor))] diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 396a9f841d..ba34ed4750 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -208,6 +208,8 @@ namespace osu.Game.Screens.Play HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); + dependencies.CacheAs(HealthProcessor); + if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); From 1d38fa29b5a853a2be449ff00e3732359b0fbe00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 12:23:04 +0900 Subject: [PATCH 255/267] Remove unused using statement --- osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs index ebc431a78b..fb4c9d713a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; From 35a7226cd82120207014a652567a5e87febc25e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 May 2021 13:41:04 +0900 Subject: [PATCH 256/267] Add newline --- osu.Game/Screens/Play/HUD/HealthDisplay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index 2292f64989..6c2571cc28 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.cs @@ -39,7 +39,8 @@ namespace osu.Game.Screens.Play.HUD private void onNewJudgement(JudgementResult judgement) { - if (judgement.IsHit && judgement.Type != HitResult.IgnoreHit) Flash(judgement); + if (judgement.IsHit && judgement.Type != HitResult.IgnoreHit) + Flash(judgement); } protected override void Dispose(bool isDisposing) From 332cb74cad9f3adf3934432c344ce275be3405ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 May 2021 13:58:13 +0900 Subject: [PATCH 257/267] Fix toolbar queuing ruleset sounds --- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index eb235632e8..9ca105ee7f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -69,13 +69,15 @@ namespace osu.Game.Overlays.Toolbar base.LoadComplete(); Current.BindDisabledChanged(disabled => this.FadeColour(disabled ? Color4.Gray : Color4.White, 300), true); - Current.BindValueChanged(_ => moveLineToCurrent(), true); + Current.BindValueChanged(_ => moveLineToCurrent()); + + // Scheduled to allow the button flow layout to be computed before the line position is updated + ScheduleAfterChildren(moveLineToCurrent); } private bool hasInitialPosition; - // Scheduled to allow the flow layout to be computed before the line position is updated - private void moveLineToCurrent() => ScheduleAfterChildren(() => + private void moveLineToCurrent() { if (SelectedTab != null) { @@ -86,7 +88,7 @@ namespace osu.Game.Overlays.Toolbar hasInitialPosition = true; } - }); + } public override bool HandleNonPositionalInput => !Current.Disabled && base.HandleNonPositionalInput; From 97e72849af46241de4acbe4e955c5e6a72db9434 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 15:19:27 +0900 Subject: [PATCH 258/267] Fix regressed `HitErrorDisplay` behaviour (and localise binding to meter implementations) --- .../Visual/Gameplay/TestSceneHitErrorMeter.cs | 39 +++++++------------ osu.Game/Screens/Play/HUD/HitErrorDisplay.cs | 24 ------------ .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 2 +- .../HUD/HitErrorMeters/ColourHitErrorMeter.cs | 2 +- .../Play/HUD/HitErrorMeters/HitErrorMeter.cs | 29 +++++++++++++- 5 files changed, 45 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index 1021ac3760..6cefd01aab 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -2,15 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; -using osu.Game.Rulesets.Judgements; -using osu.Framework.Utils; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; +using osu.Framework.Utils; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Catch.Scoring; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Scoring; -using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Scoring; @@ -20,14 +21,11 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneHitErrorMeter : OsuTestScene { - private BarHitErrorMeter barMeter; - private BarHitErrorMeter barMeter2; - private BarHitErrorMeter barMeter3; - private ColourHitErrorMeter colourMeter; - private ColourHitErrorMeter colourMeter2; - private ColourHitErrorMeter colourMeter3; private HitWindows hitWindows; + [Cached] + private ScoreProcessor scoreProcessor = new ScoreProcessor(); + public TestSceneHitErrorMeter() { recreateDisplay(new OsuHitWindows(), 5); @@ -105,40 +103,40 @@ namespace osu.Game.Tests.Visual.Gameplay } }); - Add(barMeter = new BarHitErrorMeter(hitWindows, true) + Add(new BarHitErrorMeter(hitWindows, true) { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, }); - Add(barMeter2 = new BarHitErrorMeter(hitWindows, false) + Add(new BarHitErrorMeter(hitWindows, false) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }); - Add(barMeter3 = new BarHitErrorMeter(hitWindows, true) + Add(new BarHitErrorMeter(hitWindows, true) { Anchor = Anchor.BottomCentre, Origin = Anchor.CentreLeft, Rotation = 270, }); - Add(colourMeter = new ColourHitErrorMeter(hitWindows) + Add(new ColourHitErrorMeter(hitWindows) { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Margin = new MarginPadding { Right = 50 } }); - Add(colourMeter2 = new ColourHitErrorMeter(hitWindows) + Add(new ColourHitErrorMeter(hitWindows) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Margin = new MarginPadding { Left = 50 } }); - Add(colourMeter3 = new ColourHitErrorMeter(hitWindows) + Add(new ColourHitErrorMeter(hitWindows) { Anchor = Anchor.BottomCentre, Origin = Anchor.CentreLeft, @@ -149,18 +147,11 @@ namespace osu.Game.Tests.Visual.Gameplay private void newJudgement(double offset = 0) { - var judgement = new JudgementResult(new HitObject(), new Judgement()) + scoreProcessor.ApplyResult(new JudgementResult(new HitCircle { HitWindows = hitWindows }, new Judgement()) { TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset, Type = HitResult.Perfect, - }; - - barMeter.OnNewJudgement(judgement); - barMeter2.OnNewJudgement(judgement); - barMeter3.OnNewJudgement(judgement); - colourMeter.OnNewJudgement(judgement); - colourMeter2.OnNewJudgement(judgement); - colourMeter3.OnNewJudgement(judgement); + }); } } } diff --git a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs index 998a9fb7e7..a24d9c10cb 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorDisplay.cs @@ -7,7 +7,6 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD.HitErrorMeters; @@ -22,17 +21,11 @@ namespace osu.Game.Screens.Play.HUD private readonly HitWindows hitWindows; - [Resolved] - private ScoreProcessor processor { get; set; } - public HitErrorDisplay(HitWindows hitWindows) { this.hitWindows = hitWindows; RelativeSizeAxes = Axes.Both; - - if (processor != null) - processor.NewJudgement += onNewJudgement; } [BackgroundDependencyLoader] @@ -47,15 +40,6 @@ namespace osu.Game.Screens.Play.HUD type.BindValueChanged(typeChanged, true); } - private void onNewJudgement(JudgementResult result) - { - if (result.HitObject.HitWindows.WindowFor(HitResult.Miss) == 0) - return; - - foreach (var c in Children) - c.OnNewJudgement(result); - } - private void typeChanged(ValueChangedEvent type) { Children.ForEach(c => c.FadeOut(fade_duration, Easing.OutQuint)); @@ -139,13 +123,5 @@ namespace osu.Game.Screens.Play.HUD Add(display); display.FadeInFromZero(fade_duration, Easing.OutQuint); } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (processor != null) - processor.NewJudgement -= onNewJudgement; - } } } diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 3b24c8cc9e..c5a21ade03 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -214,7 +214,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private const int max_concurrent_judgements = 50; - public override void OnNewJudgement(JudgementResult judgement) + protected override void OnNewJudgement(JudgementResult judgement) { if (!judgement.IsHit) return; diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 657235bfd4..465439cf19 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters InternalChild = judgementsFlow = new JudgementFlow(); } - public override void OnNewJudgement(JudgementResult judgement) => judgementsFlow.Push(GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset))); + protected override void OnNewJudgement(JudgementResult judgement) => judgementsFlow.Push(GetColourForHitResult(HitWindows.ResultFor(judgement.TimeOffset))); private class JudgementFlow : FillFlowContainer { diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs index b3edfdedec..8b53a9676d 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs @@ -14,6 +14,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { protected readonly HitWindows HitWindows; + [Resolved] + private ScoreProcessor processor { get; set; } + [Resolved] private OsuColour colours { get; set; } @@ -22,7 +25,23 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters HitWindows = hitWindows; } - public abstract void OnNewJudgement(JudgementResult judgement); + protected override void LoadComplete() + { + base.LoadComplete(); + + if (processor != null) + processor.NewJudgement += onNewJudgement; + } + + private void onNewJudgement(JudgementResult result) + { + if (result.HitObject.HitWindows?.WindowFor(HitResult.Miss) == 0) + return; + + OnNewJudgement(result); + } + + protected abstract void OnNewJudgement(JudgementResult judgement); protected Color4 GetColourForHitResult(HitResult result) { @@ -47,5 +66,13 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters return colours.BlueLight; } } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (processor != null) + processor.NewJudgement -= onNewJudgement; + } } } From fa872858b592278b7672c16fbd840825d8ac7a24 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 May 2021 16:40:06 +0900 Subject: [PATCH 259/267] Remove unnecessary check --- osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs index 8b53a9676d..37e9ea43c5 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs @@ -29,8 +29,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { base.LoadComplete(); - if (processor != null) - processor.NewJudgement += onNewJudgement; + processor.NewJudgement += onNewJudgement; } private void onNewJudgement(JudgementResult result) From bca5bee72eb22df8f9885c8962efe2a9125417fa Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 10 May 2021 19:28:32 +0700 Subject: [PATCH 260/267] remove duplicate CreateSpriteText in OsuMarkdownTextFlowContainer --- .../Containers/Markdown/OsuMarkdownTextFlowContainer.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs index 1550b8401d..c3527fa99a 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics.Sprites; using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown @@ -16,11 +15,6 @@ namespace osu.Game.Graphics.Containers.Markdown [Resolved] private OverlayColourProvider colourProvider { get; set; } - protected override SpriteText CreateSpriteText() => new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14), - }; - protected override void AddLinkText(string text, LinkInline linkInline) => AddDrawable(new OsuMarkdownLinkText(text, linkInline)); From f1aa47f6df50456892f2c7da4d4281f5e288714f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 May 2021 23:15:38 +0900 Subject: [PATCH 261/267] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 80b1c5b52f..8c24df5c2e 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 29189781a7..3eb5050e1a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -29,7 +29,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index c4eb7aefba..f00e20a66e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 7c8dd91674481b209d383cda463b423534f7722e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 May 2021 09:29:15 +0900 Subject: [PATCH 262/267] Rename test to better match tested class --- ...apDifficultyManagerTest.cs => BeatmapDifficultyCacheTest.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Beatmaps/{BeatmapDifficultyManagerTest.cs => BeatmapDifficultyCacheTest.cs} (98%) diff --git a/osu.Game.Tests/Beatmaps/BeatmapDifficultyManagerTest.cs b/osu.Game.Tests/Beatmaps/BeatmapDifficultyCacheTest.cs similarity index 98% rename from osu.Game.Tests/Beatmaps/BeatmapDifficultyManagerTest.cs rename to osu.Game.Tests/Beatmaps/BeatmapDifficultyCacheTest.cs index 70503bec7a..d407c0663f 100644 --- a/osu.Game.Tests/Beatmaps/BeatmapDifficultyManagerTest.cs +++ b/osu.Game.Tests/Beatmaps/BeatmapDifficultyCacheTest.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Osu.Mods; namespace osu.Game.Tests.Beatmaps { [TestFixture] - public class BeatmapDifficultyManagerTest + public class BeatmapDifficultyCacheTest { [Test] public void TestKeyEqualsWithDifferentModInstances() From 32f7691349dd449593a8664ac191dcb84d56a8b2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 May 2021 11:24:35 +0900 Subject: [PATCH 263/267] Fix token failure preventing base.LoadAsyncComplete() --- osu.Game/Screens/Play/SubmittingPlayer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index b64d835c58..79c1d1a274 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -33,9 +33,8 @@ namespace osu.Game.Screens.Play protected override void LoadAsyncComplete() { - if (!handleTokenRetrieval()) return; - base.LoadAsyncComplete(); + handleTokenRetrieval(); } private bool handleTokenRetrieval() From 6db9e26d48a490b6c3bf9912877bd8f22220b492 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 May 2021 11:24:55 +0900 Subject: [PATCH 264/267] Fix score submission failures with autoplay --- osu.Game/Screens/Play/SubmittingPlayer.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index 79c1d1a274..ece1a589cd 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.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 JetBrains.Annotations; using osu.Framework.Allocation; @@ -9,6 +10,7 @@ using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Online.API; using osu.Game.Online.Rooms; +using osu.Game.Rulesets.Mods; using osu.Game.Scoring; namespace osu.Game.Screens.Play @@ -42,6 +44,12 @@ namespace osu.Game.Screens.Play // Token request construction should happen post-load to allow derived classes to potentially prepare DI backings that are used to create the request. var tcs = new TaskCompletionSource(); + if (DrawableRuleset.HasReplayLoaded.Value || Mods.Value.Any(m => m is ModAutoplay)) + { + handleTokenFailure(new InvalidOperationException("Replay loaded.")); + return false; + } + if (!api.IsLoggedIn) { handleTokenFailure(new InvalidOperationException("API is not online.")); From 8c9390dc75fd819b65f164c141bbf02420efec29 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 May 2021 11:33:21 +0900 Subject: [PATCH 265/267] Remove replay condition --- osu.Game/Screens/Play/SubmittingPlayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index ece1a589cd..68c6282fe0 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Play // Token request construction should happen post-load to allow derived classes to potentially prepare DI backings that are used to create the request. var tcs = new TaskCompletionSource(); - if (DrawableRuleset.HasReplayLoaded.Value || Mods.Value.Any(m => m is ModAutoplay)) + if (Mods.Value.Any(m => m is ModAutoplay)) { handleTokenFailure(new InvalidOperationException("Replay loaded.")); return false; From 0f00ee8640e332453bd0131824360b594fe685a0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 May 2021 11:35:07 +0900 Subject: [PATCH 266/267] Change failure text Although this is not visible anywhere. --- osu.Game/Screens/Play/SubmittingPlayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index 68c6282fe0..d5ad87c70c 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play if (Mods.Value.Any(m => m is ModAutoplay)) { - handleTokenFailure(new InvalidOperationException("Replay loaded.")); + handleTokenFailure(new InvalidOperationException("Autoplay loaded.")); return false; } From 4bee8c23f0f8b6d502d31d877cda12261790d881 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 10 May 2021 21:40:29 -0700 Subject: [PATCH 267/267] Fix idle tracker not accounting global actions --- osu.Game/Input/IdleTracker.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index 2d6a21d1cf..f3d531cf6c 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.cs @@ -6,13 +6,14 @@ using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Input.Bindings; namespace osu.Game.Input { /// /// Track whether the end-user is in an idle state, based on their last interaction with the game. /// - public class IdleTracker : Component, IKeyBindingHandler, IHandleGlobalKeyboardInput + public class IdleTracker : Component, IKeyBindingHandler, IKeyBindingHandler, IHandleGlobalKeyboardInput { private readonly double timeToIdle; @@ -58,6 +59,10 @@ namespace osu.Game.Input public void OnReleased(PlatformAction action) => updateLastInteractionTime(); + public bool OnPressed(GlobalAction action) => updateLastInteractionTime(); + + public void OnReleased(GlobalAction action) => updateLastInteractionTime(); + protected override bool Handle(UIEvent e) { switch (e)