From 560a0174dff62173c2288a390a0324b9ddedfaf2 Mon Sep 17 00:00:00 2001 From: PercyDan54 <50285552+PercyDan54@users.noreply.github.com> Date: Fri, 18 Dec 2020 17:49:17 +0800 Subject: [PATCH 001/366] Make auto restart toggleable --- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index ae71041a64..466fdccfb7 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -2,7 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -20,9 +22,11 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; + [SettingSource("Restart on fail", "Automatically restarts when failed.")] + public BindableBool Restart { get; } = new BindableBool(); public bool PerformFail() => true; - public bool RestartOnFail => true; + public bool RestartOnFail => Restart.Value; public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { From 2babb7ecb0b122555a339809ce158b748f0e3295 Mon Sep 17 00:00:00 2001 From: PercyDan54 <50285552+PercyDan54@users.noreply.github.com> Date: Fri, 18 Dec 2020 18:33:38 +0800 Subject: [PATCH 002/366] Fix CI --- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 466fdccfb7..925844275b 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Mods [SettingSource("Restart on fail", "Automatically restarts when failed.")] public BindableBool Restart { get; } = new BindableBool(); + public bool PerformFail() => true; public bool RestartOnFail => Restart.Value; From a01402664f341be9bc04ffbb9811ee6d40cbbdae Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 13 Jul 2021 05:22:11 +0300 Subject: [PATCH 003/366] Add redesigned star rating display Matching the same design as the one in the latest figma designs. --- .../Beatmaps/Drawables/StarRatingDisplayV2.cs | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs new file mode 100644 index 0000000000..aa411e74bd --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs @@ -0,0 +1,99 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Beatmaps.Drawables +{ + public class StarRatingDisplayV2 : CompositeDrawable, IHasCurrentValue + { + private readonly Box background; + private readonly SpriteIcon starIcon; + private readonly OsuSpriteText starsText; + + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } + + [Resolved] + private OsuColour colours { get; set; } + + [Resolved(canBeNull: true)] + private OverlayColourProvider colourProvider { get; set; } + + /// + /// Creates a new using an already computed . + /// + /// The already computed to display the star difficulty of. + public StarRatingDisplayV2(StarDifficulty starDifficulty) + { + Size = new Vector2(52f, 20f); + + Current.Value = starDifficulty; + + InternalChild = new CircularContainer + { + Masking = true, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + starIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Right = 30f }, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(8f), + }, + starsText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Left = 10f, Bottom = 1f }, + Font = OsuFont.Torus.With(size: 12f, weight: FontWeight.Bold), + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(c => + { + starsText.Text = c.NewValue.Stars.ToString("0.00"); + + background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); + + starIcon.Colour = c.NewValue.Stars >= 7.5 + ? colourProvider?.Content1 ?? Color4.White + : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); + + starsText.Colour = c.NewValue.Stars >= 7.5 + ? colourProvider?.Content1 ?? Color4.White.Opacity(0.75f) + : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); + }, true); + } + } +} From 6c9ed16b0caa5e29f436d58c388ada3ab34e31b1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 13 Jul 2021 05:29:16 +0300 Subject: [PATCH 004/366] Add visual test scene --- .../TestSceneStarRatingDisplayV2.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs new file mode 100644 index 0000000000..1b85e25e92 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs @@ -0,0 +1,69 @@ +// 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.Utils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osuTK; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneStarRatingDisplayV2 : OsuTestScene + { + [Test] + public void TestDisplay() + { + AddStep("load displays", () => + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(2f), + Direction = FillDirection.Horizontal, + ChildrenEnumerable = Enumerable.Range(0, 10).Select(i => new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(2f), + Direction = FillDirection.Vertical, + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplayV2(new StarDifficulty(i + j * 0.1f, 0)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }) + }) + }; + }); + } + + [Test] + public void TestChangingStarRatingDisplay() + { + StarRatingDisplayV2 starRating = null; + + AddStep("load display", () => Child = starRating = new StarRatingDisplayV2(new StarDifficulty(5.55, 1)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddRepeatStep("set random value", () => + { + starRating.Current.Value = new StarDifficulty(RNG.NextDouble(0.0, 11.0), 1); + }, 10); + + AddSliderStep("set exact stars", 0.0, 11.0, 5.55, d => + { + if (starRating != null) + starRating.Current.Value = new StarDifficulty(d, 1); + }); + } + } +} From 19d54ee7510d0a4d594b0897e22fd39e45c3b9e5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Jul 2021 01:59:32 +0300 Subject: [PATCH 005/366] Update light background handling to `Color4.Yellow` instead Confirmed to be the way forward in https://github.com/ppy/osu-web/pull/7855#issuecomment-880959644. --- osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs index aa411e74bd..6154c8e811 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs @@ -86,13 +86,8 @@ namespace osu.Game.Beatmaps.Drawables background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); - starIcon.Colour = c.NewValue.Stars >= 7.5 - ? colourProvider?.Content1 ?? Color4.White - : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); - - starsText.Colour = c.NewValue.Stars >= 7.5 - ? colourProvider?.Content1 ?? Color4.White.Opacity(0.75f) - : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); + starIcon.Colour = c.NewValue.Stars >= 6.5 ? Color4.Yellow : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); + starsText.Colour = c.NewValue.Stars >= 6.5 ? Color4.Yellow : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); }, true); } } From 95b134f3d82ff42868c6726dcd0ad22220efe327 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jul 2021 05:41:34 +0300 Subject: [PATCH 006/366] Use `OsuColour.Orange1` instead of pure yellow --- osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs index 6154c8e811..5a942cdeee 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs @@ -86,8 +86,8 @@ namespace osu.Game.Beatmaps.Drawables background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); - starIcon.Colour = c.NewValue.Stars >= 6.5 ? Color4.Yellow : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); - starsText.Colour = c.NewValue.Stars >= 6.5 ? Color4.Yellow : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); + starIcon.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); + starsText.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); }, true); } } From 14da5ab813d1d7fe523827a59de535c2846d9298 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jul 2021 05:43:04 +0300 Subject: [PATCH 007/366] Remove defined size from the star rating display --- osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs index 5a942cdeee..e8961ae414 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs @@ -43,8 +43,6 @@ namespace osu.Game.Beatmaps.Drawables /// The already computed to display the star difficulty of. public StarRatingDisplayV2(StarDifficulty starDifficulty) { - Size = new Vector2(52f, 20f); - Current.Value = starDifficulty; InternalChild = new CircularContainer From 0a8d37defa3a167ae725f62c9ab39799f03449bd Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jul 2021 05:48:38 +0300 Subject: [PATCH 008/366] Test star rating display with multiple sizes --- .../Visual/UserInterface/TestSceneStarRatingDisplayV2.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs index 1b85e25e92..43178bb280 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs @@ -14,8 +14,10 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneStarRatingDisplayV2 : OsuTestScene { - [Test] - public void TestDisplay() + [TestCase(52f, 20f)] + [TestCase(52f, 16f)] + [TestCase(50f, 14f)] + public void TestDisplay(float width, float height) { AddStep("load displays", () => { @@ -37,6 +39,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Size = new Vector2(width, height), }) }) }; @@ -52,6 +55,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Size = new Vector2(52f, 20f), }); AddRepeatStep("set random value", () => From d4399f10f9b65bb737da9785ceb44a1bf10ef6e7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jul 2021 06:54:11 +0300 Subject: [PATCH 009/366] Merge both variants of the star rating display --- .../Ranking/TestSceneStarRatingDisplay.cs | 65 --------- ...layV2.cs => TestSceneStarRatingDisplay.cs} | 36 ++++- ...atingDisplayV2.cs => StarRatingDisplay.cs} | 21 ++- .../Components/StarRatingRangeDisplay.cs | 12 +- .../Screens/Play/BeatmapMetadataDisplay.cs | 2 +- .../Expanded/ExpandedPanelMiddleContent.cs | 1 + .../Ranking/Expanded/StarRatingDisplay.cs | 129 ------------------ osu.Game/Screens/Select/BeatmapInfoWedge.cs | 1 - 8 files changed, 56 insertions(+), 211 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs rename osu.Game.Tests/Visual/UserInterface/{TestSceneStarRatingDisplayV2.cs => TestSceneStarRatingDisplay.cs} (66%) rename osu.Game/Beatmaps/Drawables/{StarRatingDisplayV2.cs => StarRatingDisplay.cs} (75%) delete mode 100644 osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs deleted file mode 100644 index 566452249f..0000000000 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs +++ /dev/null @@ -1,65 +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.Linq; -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Utils; -using osu.Game.Beatmaps; -using osu.Game.Screens.Ranking.Expanded; -using osuTK; - -namespace osu.Game.Tests.Visual.Ranking -{ - public class TestSceneStarRatingDisplay : OsuTestScene - { - [Test] - public void TestDisplay() - { - AddStep("load displays", () => Child = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - ChildrenEnumerable = new[] - { - 1.23, - 2.34, - 3.45, - 4.56, - 5.67, - 6.78, - 10.11, - }.Select(starRating => new StarRatingDisplay(new StarDifficulty(starRating, 0)) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }) - }); - } - - [Test] - public void TestChangingStarRatingDisplay() - { - StarRatingDisplay starRating = null; - - AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(3f), - }); - - AddRepeatStep("set random value", () => - { - starRating.Current.Value = new StarDifficulty(RNG.NextDouble(0.0, 11.0), 1); - }, 10); - - AddSliderStep("set exact stars", 0.0, 11.0, 5.55, d => - { - if (starRating != null) - starRating.Current.Value = new StarDifficulty(d, 1); - }); - } - } -} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs similarity index 66% rename from osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 43178bb280..4c65500fbe 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplayV2.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -12,12 +12,36 @@ using osuTK; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneStarRatingDisplayV2 : OsuTestScene + public class TestSceneStarRatingDisplay : OsuTestScene { + [Test] + public void TestOldColoursDisplay() + { + AddStep("load displays", () => Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + ChildrenEnumerable = new[] + { + 1.23, + 2.34, + 3.45, + 4.56, + 5.67, + 6.78, + 10.11, + }.Select(starRating => new StarRatingDisplay(new StarDifficulty(starRating, 0)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }) + }); + } + [TestCase(52f, 20f)] [TestCase(52f, 16f)] [TestCase(50f, 14f)] - public void TestDisplay(float width, float height) + public void TestNewColoursDisplay(float width, float height) { AddStep("load displays", () => { @@ -35,7 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Vertical, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplayV2(new StarDifficulty(i + j * 0.1f, 0)) + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i + j * 0.1f, 0), true) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -47,11 +71,11 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestChangingStarRatingDisplay() + public void TestChangingStarRatingDisplay([Values(false, true)] bool useNewColours) { - StarRatingDisplayV2 starRating = null; + StarRatingDisplay starRating = null; - AddStep("load display", () => Child = starRating = new StarRatingDisplayV2(new StarDifficulty(5.55, 1)) + AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1), useNewColours) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs similarity index 75% rename from osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs rename to osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index e8961ae414..ed751c66de 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplayV2.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -17,8 +17,12 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class StarRatingDisplayV2 : CompositeDrawable, IHasCurrentValue + /// + /// A pill that displays the star rating of a beatmap. + /// + public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { + private readonly bool useNewDifficultyColours; private readonly Box background; private readonly SpriteIcon starIcon; private readonly OsuSpriteText starsText; @@ -38,13 +42,18 @@ namespace osu.Game.Beatmaps.Drawables private OverlayColourProvider colourProvider { get; set; } /// - /// Creates a new using an already computed . + /// Creates a new using an already computed . /// - /// The already computed to display the star difficulty of. - public StarRatingDisplayV2(StarDifficulty starDifficulty) + /// The already computed to display. + /// Use the new spectrum-based difficulty colours for the display, rather than the old. + public StarRatingDisplay(StarDifficulty starDifficulty, bool useNewDifficultyColours = false) { + this.useNewDifficultyColours = useNewDifficultyColours; + Current.Value = starDifficulty; + Size = new Vector2(52f, 20f); + InternalChild = new CircularContainer { Masking = true, @@ -82,7 +91,9 @@ namespace osu.Game.Beatmaps.Drawables { starsText.Text = c.NewValue.Stars.ToString("0.00"); - background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); + background.Colour = useNewDifficultyColours + ? colours.ForStarDifficulty(c.NewValue.Stars) + : colours.ForDifficultyRating(c.NewValue.DifficultyRating); starIcon.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); starsText.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 8c1b10e3bd..6f5e48f09c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -8,14 +8,16 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Screens.Ranking.Expanded; using osuTK; namespace osu.Game.Screens.OnlinePlay.Components { public class StarRatingRangeDisplay : OnlinePlayComposite { + private readonly bool useNewDifficultyColours; + [Resolved] private OsuColour colours { get; set; } @@ -24,8 +26,10 @@ namespace osu.Game.Screens.OnlinePlay.Components private StarRatingDisplay maxDisplay; private Drawable maxBackground; - public StarRatingRangeDisplay() + public StarRatingRangeDisplay(bool useNewDifficultyColours = false) { + this.useNewDifficultyColours = useNewDifficultyColours; + AutoSizeAxes = Axes.Both; } @@ -62,8 +66,8 @@ namespace osu.Game.Screens.OnlinePlay.Components AutoSizeAxes = Axes.Both, Children = new Drawable[] { - minDisplay = new StarRatingDisplay(default), - maxDisplay = new StarRatingDisplay(default) + minDisplay = new StarRatingDisplay(default) { Size = new Vector2(52f, 16f) }, + maxDisplay = new StarRatingDisplay(default) { Size = new Vector2(52f, 16f) } } } }; diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 4265a83ce1..d77673580a 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -10,12 +10,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; -using osu.Game.Screens.Ranking.Expanded; using osuTK; namespace osu.Game.Screens.Play diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs index e10fe5726d..bcb5e7999f 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs deleted file mode 100644 index 2b86100be8..0000000000 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ /dev/null @@ -1,129 +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.Globalization; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Screens.Ranking.Expanded -{ - /// - /// A pill that displays the star rating of a . - /// - public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue - { - private Box background; - private FillFlowContainer content; - private OsuTextFlowContainer textFlow; - - [Resolved] - private OsuColour colours { get; set; } - - private readonly BindableWithCurrent current = new BindableWithCurrent(); - - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } - - /// - /// Creates a new using an already computed . - /// - /// The already computed to display the star difficulty of. - public StarRatingDisplay(StarDifficulty starDifficulty) - { - Current.Value = starDifficulty; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) - { - AutoSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] - { - new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - } - }, - content = 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 - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(7), - Icon = FontAwesome.Solid.Star, - }, - textFlow = 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, - } - } - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - Current.BindValueChanged(_ => updateDisplay(), true); - } - - private void updateDisplay() - { - var starRatingParts = Current.Value.Stars.ToString("0.00", CultureInfo.InvariantCulture).Split('.'); - string wholePart = starRatingParts[0]; - string fractionPart = starRatingParts[1]; - string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; - - var stars = Current.Value.Stars; - - background.Colour = colours.ForStarDifficulty(stars); - content.Colour = stars >= 6.5 ? colours.Orange1 : Color4.Black; - - textFlow.Clear(); - textFlow.AddText($"{wholePart}", s => - { - s.Font = s.Font.With(size: 14); - s.UseFullGlyphHeight = false; - }); - - textFlow.AddText($"{separator}{fractionPart}", s => - { - 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 3779523094..67eb8220f7 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -28,7 +28,6 @@ using osu.Game.Extensions; 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 From 42370e48ec3b06e4861cb56175f521faece1f033 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Jul 2021 08:20:06 +0300 Subject: [PATCH 010/366] Disable shadow on star display text --- osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index ed751c66de..96e830ccc3 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -78,6 +78,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, Margin = new MarginPadding { Left = 10f, Bottom = 1f }, Font = OsuFont.Torus.With(size: 12f, weight: FontWeight.Bold), + Shadow = false, } } }; From 284fa496463bc3c5d718b141bf1dd81293705845 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Jul 2021 08:20:22 +0300 Subject: [PATCH 011/366] Bring margins of components closer to existing designs --- osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 96e830ccc3..2b555cc096 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -68,7 +68,7 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Right = 30f }, + Margin = new MarginPadding { Right = 26.5f }, Icon = FontAwesome.Solid.Star, Size = new Vector2(8f), }, @@ -76,7 +76,7 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Left = 10f, Bottom = 1f }, + Margin = new MarginPadding { Left = 10f, Bottom = 1.5f }, Font = OsuFont.Torus.With(size: 12f, weight: FontWeight.Bold), Shadow = false, } From 7f9af0ae658331cc424b4572791ea5312bc63013 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Jul 2021 08:21:27 +0300 Subject: [PATCH 012/366] Scale up "changing display" test cases --- .../Visual/UserInterface/TestSceneStarRatingDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 4c65500fbe..88f43cd701 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(52f, 20f), + Scale = new Vector2(3f), }); AddRepeatStep("set random value", () => From b2332eb5b38091c6ea175cb27ead4b3d8d04c06f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 Aug 2021 17:06:07 +0300 Subject: [PATCH 013/366] Use new difficulty colours permanently --- .../TestSceneStarRatingDisplay.cs | 32 +++---------------- .../Beatmaps/Drawables/StarRatingDisplay.cs | 10 ++---- .../Components/StarRatingRangeDisplay.cs | 6 +--- 3 files changed, 7 insertions(+), 41 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 88f43cd701..2f3593c062 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -14,34 +14,10 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneStarRatingDisplay : OsuTestScene { - [Test] - public void TestOldColoursDisplay() - { - AddStep("load displays", () => Child = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - ChildrenEnumerable = new[] - { - 1.23, - 2.34, - 3.45, - 4.56, - 5.67, - 6.78, - 10.11, - }.Select(starRating => new StarRatingDisplay(new StarDifficulty(starRating, 0)) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }) - }); - } - [TestCase(52f, 20f)] [TestCase(52f, 16f)] [TestCase(50f, 14f)] - public void TestNewColoursDisplay(float width, float height) + public void TestDisplay(float width, float height) { AddStep("load displays", () => { @@ -59,7 +35,7 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Vertical, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i + j * 0.1f, 0), true) + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i + j * 0.1f, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -71,11 +47,11 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestChangingStarRatingDisplay([Values(false, true)] bool useNewColours) + public void TestChangingStarRatingDisplay() { StarRatingDisplay starRating = null; - AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1), useNewColours) + AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 2b555cc096..0520cea17a 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -22,7 +22,6 @@ namespace osu.Game.Beatmaps.Drawables /// public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { - private readonly bool useNewDifficultyColours; private readonly Box background; private readonly SpriteIcon starIcon; private readonly OsuSpriteText starsText; @@ -45,11 +44,8 @@ namespace osu.Game.Beatmaps.Drawables /// Creates a new using an already computed . /// /// The already computed to display. - /// Use the new spectrum-based difficulty colours for the display, rather than the old. - public StarRatingDisplay(StarDifficulty starDifficulty, bool useNewDifficultyColours = false) + public StarRatingDisplay(StarDifficulty starDifficulty) { - this.useNewDifficultyColours = useNewDifficultyColours; - Current.Value = starDifficulty; Size = new Vector2(52f, 20f); @@ -92,9 +88,7 @@ namespace osu.Game.Beatmaps.Drawables { starsText.Text = c.NewValue.Stars.ToString("0.00"); - background.Colour = useNewDifficultyColours - ? colours.ForStarDifficulty(c.NewValue.Stars) - : colours.ForDifficultyRating(c.NewValue.DifficultyRating); + background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); starIcon.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); starsText.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 6f5e48f09c..867fa88352 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -16,8 +16,6 @@ namespace osu.Game.Screens.OnlinePlay.Components { public class StarRatingRangeDisplay : OnlinePlayComposite { - private readonly bool useNewDifficultyColours; - [Resolved] private OsuColour colours { get; set; } @@ -26,10 +24,8 @@ namespace osu.Game.Screens.OnlinePlay.Components private StarRatingDisplay maxDisplay; private Drawable maxBackground; - public StarRatingRangeDisplay(bool useNewDifficultyColours = false) + public StarRatingRangeDisplay() { - this.useNewDifficultyColours = useNewDifficultyColours; - AutoSizeAxes = Axes.Both; } From b63d47259480ddc46579b76cb8505102f249000c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 Aug 2021 18:17:02 +0300 Subject: [PATCH 014/366] Adjust font size to match designs Looks silly when using `12f`, I've added a todo comment so that this specific case does not get forgotten when CSS-compatible font sizing gets supported. The todo comment may not be 100% required but very unsure about silently changing it and forgetting about it. --- osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 0520cea17a..2c40aebbe1 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -64,7 +64,7 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Right = 26.5f }, + Margin = new MarginPadding { Right = 30f }, Icon = FontAwesome.Solid.Star, Size = new Vector2(8f), }, @@ -72,8 +72,10 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Left = 10f, Bottom = 1.5f }, - Font = OsuFont.Torus.With(size: 12f, weight: FontWeight.Bold), + Margin = new MarginPadding { Left = 10f, Bottom = 2f }, + // todo: this should be size: 12f, but to match up with the design, it needs to be 14.4f + // see https://github.com/ppy/osu-framework/issues/3271. + Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold), Shadow = false, } } From 7bbc917f75dba460e055c8eb2981f8808967c9a5 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 6 Aug 2021 22:50:57 +0200 Subject: [PATCH 015/366] Localise beatmap picker. --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 66886b0882..b16fb76ec3 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -11,11 +11,13 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osuTK; @@ -26,7 +28,8 @@ namespace osu.Game.Overlays.BeatmapSet private const float tile_icon_padding = 7; private const float tile_spacing = 2; - private readonly OsuSpriteText version, starRating; + private readonly OsuSpriteText version, starRating, starRatingText; + private readonly FillFlowContainer starRatingContainer; private readonly Statistic plays, favourites; public readonly DifficultiesContainer Difficulties; @@ -68,14 +71,14 @@ namespace osu.Game.Overlays.BeatmapSet OnLostHover = () => { showBeatmap(Beatmap.Value); - starRating.FadeOut(100); + starRatingContainer.FadeOut(100); }, }, new FillFlowContainer { AutoSizeAxes = Axes.Both, Spacing = new Vector2(5f), - Children = new[] + Children = new Drawable[] { version = new OsuSpriteText { @@ -83,14 +86,31 @@ namespace osu.Game.Overlays.BeatmapSet Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold) }, - starRating = new OsuSpriteText + starRatingContainer = new FillFlowContainer { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(size: 11, weight: FontWeight.Bold), - Text = "Star Difficulty", Alpha = 0, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(2f, 0), Margin = new MarginPadding { Bottom = 1 }, + Children = new[] + { + starRatingText = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Bold), + Text = BeatmapsetsStrings.ShowStatsStars, + }, + starRating = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Bold), + Text = string.Empty, + }, + } }, }, }, @@ -124,6 +144,7 @@ namespace osu.Game.Overlays.BeatmapSet private void load(OsuColour colours) { starRating.Colour = colours.Yellow; + starRatingText.Colour = colours.Yellow; updateDisplay(); } @@ -149,14 +170,14 @@ namespace osu.Game.Overlays.BeatmapSet OnHovered = beatmap => { showBeatmap(beatmap); - starRating.Text = beatmap.StarDifficulty.ToString("Star Difficulty 0.##"); - starRating.FadeIn(100); + starRating.Text = beatmap.StarDifficulty.ToLocalisableString(@"0.##"); + starRatingContainer.FadeIn(100); }, OnClicked = beatmap => { Beatmap.Value = beatmap; }, }); } - starRating.FadeOut(100); + starRatingContainer.FadeOut(100); Beatmap.Value = Difficulties.FirstOrDefault()?.Beatmap; plays.Value = BeatmapSet?.OnlineInfo.PlayCount ?? 0; favourites.Value = BeatmapSet?.OnlineInfo.FavouriteCount ?? 0; @@ -300,7 +321,7 @@ namespace osu.Game.Overlays.BeatmapSet set { this.value = value; - text.Text = Value.ToString(@"N0"); + text.Text = Value.ToLocalisableString(@"N0"); } } From fc48696718796a1cb3597e9132e362c8ec187ff5 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 7 Aug 2021 18:27:55 +0200 Subject: [PATCH 016/366] Localise detail buttons. --- .../Localisation/DownloadButtonStrings.cs | 24 +++++++++++++++++++ .../BeatmapSet/Buttons/FavouriteButton.cs | 3 ++- .../Buttons/HeaderDownloadButton.cs | 14 ++++++----- 3 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Localisation/DownloadButtonStrings.cs diff --git a/osu.Game/Localisation/DownloadButtonStrings.cs b/osu.Game/Localisation/DownloadButtonStrings.cs new file mode 100644 index 0000000000..736f309624 --- /dev/null +++ b/osu.Game/Localisation/DownloadButtonStrings.cs @@ -0,0 +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 osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class DownloadButtonStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.DownloadButton"; + + /// + /// "Downloading..." + /// + public static LocalisableString Downloading => new TranslatableString(getKey(@"downloading"), @"Downloading..."); + + /// + /// "Importing..." + /// + public static LocalisableString Importing => new TranslatableString(getKey(@"importing"), @"Importing..."); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index bb87e7151b..43dd1438f1 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Notifications; +using osu.Game.Resources.Localisation.Web; using osu.Game.Users; using osuTK; @@ -35,7 +36,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { if (!Enabled.Value) return string.Empty; - return (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; + return favourited.Value ? BeatmapsetsStrings.ShowDetailsUnfavourite : BeatmapsetsStrings.ShowDetailsFavourite; } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index cef623e59b..441ef2f6cf 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -15,9 +15,11 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Overlays.BeatmapListing.Panels; +using osu.Game.Resources.Localisation.Web; using osu.Game.Users; using osuTK; using osuTK.Graphics; +using osu.Game.Localisation; namespace osu.Game.Overlays.BeatmapSet.Buttons { @@ -27,7 +29,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private readonly bool noVideo; - public LocalisableString TooltipText => button.Enabled.Value ? "download this beatmap" : "login to download"; + public LocalisableString TooltipText => button.Enabled.Value ? BeatmapsetsStrings.ShowDetailsDownloadDefault : BeatmapsetsStrings.ShowDetailsLoggedOut; private readonly IBindable localUser = new Bindable(); @@ -113,7 +115,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { new OsuSpriteText { - Text = "Downloading...", + Text = DownloadButtonStrings.Downloading, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, }; @@ -124,7 +126,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { new OsuSpriteText { - Text = "Importing...", + Text = DownloadButtonStrings.Importing, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, }; @@ -139,7 +141,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { new OsuSpriteText { - Text = "Download", + Text = BeatmapsetsStrings.ShowDetailsDownloadDefault, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, new OsuSpriteText @@ -158,12 +160,12 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private void enabledChanged(ValueChangedEvent e) => this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); - private string getVideoSuffixText() + private LocalisableString getVideoSuffixText() { if (!BeatmapSet.Value.OnlineInfo.HasVideo) return string.Empty; - return noVideo ? "without Video" : "with Video"; + return noVideo ? BeatmapsetsStrings.ShowDetailsDownloadNoVideo : BeatmapsetsStrings.ShowDetailsDownloadVideo; } } } From 3a0dd5b019e2401f917d2656ae73ef9ddd09847b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 8 Aug 2021 01:37:45 +0300 Subject: [PATCH 017/366] Add more insane star difficulties for visual testing --- .../Visual/UserInterface/TestSceneStarRatingDisplay.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 2f3593c062..a8bc5664f3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics.Containers; using osuTK; namespace osu.Game.Tests.Visual.UserInterface @@ -28,19 +29,19 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Horizontal, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(i => new FillFlowContainer + ChildrenEnumerable = Enumerable.Range(0, 15).Select(i => new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Vertical, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i + j * 0.1f, 0)) + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i * (i >= 11 ? 25f : 1f) + j * 0.1f, 0)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(width, height), - }) + }), }) }; }); From bf0d4b6ef1c9d20e69c43abb3d945b92ca2c135d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 8 Aug 2021 10:25:51 +0200 Subject: [PATCH 018/366] Localise basic stats. --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 3f1034759e..ce348bd753 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; using osuTK; namespace osu.Game.Overlays.BeatmapSet @@ -53,7 +54,7 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - bpm.Value = BeatmapSet?.OnlineInfo?.BPM.ToString(@"0.##") ?? "-"; + bpm.Value = BeatmapSet?.OnlineInfo?.BPM.ToLocalisableString(@"0.##") ?? (LocalisableString)"-"; if (beatmap == null) { @@ -63,9 +64,11 @@ namespace osu.Game.Overlays.BeatmapSet } else { + length.TooltipText = BeatmapsetsStrings.ShowStatsTotalLength(TimeSpan.FromMilliseconds(beatmap.Length).ToFormattedDuration()); length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToFormattedDuration(); - circleCount.Value = beatmap.OnlineInfo.CircleCount.ToString(); - sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToString(); + + circleCount.Value = beatmap.OnlineInfo.CircleCount.ToLocalisableString("N0"); + sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToLocalisableString("N0"); } } @@ -78,10 +81,10 @@ namespace osu.Game.Overlays.BeatmapSet Direction = FillDirection.Horizontal, Children = new[] { - length = new Statistic(FontAwesome.Regular.Clock, "Length") { Width = 0.25f }, - bpm = new Statistic(FontAwesome.Regular.Circle, "BPM") { Width = 0.25f }, - circleCount = new Statistic(FontAwesome.Regular.Circle, "Circle Count") { Width = 0.25f }, - sliderCount = new Statistic(FontAwesome.Regular.Circle, "Slider Count") { Width = 0.25f }, + length = new Statistic(FontAwesome.Regular.Clock, BeatmapsetsStrings.ShowStatsTotalLength(string.Empty)) { Width = 0.25f }, + bpm = new Statistic(FontAwesome.Regular.Circle, BeatmapsetsStrings.ShowStatsBpm) { Width = 0.25f }, + circleCount = new Statistic(FontAwesome.Regular.Circle, BeatmapsetsStrings.ShowStatsCountCircles) { Width = 0.25f }, + sliderCount = new Statistic(FontAwesome.Regular.Circle, BeatmapsetsStrings.ShowStatsCountSliders) { Width = 0.25f }, }, }; } @@ -96,7 +99,7 @@ namespace osu.Game.Overlays.BeatmapSet { private readonly OsuSpriteText value; - public LocalisableString TooltipText { get; } + public LocalisableString TooltipText { get; set; } public LocalisableString Value { @@ -104,7 +107,7 @@ namespace osu.Game.Overlays.BeatmapSet set => this.value.Text = value; } - public Statistic(IconUsage icon, string name) + public Statistic(IconUsage icon, LocalisableString name) { TooltipText = name; RelativeSizeAxes = Axes.X; From 5e0f9d0af9beffed5189b7cce890b972c5b32413 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 8 Aug 2021 22:00:12 +0200 Subject: [PATCH 019/366] Localise user ratings. --- osu.Game/Screens/Select/Details/UserRatings.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index cf5e3ba1b3..a45bcd0666 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -9,6 +9,8 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using System.Linq; using osu.Game.Beatmaps; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Screens.Select.Details { @@ -35,8 +37,8 @@ namespace osu.Game.Screens.Select.Details if (metrics == null) { - negativeRatings.Text = "0"; - positiveRatings.Text = "0"; + negativeRatings.Text = 0.ToLocalisableString("N0"); + positiveRatings.Text = 0.ToLocalisableString("N0"); ratingsBar.Length = 0; graph.Values = new float[rating_range]; } @@ -47,8 +49,8 @@ namespace osu.Game.Screens.Select.Details var negativeCount = ratings.Take(rating_range / 2).Sum(); var totalCount = ratings.Sum(); - negativeRatings.Text = negativeCount.ToString(); - positiveRatings.Text = (totalCount - negativeCount).ToString(); + negativeRatings.Text = negativeCount.ToLocalisableString("N0"); + positiveRatings.Text = (totalCount - negativeCount).ToLocalisableString("N0"); ratingsBar.Length = totalCount == 0 ? 0 : (float)negativeCount / totalCount; graph.Values = ratings.Take(rating_range).Select(r => (float)r); } @@ -70,7 +72,7 @@ namespace osu.Game.Screens.Select.Details { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = "User Rating", + Text = BeatmapsetsStrings.ShowStatsUserRating, Font = OsuFont.GetFont(size: 12), Margin = new MarginPadding { Bottom = 5 }, }, @@ -88,14 +90,14 @@ namespace osu.Game.Screens.Select.Details { negativeRatings = new OsuSpriteText { - Text = "0", + Text = 0.ToLocalisableString("N0"), Font = OsuFont.GetFont(size: 12) }, positiveRatings = new OsuSpriteText { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Text = @"0", + Text = 0.ToLocalisableString("N0"), Font = OsuFont.GetFont(size: 12) }, }, @@ -104,7 +106,7 @@ namespace osu.Game.Screens.Select.Details { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = "Rating Spread", + Text = BeatmapsetsStrings.ShowStatsRatingSpread, Font = OsuFont.GetFont(size: 12), Margin = new MarginPadding { Bottom = 5 }, }, From d9a4f018e65ce669a1fd329a3aa6880b5c94bdbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 18:26:36 +0900 Subject: [PATCH 020/366] Add event flow for receiving kick commands --- osu.Game/Online/Multiplayer/IMultiplayerClient.cs | 9 +++++++++ osu.Game/Online/Multiplayer/MultiplayerClient.cs | 6 ++++++ osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs | 1 + 3 files changed, 16 insertions(+) diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index 064065ab00..8f16d22c4c 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -31,6 +31,15 @@ namespace osu.Game.Online.Multiplayer /// The user. Task UserLeft(MultiplayerRoomUser user); + /// + /// Signals that a user has been kicked from the room. + /// + /// + /// This will also be sent to the user that was kicked. + /// + /// The user. + Task UserKicked(MultiplayerRoomUser user); + /// /// Signal that the host of the room has changed. /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 4607211cdf..7e964ed5fa 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -389,6 +389,12 @@ namespace osu.Game.Online.Multiplayer return Task.CompletedTask; } + Task IMultiplayerClient.UserKicked(MultiplayerRoomUser user) + { + // TODO: also inform users of the kick operation. + return ((IMultiplayerClient)this).UserLeft(user); + } + Task IMultiplayerClient.HostChanged(int userId) { if (Room == null) diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 55477a9fc7..c38a648a6a 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -50,6 +50,7 @@ namespace osu.Game.Online.Multiplayer connection.On(nameof(IMultiplayerClient.RoomStateChanged), ((IMultiplayerClient)this).RoomStateChanged); connection.On(nameof(IMultiplayerClient.UserJoined), ((IMultiplayerClient)this).UserJoined); connection.On(nameof(IMultiplayerClient.UserLeft), ((IMultiplayerClient)this).UserLeft); + connection.On(nameof(IMultiplayerClient.UserKicked), ((IMultiplayerClient)this).UserKicked); connection.On(nameof(IMultiplayerClient.HostChanged), ((IMultiplayerClient)this).HostChanged); connection.On(nameof(IMultiplayerClient.SettingsChanged), ((IMultiplayerClient)this).SettingsChanged); connection.On(nameof(IMultiplayerClient.UserStateChanged), ((IMultiplayerClient)this).UserStateChanged); From 9b21ebd6d04410d2e5fcd363cf26b4ee88a0bfec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 18:31:04 +0900 Subject: [PATCH 021/366] Add client side handling on incoming kick --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 7e964ed5fa..57dbfbb507 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -190,7 +190,8 @@ namespace osu.Game.Online.Multiplayer return joinOrLeaveTaskChain.Add(async () => { await scheduledReset.ConfigureAwait(false); - await LeaveRoomInternal().ConfigureAwait(false); + if (Room != null) + await LeaveRoomInternal().ConfigureAwait(false); }); } @@ -391,6 +392,12 @@ namespace osu.Game.Online.Multiplayer Task IMultiplayerClient.UserKicked(MultiplayerRoomUser user) { + if (LocalUser == null) + return Task.CompletedTask; + + if (user.Equals(LocalUser)) + LeaveRoom(); + // TODO: also inform users of the kick operation. return ((IMultiplayerClient)this).UserLeft(user); } From 31608a1bc6c4a691571967dd1e893a7ac4338ee9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 19:56:25 +0900 Subject: [PATCH 022/366] Leave the match screen when kicked --- .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 561fa220c8..57dde31b68 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -448,6 +448,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private void onRoomUpdated() { + // may happen if the client is kicked or otherwise removed from the room. + if (client.Room == null) + { + Schedule(this.Exit); + return; + } + Scheduler.AddOnce(UpdateMods); } From 18ecd8758ba0646e5c54621eb77d23d152eea397 Mon Sep 17 00:00:00 2001 From: PercyDan <50285552+PercyDan54@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:12:35 +0800 Subject: [PATCH 023/366] Make Perfect auto restart toggleable --- osu.Game/Rulesets/Mods/ModFailCondition.cs | 5 +++++ osu.Game/Rulesets/Mods/ModPerfect.cs | 5 +++++ osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 5 ----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFailCondition.cs b/osu.Game/Rulesets/Mods/ModFailCondition.cs index c0d7bae2b2..c6855a3d38 100644 --- a/osu.Game/Rulesets/Mods/ModFailCondition.cs +++ b/osu.Game/Rulesets/Mods/ModFailCondition.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; +using osu.Game.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -11,6 +13,9 @@ namespace osu.Game.Rulesets.Mods { public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; + [SettingSource("Restart on fail", "Automatically restarts when failed.")] + public BindableBool Restart { get; } = new BindableBool(); + public virtual bool PerformFail() => true; public virtual bool RestartOnFail => true; diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 187a4d8e23..9016a24f8d 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -21,6 +21,11 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModSuddenDeath)).ToArray(); + protected ModPerfect() + { + Restart.Value = Restart.Default = true; + } + protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => result.Type.AffectsAccuracy() && result.Type != result.Judgement.MaxResult; diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 7df561b199..68ed112078 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -3,9 +3,7 @@ using System; using System.Linq; -using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -23,9 +21,6 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModPerfect)).ToArray(); - [SettingSource("Restart on fail", "Automatically restarts when failed.")] - public BindableBool Restart { get; } = new BindableBool(); - public override bool PerformFail() => true; public override bool RestartOnFail => Restart.Value; From d80a2dcca72da28a9fac4a6ec3c5abff2d5ddf30 Mon Sep 17 00:00:00 2001 From: PercyDan <50285552+PercyDan54@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:14:01 +0800 Subject: [PATCH 024/366] Missed one --- osu.Game/Rulesets/Mods/ModFailCondition.cs | 2 +- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFailCondition.cs b/osu.Game/Rulesets/Mods/ModFailCondition.cs index c6855a3d38..4425ece513 100644 --- a/osu.Game/Rulesets/Mods/ModFailCondition.cs +++ b/osu.Game/Rulesets/Mods/ModFailCondition.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mods public virtual bool PerformFail() => true; - public virtual bool RestartOnFail => true; + public virtual bool RestartOnFail => Restart.Value; public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 68ed112078..031eb716c3 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -23,8 +23,6 @@ namespace osu.Game.Rulesets.Mods public override bool PerformFail() => true; - public override bool RestartOnFail => Restart.Value; - protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => result.Type.AffectsCombo() && !result.IsHit; From 6ecc728c0121e4821cf83346e2cf8a5401a6210e Mon Sep 17 00:00:00 2001 From: PercyDan <50285552+PercyDan54@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:27:36 +0800 Subject: [PATCH 025/366] Remove override --- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 031eb716c3..1abd353d20 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -21,8 +21,6 @@ namespace osu.Game.Rulesets.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModPerfect)).ToArray(); - public override bool PerformFail() => true; - protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => result.Type.AffectsCombo() && !result.IsHit; From 97041de09f5230e2fe1d5d9004e74b920be8b42b Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Wed, 11 Aug 2021 11:23:12 +0800 Subject: [PATCH 026/366] Preparation for localisation. --- osu.Game/Overlays/Settings/SettingsSection.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 4143605c28..f993a46dc6 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK.Graphics; @@ -19,10 +20,10 @@ namespace osu.Game.Overlays.Settings protected override Container Content => FlowContent; public abstract Drawable CreateIcon(); - public abstract string Header { get; } + public abstract LocalisableString Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public virtual IEnumerable FilterTerms => new[] { Header }; + public virtual IEnumerable FilterTerms => new[] { Header.ToString() }; private const int header_size = 26; private const int margin = 20; From 9a5d4ffd43e1fc2fed39cf03992ff7e503cd5473 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Wed, 11 Aug 2021 15:25:08 +0800 Subject: [PATCH 027/366] Add GeneralSettingsStrings --- .../Localisation/GeneralSettingsStrings.cs | 59 +++++++++++++++++++ .../Sections/General/LanguageSettings.cs | 6 +- .../Sections/General/UpdateSettings.cs | 11 ++-- .../Settings/Sections/GeneralSection.cs | 4 +- 4 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 osu.Game/Localisation/GeneralSettingsStrings.cs diff --git a/osu.Game/Localisation/GeneralSettingsStrings.cs b/osu.Game/Localisation/GeneralSettingsStrings.cs new file mode 100644 index 0000000000..19fb8de972 --- /dev/null +++ b/osu.Game/Localisation/GeneralSettingsStrings.cs @@ -0,0 +1,59 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class GeneralSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.GeneralSettings"; + + /// + /// "General" + /// + public static LocalisableString GeneralSectionHeader => new TranslatableString(getKey(@"general_section_header"), @"General"); + + /// + /// "Language" + /// + public static LocalisableString LanguageHeader => new TranslatableString(getKey(@"language_header"), @"Language"); + + /// + /// "Language" + /// + public static LocalisableString LanguageDropdown => new TranslatableString(getKey(@"language_dropdown"), @"Language"); + + /// + /// "Prefer metadata in original language" + /// + public static LocalisableString PreferOriginal => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language"); + + /// + /// "Updates" + /// + public static LocalisableString UpdateHeader => new TranslatableString(getKey(@"update_header"), @"Updates"); + + /// + /// "Release stream" + /// + public static LocalisableString ReleaseStream => new TranslatableString(getKey(@"release_stream"), @"Release stream"); + + /// + /// "Check for updates" + /// + public static LocalisableString CheckUpdate => new TranslatableString(getKey(@"check_update"), @"Check for updates"); + + /// + /// "Open osu! folder" + /// + public static LocalisableString OpenOsuFolder => new TranslatableString(getKey(@"open_osu_folder"), @"Open osu! folder"); + + /// + /// "Change folder location..." + /// + public static LocalisableString ChangeFolderLocation => new TranslatableString(getKey(@"change_folder_location"), @"Change folder location..."); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index c6c752e2fd..ac95a713bf 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.General private SettingsDropdown languageSelection; private Bindable frameworkLocale; - protected override LocalisableString Header => "Language"; + protected override LocalisableString Header => GeneralSettingsStrings.LanguageHeader; [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig) @@ -27,11 +27,11 @@ namespace osu.Game.Overlays.Settings.Sections.General { languageSelection = new SettingsEnumDropdown { - LabelText = "Language", + LabelText = GeneralSettingsStrings.LanguageDropdown, }, new SettingsCheckbox { - LabelText = "Prefer metadata in original language", + LabelText = GeneralSettingsStrings.PreferOriginal, Current = frameworkConfig.GetBindable(FrameworkSetting.ShowUnicode) }, }; diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index dd20e1d7ef..aa37748653 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -9,6 +9,7 @@ using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Settings.Sections.Maintenance; using osu.Game.Updater; @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.General [Resolved(CanBeNull = true)] private UpdateManager updateManager { get; set; } - protected override LocalisableString Header => "Updates"; + protected override LocalisableString Header => GeneralSettingsStrings.UpdateHeader; private SettingsButton checkForUpdatesButton; @@ -32,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { Add(new SettingsEnumDropdown { - LabelText = "Release stream", + LabelText = GeneralSettingsStrings.ReleaseStream, Current = config.GetBindable(OsuSetting.ReleaseStream), }); @@ -40,7 +41,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { Add(checkForUpdatesButton = new SettingsButton { - Text = "Check for updates", + Text = GeneralSettingsStrings.CheckUpdate, Action = () => { checkForUpdatesButton.Enabled.Value = false; @@ -65,13 +66,13 @@ namespace osu.Game.Overlays.Settings.Sections.General { Add(new SettingsButton { - Text = "Open osu! folder", + Text = GeneralSettingsStrings.OpenOsuFolder, Action = storage.OpenInNativeExplorer, }); Add(new SettingsButton { - Text = "Change folder location...", + Text = GeneralSettingsStrings.ChangeFolderLocation, Action = () => game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen())) }); } diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index fefc3fe6a7..87e9f34833 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.General; namespace osu.Game.Overlays.Settings.Sections { public class GeneralSection : SettingsSection { - public override string Header => "General"; + public override LocalisableString Header => GeneralSettingsStrings.GeneralSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 078953980e65c4639899833556b6cd3969e6fd1c Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Wed, 11 Aug 2021 16:48:37 +0800 Subject: [PATCH 028/366] Add GraphicsSettingsStrings --- osu.Game/Localisation/CommonStrings.cs | 7 +- .../Localisation/GraphicsSettingsStrings.cs | 119 ++++++++++++++++++ .../Sections/Graphics/DetailSettings.cs | 11 +- .../Sections/Graphics/LayoutSettings.cs | 25 ++-- .../Sections/Graphics/RendererSettings.cs | 13 +- .../Settings/Sections/GraphicsSection.cs | 4 +- 6 files changed, 152 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Localisation/GraphicsSettingsStrings.cs diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index bf488d2590..5e4ce235b4 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -19,6 +19,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Enabled => new TranslatableString(getKey(@"enabled"), @"Enabled"); + /// + /// "Default" + /// + public static LocalisableString Default => new TranslatableString(getKey(@"default"), @"Default"); + /// /// "Width" /// @@ -31,4 +36,4 @@ namespace osu.Game.Localisation private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs new file mode 100644 index 0000000000..841635649e --- /dev/null +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -0,0 +1,119 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class GraphicsSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.GraphicsSettings"; + + /// + /// "Graphics" + /// + public static LocalisableString GraphicsSectionHeader => new TranslatableString(getKey(@"graphics_section_header"), @"Graphics"); + + /// + /// "Renderer" + /// + public static LocalisableString RendererHeader => new TranslatableString(getKey(@"renderer_header"), @"Renderer"); + + /// + /// "Frame limiter" + /// + public static LocalisableString FrameLimiter => new TranslatableString(getKey(@"frame_limiter"), @"Frame limiter"); + + /// + /// "Threading mode" + /// + public static LocalisableString ThreadingMode => new TranslatableString(getKey(@"threading_mode"), @"Threading mode"); + + /// + /// "Show FPS" + /// + public static LocalisableString ShowFPS => new TranslatableString(getKey(@"show_fps"), @"Show FPS"); + + /// + /// "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. "2x refresh rate" is recommended." + /// + public static LocalisableString UnlimitedFramesNote => new TranslatableString(getKey(@"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."); + + /// + /// "Layout" + /// + public static LocalisableString LayoutHeader => new TranslatableString(getKey(@"layout_header"), @"Layout"); + + /// + /// "Screen mode" + /// + public static LocalisableString ScreenMode => new TranslatableString(getKey(@"screen_mode"), @"Screen mode"); + + /// + /// "Resolution" + /// + public static LocalisableString Resolution => new TranslatableString(getKey(@"resolution"), @"Resolution"); + + /// + /// "UI Scaling" + /// + public static LocalisableString UIScaling => new TranslatableString(getKey(@"ui_scaling"), @"UI Scaling"); + + /// + /// "Screen Scaling" + /// + public static LocalisableString ScreenScaling => new TranslatableString(getKey(@"screen_scaling"), @"Screen Scaling"); + + /// + /// "Horizontal position" + /// + public static LocalisableString HorizontalPosition => new TranslatableString(getKey(@"horizontal_position"), @"Horizontal position"); + + /// + /// "Vertical position" + /// + public static LocalisableString VerticalPosition => new TranslatableString(getKey(@"vertical_position"), @"Vertical position"); + + /// + /// "Horizontal scale" + /// + public static LocalisableString HorizontalScale => new TranslatableString(getKey(@"horizontal_scale"), @"Horizontal scale"); + + /// + /// "Vertical scale" + /// + public static LocalisableString VerticalScale => new TranslatableString(getKey(@"vertical_scale"), @"Vertical scale"); + + /// + /// "Running without fullscreen mode will increase your input latency!" + /// + public static LocalisableString NotFullscreenNote => new TranslatableString(getKey(@"not_fullscreen_note"), @"Running without fullscreen mode will increase your input latency!"); + + /// + /// "Detail Settings" + /// + public static LocalisableString DetailSettingsHeader => new TranslatableString(getKey(@"detail_settings_header"), @"Detail Settings"); + + /// + /// "Storyboard / Video" + /// + public static LocalisableString StoryboardVideo => new TranslatableString(getKey(@"storyboard_video"), @"Storyboard / Video"); + + /// + /// "Hit Lighting" + /// + public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit Lighting"); + + /// + /// "Screenshot format" + /// + public static LocalisableString ScreenshotFormat => new TranslatableString(getKey(@"screenshot_format"), @"Screenshot format"); + + /// + /// "Show menu cursor in screenshots" + /// + public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@""), @"Show menu cursor in screenshots"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index f889cfca0f..20b1d8d801 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -5,12 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics { public class DetailSettings : SettingsSubsection { - protected override LocalisableString Header => "Detail Settings"; + protected override LocalisableString Header => GraphicsSettingsStrings.DetailSettingsHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -19,22 +20,22 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { new SettingsCheckbox { - LabelText = "Storyboard / Video", + LabelText = GraphicsSettingsStrings.StoryboardVideo, Current = config.GetBindable(OsuSetting.ShowStoryboard) }, new SettingsCheckbox { - LabelText = "Hit Lighting", + LabelText = GraphicsSettingsStrings.HitLighting, Current = config.GetBindable(OsuSetting.HitLighting) }, new SettingsEnumDropdown { - LabelText = "Screenshot format", + LabelText = GraphicsSettingsStrings.ScreenshotFormat, Current = config.GetBindable(OsuSetting.ScreenshotFormat) }, new SettingsCheckbox { - LabelText = "Show menu cursor in screenshots", + LabelText = GraphicsSettingsStrings.ShowCursorInScreenshots, Current = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor) } }; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 91208cb78a..50bd8184ee 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -16,13 +16,14 @@ using osu.Framework.Platform; using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osuTK.Graphics; namespace osu.Game.Overlays.Settings.Sections.Graphics { public class LayoutSettings : SettingsSubsection { - protected override LocalisableString Header => "Layout"; + protected override LocalisableString Header => GraphicsSettingsStrings.LayoutHeader; private FillFlowContainer> scalingSettings; @@ -67,20 +68,20 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { windowModeDropdown = new SettingsDropdown { - LabelText = "Screen mode", + LabelText = GraphicsSettingsStrings.ScreenMode, ItemSource = windowModes, Current = config.GetBindable(FrameworkSetting.WindowMode), }, resolutionDropdown = new ResolutionSettingsDropdown { - LabelText = "Resolution", + LabelText = GraphicsSettingsStrings.Resolution, ShowsDefaultIndicator = false, ItemSource = resolutions, Current = sizeFullscreen }, new SettingsSlider { - LabelText = "UI Scaling", + LabelText = GraphicsSettingsStrings.UIScaling, TransferValueOnCommit = true, Current = osuConfig.GetBindable(OsuSetting.UIScale), KeyboardStep = 0.01f, @@ -88,7 +89,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, new SettingsEnumDropdown { - LabelText = "Screen Scaling", + LabelText = GraphicsSettingsStrings.ScreenScaling, Current = osuConfig.GetBindable(OsuSetting.Scaling), Keywords = new[] { "scale", "letterbox" }, }, @@ -104,28 +105,28 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { new SettingsSlider { - LabelText = "Horizontal position", + LabelText = GraphicsSettingsStrings.HorizontalPosition, Current = scalingPositionX, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Vertical position", + LabelText = GraphicsSettingsStrings.VerticalPosition, Current = scalingPositionY, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Horizontal scale", + LabelText = GraphicsSettingsStrings.HorizontalScale, Current = scalingSizeX, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Vertical scale", + LabelText = GraphicsSettingsStrings.VerticalScale, Current = scalingSizeY, KeyboardStep = 0.01f, DisplayAsPercentage = true @@ -145,9 +146,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { updateResolutionDropdown(); - const string not_fullscreen_note = "Running without fullscreen mode will increase your input latency!"; - - windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? not_fullscreen_note : string.Empty; + windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : string.Empty; }, true); windowModes.BindCollectionChanged((sender, args) => @@ -245,7 +244,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics protected override LocalisableString GenerateItemText(Size item) { if (item == new Size(9999, 9999)) - return "Default"; + return CommonStrings.Default; return $"{item.Width}x{item.Height}"; } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 2210c7911e..9747f6b373 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -7,12 +7,13 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics { public class RendererSettings : SettingsSubsection { - protected override LocalisableString Header => "Renderer"; + protected override LocalisableString Header => GraphicsSettingsStrings.RendererHeader; private SettingsEnumDropdown frameLimiterDropdown; @@ -25,17 +26,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics // TODO: this needs to be a custom dropdown at some point frameLimiterDropdown = new SettingsEnumDropdown { - LabelText = "Frame limiter", + LabelText = GraphicsSettingsStrings.FrameLimiter, Current = config.GetBindable(FrameworkSetting.FrameSync) }, new SettingsEnumDropdown { - LabelText = "Threading mode", + LabelText = GraphicsSettingsStrings.ThreadingMode, Current = config.GetBindable(FrameworkSetting.ExecutionMode) }, new SettingsCheckbox { - LabelText = "Show FPS", + LabelText = GraphicsSettingsStrings.ShowFPS, Current = osuConfig.GetBindable(OsuSetting.ShowFpsDisplay) }, }; @@ -47,9 +48,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, bad performance and overheating. It will not improve perceived latency. \"2x refresh rate\" is recommended."; - - frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? unlimited_frames_note : string.Empty; + frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? GraphicsSettingsStrings.UnlimitedFramesNote : string.Empty; }, true); } } diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 4ade48031f..fd0718f9f2 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Graphics; namespace osu.Game.Overlays.Settings.Sections { public class GraphicsSection : SettingsSection { - public override string Header => "Graphics"; + public override LocalisableString Header => GraphicsSettingsStrings.GraphicsSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From b2986e99d30a8e638e53047dd3b594343a18e073 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Wed, 11 Aug 2021 17:10:08 +0800 Subject: [PATCH 029/366] Add AudioSettingsStrings --- osu.Game/Localisation/AudioSettingsStrings.cs | 64 +++++++++++++++++++ .../Sections/Audio/AudioDevicesSettings.cs | 5 +- .../Settings/Sections/Audio/OffsetSettings.cs | 7 +- .../Settings/Sections/Audio/VolumeSettings.cs | 11 ++-- .../Settings/Sections/AudioSection.cs | 4 +- 5 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Localisation/AudioSettingsStrings.cs diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs new file mode 100644 index 0000000000..aa6eabd7d1 --- /dev/null +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -0,0 +1,64 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class AudioSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.AudioSettings"; + + /// + /// "Audio" + /// + public static LocalisableString AudioSectionHeader => new TranslatableString(getKey(@"audio_section_header"), @"Audio"); + + /// + /// "Devices" + /// + public static LocalisableString AudioDevicesHeader => new TranslatableString(getKey(@"audio_devices_header"), @"Devices"); + + /// + /// "Volume" + /// + public static LocalisableString VolumeHeader => new TranslatableString(getKey(@"volume_header"), @"Volume"); + + /// + /// "Master" + /// + public static LocalisableString MasterVolume => new TranslatableString(getKey(@"master_volume"), @"Master"); + + /// + /// "Master (window inactive)" + /// + public static LocalisableString MasterVolumeInactive => new TranslatableString(getKey(@"master_volume_inactive"), @"Master (window inactive)"); + + /// + /// "Effect" + /// + public static LocalisableString EffectVolume => new TranslatableString(getKey(@"effect_volume"), @"Effect"); + + /// + /// "Music" + /// + public static LocalisableString MusicVolume => new TranslatableString(getKey(@"music_volume"), @"Music"); + + /// + /// "Offset Adjustment" + /// + public static LocalisableString OffsetHeader => new TranslatableString(getKey(@"offset_header"), @"Offset Adjustment"); + + /// + /// "Audio offset" + /// + public static LocalisableString AudioOffset => new TranslatableString(getKey(@"audio_offset"), @"Audio offset"); + + /// + /// "Offset wizard" + /// + public static LocalisableString OffsetWizard => new TranslatableString(getKey(@"offset_wizard"), @"Offset wizard"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index d64f176468..501f1b86b8 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -8,12 +8,13 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { public class AudioDevicesSettings : SettingsSubsection { - protected override LocalisableString Header => "Devices"; + protected override LocalisableString Header => AudioSettingsStrings.AudioDevicesHeader; [Resolved] private AudioManager audio { get; set; } @@ -78,7 +79,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio private class AudioDeviceDropdownControl : DropdownControl { protected override LocalisableString GenerateItemText(string item) - => string.IsNullOrEmpty(item) ? "Default" : base.GenerateItemText(item); + => string.IsNullOrEmpty(item) ? CommonStrings.Default : base.GenerateItemText(item); } } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index 7f2e377c83..85973c81c9 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -6,12 +6,13 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { public class OffsetSettings : SettingsSubsection { - protected override LocalisableString Header => "Offset Adjustment"; + protected override LocalisableString Header => AudioSettingsStrings.OffsetHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -20,13 +21,13 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { new SettingsSlider { - LabelText = "Audio offset", + LabelText = AudioSettingsStrings.AudioOffset, Current = config.GetBindable(OsuSetting.AudioOffset), KeyboardStep = 1f }, new SettingsButton { - Text = "Offset wizard" + Text = AudioSettingsStrings.OffsetWizard } }; } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 8f88b03471..00c1cb8f43 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -6,12 +6,13 @@ using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio { public class VolumeSettings : SettingsSubsection { - protected override LocalisableString Header => "Volume"; + protected override LocalisableString Header => AudioSettingsStrings.VolumeHeader; [BackgroundDependencyLoader] private void load(AudioManager audio, OsuConfigManager config) @@ -20,28 +21,28 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { new SettingsSlider { - LabelText = "Master", + LabelText = AudioSettingsStrings.MasterVolume, Current = audio.Volume, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Master (window inactive)", + LabelText = AudioSettingsStrings.MasterVolumeInactive, Current = config.GetBindable(OsuSetting.VolumeInactive), KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Effect", + LabelText = AudioSettingsStrings.EffectVolume, Current = audio.VolumeSample, KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Music", + LabelText = AudioSettingsStrings.MusicVolume, Current = audio.VolumeTrack, KeyboardStep = 0.01f, DisplayAsPercentage = true diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 7072d8e63d..694da0529a 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -3,15 +3,17 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Localisation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Audio; namespace osu.Game.Overlays.Settings.Sections { public class AudioSection : SettingsSection { - public override string Header => "Audio"; + public override LocalisableString Header => AudioSettingsStrings.AudioSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 2cc89f50cce503ed8ecd3a86206b8cd6a50660ea Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 09:14:49 +0800 Subject: [PATCH 030/366] Add missing key --- osu.Game/Localisation/GraphicsSettingsStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index 841635649e..989eaf19b9 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -112,7 +112,7 @@ namespace osu.Game.Localisation /// /// "Show menu cursor in screenshots" /// - public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@""), @"Show menu cursor in screenshots"); + public static LocalisableString ShowCursorInScreenshots => new TranslatableString(getKey(@"show_cursor_in_screenshots"), @"Show menu cursor in screenshots"); private static string getKey(string key) => $"{prefix}:{key}"; } From 03013d0d307480f3589714dd4b6043555fb4943d Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 09:53:31 +0800 Subject: [PATCH 031/366] Add InputSettingsStrings Existed strings files keep no change --- osu.Game/Localisation/CommonStrings.cs | 5 ++ osu.Game/Localisation/InputSettingsStrings.cs | 59 +++++++++++++++++++ .../Input/GlobalKeyBindingsSection.cs | 11 ++-- .../Sections/Input/KeyBindingPanel.cs | 3 +- .../Settings/Sections/Input/KeyBindingRow.cs | 5 +- .../Sections/Input/KeyBindingsSubsection.cs | 3 +- .../Sections/Input/RulesetBindingsSection.cs | 3 +- .../Settings/Sections/InputSection.cs | 5 +- 8 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 osu.Game/Localisation/InputSettingsStrings.cs diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index 5e4ce235b4..432c1c6255 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -14,6 +14,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Cancel => new TranslatableString(getKey(@"cancel"), @"Cancel"); + /// + /// "Clear" + /// + public static LocalisableString Clear => new TranslatableString(getKey(@"clear"), @"Clear"); + /// /// "Enabled" /// diff --git a/osu.Game/Localisation/InputSettingsStrings.cs b/osu.Game/Localisation/InputSettingsStrings.cs new file mode 100644 index 0000000000..e46b4cecf3 --- /dev/null +++ b/osu.Game/Localisation/InputSettingsStrings.cs @@ -0,0 +1,59 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class InputSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.InputSettings"; + + /// + /// "Input" + /// + public static LocalisableString InputSectionHeader => new TranslatableString(getKey(@"input_section_header"), @"Input"); + + /// + /// "Global" + /// + public static LocalisableString GlobalKeyBindingHeader => new TranslatableString(getKey(@"global_key_binding_header"), @"Global"); + + /// + /// "Song Select" + /// + public static LocalisableString SongSelectSection => new TranslatableString(getKey(@"song_select_section"), @"Song Select"); + + /// + /// "In Game" + /// + public static LocalisableString InGameSection => new TranslatableString(getKey(@"in_game_section"), @"In Game"); + + /// + /// "Audio" + /// + public static LocalisableString AudioSection => new TranslatableString(getKey(@"audio_section"), @"Audio"); + + /// + /// "Editor" + /// + public static LocalisableString EditorSection => new TranslatableString(getKey(@"editor_section"), @"Editor"); + + /// + /// "Reset all bindings in section" + /// + public static LocalisableString ResetSectionButton => new TranslatableString(getKey(@"reset_section_button"), @"Reset all bindings in section"); + + /// + /// "key configuration" + /// + public static LocalisableString KeyBindingPanelHeader => new TranslatableString(getKey(@"key_binding_panel_header"), @"key configuration"); + + /// + /// "Customise your keys!" + /// + public static LocalisableString KeyBindingPanelDescription => new TranslatableString(getKey(@"key_binding_panel_description"), @"Customise your keys!"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs index 9898a50320..3350ff4eaa 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Input.Bindings; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input { @@ -15,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input Icon = FontAwesome.Solid.Globe }; - public override string Header => "Global"; + public override LocalisableString Header => InputSettingsStrings.GlobalKeyBindingHeader; public GlobalKeyBindingsSection(GlobalActionContainer manager) { @@ -39,7 +40,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class SongSelectKeyBindingSubsection : KeyBindingsSubsection { - protected override LocalisableString Header => "Song Select"; + protected override LocalisableString Header => InputSettingsStrings.SongSelectSection; public SongSelectKeyBindingSubsection(GlobalActionContainer manager) : base(null) @@ -50,7 +51,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class InGameKeyBindingsSubsection : KeyBindingsSubsection { - protected override LocalisableString Header => "In Game"; + protected override LocalisableString Header => InputSettingsStrings.InGameSection; public InGameKeyBindingsSubsection(GlobalActionContainer manager) : base(null) @@ -61,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class AudioControlKeyBindingsSubsection : KeyBindingsSubsection { - protected override LocalisableString Header => "Audio"; + protected override LocalisableString Header => InputSettingsStrings.AudioSection; public AudioControlKeyBindingsSubsection(GlobalActionContainer manager) : base(null) @@ -72,7 +73,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class EditorKeyBindingsSubsection : KeyBindingsSubsection { - protected override LocalisableString Header => "Editor"; + protected override LocalisableString Header => InputSettingsStrings.EditorSection; public EditorKeyBindingsSubsection(GlobalActionContainer manager) : base(null) diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs index 7cdc739b7c..67f1bb8d3e 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs @@ -4,13 +4,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; +using osu.Game.Localisation; using osu.Game.Rulesets; namespace osu.Game.Overlays.Settings.Sections.Input { public class KeyBindingPanel : SettingsSubPanel { - protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); + protected override Drawable CreateHeader() => new SettingsHeader(InputSettingsStrings.KeyBindingPanelHeader, InputSettingsStrings.KeyBindingPanelDescription); [BackgroundDependencyLoader(permitNulls: true)] private void load(RulesetStore rulesets, GlobalActionContainer global) diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index 6e018597be..c38c516f21 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -20,6 +20,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input; using osu.Game.Input.Bindings; +using osu.Game.Localisation; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -385,7 +386,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { public CancelButton() { - Text = "Cancel"; + Text = CommonStrings.Cancel; Size = new Vector2(80, 20); } } @@ -394,7 +395,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { public ClearButton() { - Text = "Clear"; + Text = CommonStrings.Clear; Size = new Vector2(80, 20); } } diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs index d65684fd37..ef5ccae1a0 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs @@ -10,6 +10,7 @@ using osu.Game.Database; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Rulesets; +using osu.Game.Localisation; using osuTK; namespace osu.Game.Overlays.Settings.Sections.Input @@ -64,7 +65,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input [BackgroundDependencyLoader] private void load() { - Text = "Reset all bindings in section"; + Text = InputSettingsStrings.ResetSectionButton; RelativeSizeAxes = Axes.X; Width = 0.5f; Anchor = Anchor.TopCentre; diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs index 81a4d7eccd..5246051a4a 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Rulesets; @@ -15,7 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input Icon = OsuIcon.Hot }; - public override string Header => ruleset.Name; + public override LocalisableString Header => ruleset.Name; private readonly RulesetInfo ruleset; diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index 366f39388a..d282ba5318 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -11,6 +11,7 @@ using osu.Framework.Input.Handlers.Mouse; using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Platform; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Input; namespace osu.Game.Overlays.Settings.Sections @@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections { private readonly KeyBindingPanel keyConfig; - public override string Header => "Input"; + public override LocalisableString Header => InputSettingsStrings.InputSectionHeader; [Resolved] private GameHost host { get; set; } @@ -95,7 +96,7 @@ namespace osu.Game.Overlays.Settings.Sections { new SettingsCheckbox { - LabelText = "Enabled", + LabelText = CommonStrings.Enabled, Current = handler.Enabled }, }; From 7adf2bb64c3be39f920cb074781fe032af3d0e9b Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 10:48:29 +0800 Subject: [PATCH 032/366] Add UserInterfaceStrings --- osu.Game/Localisation/UserInterfaceStrings.cs | 114 ++++++++++++++++++ .../Sections/UserInterface/GeneralSettings.cs | 11 +- .../UserInterface/MainMenuSettings.cs | 17 ++- .../UserInterface/SongSelectSettings.cs | 15 +-- .../Settings/Sections/UserInterfaceSection.cs | 4 +- 5 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 osu.Game/Localisation/UserInterfaceStrings.cs diff --git a/osu.Game/Localisation/UserInterfaceStrings.cs b/osu.Game/Localisation/UserInterfaceStrings.cs new file mode 100644 index 0000000000..18a9257732 --- /dev/null +++ b/osu.Game/Localisation/UserInterfaceStrings.cs @@ -0,0 +1,114 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class UserInterfaceStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.UserInterface"; + + /// + /// "User Interface" + /// + public static LocalisableString UserInterfaceSectionHeader => new TranslatableString(getKey(@"user_interface_section_header"), @"User Interface"); + + /// + /// "General" + /// + public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General"); + + /// + /// "Rotate cursor when dragging" + /// + public static LocalisableString CursorRotation => new TranslatableString(getKey(@"cursor_rotation"), @"Rotate cursor when dragging"); + + /// + /// "Menu cursor size" + /// + public static LocalisableString MenuCursorSize => new TranslatableString(getKey(@"menu_cursor_size"), @"Menu cursor size"); + + /// + /// "Parallax" + /// + public static LocalisableString Parallax => new TranslatableString(getKey(@"parallax"), @"Parallax"); + + /// + /// "Hold-to-confirm activation time" + /// + public static LocalisableString HoldActivationDelay => new TranslatableString(getKey(@"hold_activation_delay"), @"Hold-to-confirm activation time"); + + /// + /// "Main Menu" + /// + public static LocalisableString MainMenuHeader => new TranslatableString(getKey(@"main_menu_header"), @"Main Menu"); + + /// + /// "Interface voices" + /// + public static LocalisableString InterfaceVoices => new TranslatableString(getKey(@"interface_voices"), @"Interface voices"); + + /// + /// "osu! music theme" + /// + public static LocalisableString OsuMusicTheme => new TranslatableString(getKey(@"osu_music_theme"), @"osu! music theme"); + + /// + /// "Intro sequence" + /// + public static LocalisableString IntroSequence => new TranslatableString(getKey(@"intro_sequence"), @"Intro sequence"); + + /// + /// "Background source" + /// + public static LocalisableString BackgroundSource => new TranslatableString(getKey(@"background_source"), @"Background source"); + + /// + /// "Seasonal backgrounds" + /// + public static LocalisableString SeasonalBackgrounds => new TranslatableString(getKey(@"seasonal_backgrounds"), @"Seasonal backgrounds"); + + /// + /// "Changes to this setting will only apply with an active osu!supporter tag." + /// + public static LocalisableString NotSupporterNote => new TranslatableString(getKey(@"not_supporter_note"), @"Changes to this setting will only apply with an active osu!supporter tag."); + + /// + /// "Song Select" + /// + public static LocalisableString SoneSelectHeader => new TranslatableString(getKey(@"song_select_header"), @"Song Select"); + + /// + /// "Right mouse drag to absolute scroll" + /// + public static LocalisableString RightMouseScroll => new TranslatableString(getKey(@"right_mouse_scroll"), @"Right mouse drag to absolute scroll"); + + /// + /// "Show converted beatmaps" + /// + public static LocalisableString ShowConvertedBeatmaps => new TranslatableString(getKey(@"show_converted_beatmaps"), @"Show converted beatmaps"); + + /// + /// "Display beatmaps from" + /// + public static LocalisableString StarsMinimum => new TranslatableString(getKey(@"stars_minimum"), @"Display beatmaps from"); + + /// + /// "up to" + /// + public static LocalisableString StarsMaximum => new TranslatableString(getKey(@"stars_maximum"), @"up to"); + + /// + /// "Random selection algorithm" + /// + public static LocalisableString RandomSelectionAlgorithm => new TranslatableString(getKey(@"random_selection_algorithm"), @"Random selection algorithm"); + + /// + /// "no limit" + /// + public static LocalisableString NoLimit => new TranslatableString(getKey(@"no_limit"), @"no limit"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index 4b26645ef3..b26363a9da 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -6,12 +6,13 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.UserInterface { public class GeneralSettings : SettingsSubsection { - protected override LocalisableString Header => "General"; + protected override LocalisableString Header => UserInterfaceStrings.GeneralHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -20,23 +21,23 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { new SettingsCheckbox { - LabelText = "Rotate cursor when dragging", + LabelText = UserInterfaceStrings.CursorRotation, Current = config.GetBindable(OsuSetting.CursorRotation) }, new SettingsSlider { - LabelText = "Menu cursor size", + LabelText = UserInterfaceStrings.MenuCursorSize, Current = config.GetBindable(OsuSetting.MenuCursorSize), KeyboardStep = 0.01f }, new SettingsCheckbox { - LabelText = "Parallax", + LabelText = UserInterfaceStrings.Parallax, Current = config.GetBindable(OsuSetting.MenuParallax) }, new SettingsSlider { - LabelText = "Hold-to-confirm activation time", + LabelText = UserInterfaceStrings.HoldActivationDelay, Current = config.GetBindable(OsuSetting.UIHoldActivationDelay), KeyboardStep = 50 }, diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index 81bbcbb54a..976893bf0a 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Users; @@ -13,7 +14,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { public class MainMenuSettings : SettingsSubsection { - protected override LocalisableString Header => "Main Menu"; + protected override LocalisableString Header => UserInterfaceStrings.MainMenuHeader; private IBindable user; @@ -28,27 +29,27 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { new SettingsCheckbox { - LabelText = "Interface voices", + LabelText = UserInterfaceStrings.InterfaceVoices, Current = config.GetBindable(OsuSetting.MenuVoice) }, new SettingsCheckbox { - LabelText = "osu! music theme", + LabelText = UserInterfaceStrings.OsuMusicTheme, Current = config.GetBindable(OsuSetting.MenuMusic) }, new SettingsEnumDropdown { - LabelText = "Intro sequence", + LabelText = UserInterfaceStrings.IntroSequence, Current = config.GetBindable(OsuSetting.IntroSequence), }, backgroundSourceDropdown = new SettingsEnumDropdown { - LabelText = "Background source", + LabelText = UserInterfaceStrings.BackgroundSource, Current = config.GetBindable(OsuSetting.MenuBackgroundSource), }, new SettingsEnumDropdown { - LabelText = "Seasonal backgrounds", + LabelText = UserInterfaceStrings.SeasonalBackgrounds, Current = config.GetBindable(OsuSetting.SeasonalBackgroundMode), } }; @@ -60,9 +61,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface user.BindValueChanged(u => { - const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag."; - - backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? not_supporter_note : string.Empty; + backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? UserInterfaceStrings.NotSupporterNote : string.Empty; }, true); } } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index 587155eb0d..8596cecbb8 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.UserInterface { @@ -16,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface private Bindable minStars; private Bindable maxStars; - protected override LocalisableString Header => "Song Select"; + protected override LocalisableString Header => UserInterfaceStrings.SoneSelectHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -31,31 +32,31 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { new SettingsCheckbox { - LabelText = "Right mouse drag to absolute scroll", + LabelText = UserInterfaceStrings.RightMouseScroll, Current = config.GetBindable(OsuSetting.SongSelectRightMouseScroll), }, new SettingsCheckbox { - LabelText = "Show converted beatmaps", + LabelText = UserInterfaceStrings.ShowConvertedBeatmaps, Current = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), }, new SettingsSlider { - LabelText = "Display beatmaps from", + LabelText = UserInterfaceStrings.StarsMinimum, Current = config.GetBindable(OsuSetting.DisplayStarsMinimum), KeyboardStep = 0.1f, Keywords = new[] { "minimum", "maximum", "star", "difficulty" } }, new SettingsSlider { - LabelText = "up to", + LabelText = UserInterfaceStrings.StarsMaximum, Current = config.GetBindable(OsuSetting.DisplayStarsMaximum), KeyboardStep = 0.1f, Keywords = new[] { "minimum", "maximum", "star", "difficulty" } }, new SettingsEnumDropdown { - LabelText = "Random selection algorithm", + LabelText = UserInterfaceStrings.RandomSelectionAlgorithm, Current = config.GetBindable(OsuSetting.RandomSelectAlgorithm), } }; @@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface private class MaximumStarsSlider : StarsSlider { - public override LocalisableString TooltipText => Current.IsDefault ? "no limit" : base.TooltipText; + public override LocalisableString TooltipText => Current.IsDefault ? UserInterfaceStrings.NoLimit : base.TooltipText; } private class StarsSlider : OsuSliderBar diff --git a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs index 718fea5f2b..6228c4c99a 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.UserInterface; namespace osu.Game.Overlays.Settings.Sections { public class UserInterfaceSection : SettingsSection { - public override string Header => "User Interface"; + public override LocalisableString Header => UserInterfaceStrings.UserInterfaceSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 31ffaf15d4866275f1c86c0dbecd67af5eba59ff Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 11:11:22 +0800 Subject: [PATCH 033/366] Add GameplaySettingsStrings --- .../Localisation/GameplaySettingsStrings.cs | 95 +++++++++++++++++++ .../Sections/Gameplay/GeneralSettings.cs | 27 +++--- .../Sections/Gameplay/ModsSettings.cs | 5 +- .../Settings/Sections/GameplaySection.cs | 4 +- 4 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Localisation/GameplaySettingsStrings.cs diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs new file mode 100644 index 0000000000..172387bbb8 --- /dev/null +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -0,0 +1,95 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class GameplaySettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.GameplaySettings"; + + /// + /// "Gameplay" + /// + public static LocalisableString GameplaySectionHeader => new TranslatableString(getKey(@"gameplay_section_header"), @"Gameplay"); + + /// + /// "General" + /// + public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General"); + + /// + /// "Background dim" + /// + public static LocalisableString Dim => new TranslatableString(getKey(@"dim"), @"Background dim"); + + /// + /// "Background blur" + /// + public static LocalisableString Blur => new TranslatableString(getKey(@"blur"), @"Background blur"); + + /// + /// "Lighten playfield during breaks" + /// + public static LocalisableString LightenDuringBreaks => new TranslatableString(getKey(@"lighten_during_breaks"), @"Lighten playfield during breaks"); + + /// + /// "HUD overlay visibility mode" + /// + public static LocalisableString HUDVisibilityMode => new TranslatableString(getKey(@"hud_visibility_mode"), @"HUD overlay visibility mode"); + + /// + /// "Show difficulty graph on progress bar" + /// + public static LocalisableString ShowProgressGraph => new TranslatableString(getKey(@"show_progress_graph"), @"Show difficulty graph on progress bar"); + + /// + /// "Show health display even when you can't fail" + /// + public static LocalisableString ShowHealthDisplayWhenCantFail => new TranslatableString(getKey(@"show_health_display_when_cant_fail"), @"Show health display even when you can't fail"); + + /// + /// "Fade playfield to red when health is low" + /// + public static LocalisableString FadePlayfieldWhenHealthLow => new TranslatableString(getKey(@"fade_playfield_when_health_low"), @"Fade playfield to red when health is low"); + + /// + /// "Always show key overlay" + /// + public static LocalisableString KeyOverlay => new TranslatableString(getKey(@"key_overlay"), @"Always show key overlay"); + + /// + /// "Positional hitsounds" + /// + public static LocalisableString PositionalHitsounds => new TranslatableString(getKey(@"positional_hitsounds"), @"Positional hitsounds"); + + /// + /// "Always play first combo break sound" + /// + public static LocalisableString AlwaysPlayFirstComboBreak => new TranslatableString(getKey(@"always_play_first_combo_break"), @"Always play first combo break sound"); + + /// + /// "Score display mode" + /// + public static LocalisableString ScoreDisplayMode => new TranslatableString(getKey(@"score_display_mode"), @"Score display mode"); + + /// + /// "Disable Windows key during gameplay" + /// + public static LocalisableString DisableWinKey => new TranslatableString(getKey(@"disable_win_key"), @"Disable Windows key during gameplay"); + + /// + /// "Mods" + /// + public static LocalisableString ModsHeader => new TranslatableString(getKey(@"mods_header"), @"Mods"); + + /// + /// "Increase visibility of first object when visual impairment mods are enabled" + /// + public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled"); + + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 353292606f..efb586fdca 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -6,13 +6,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Rulesets.Scoring; namespace osu.Game.Overlays.Settings.Sections.Gameplay { public class GeneralSettings : SettingsSubsection { - protected override LocalisableString Header => "General"; + protected override LocalisableString Header => GameplaySettingsStrings.GeneralHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -21,62 +22,62 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsSlider { - LabelText = "Background dim", + LabelText = GameplaySettingsStrings.Dim, Current = config.GetBindable(OsuSetting.DimLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = "Background blur", + LabelText = GameplaySettingsStrings.Blur, Current = config.GetBindable(OsuSetting.BlurLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsCheckbox { - LabelText = "Lighten playfield during breaks", + LabelText = GameplaySettingsStrings.LightenDuringBreaks, Current = config.GetBindable(OsuSetting.LightenDuringBreaks) }, new SettingsEnumDropdown { - LabelText = "HUD overlay visibility mode", + LabelText = GameplaySettingsStrings.HUDVisibilityMode, Current = config.GetBindable(OsuSetting.HUDVisibilityMode) }, new SettingsCheckbox { - LabelText = "Show difficulty graph on progress bar", + LabelText = GameplaySettingsStrings.ShowProgressGraph, Current = config.GetBindable(OsuSetting.ShowProgressGraph) }, new SettingsCheckbox { - LabelText = "Show health display even when you can't fail", + LabelText = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail, Current = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), Keywords = new[] { "hp", "bar" } }, new SettingsCheckbox { - LabelText = "Fade playfield to red when health is low", + LabelText = GameplaySettingsStrings.FadePlayfieldWhenHealthLow, Current = config.GetBindable(OsuSetting.FadePlayfieldWhenHealthLow), }, new SettingsCheckbox { - LabelText = "Always show key overlay", + LabelText = GameplaySettingsStrings.KeyOverlay, Current = config.GetBindable(OsuSetting.KeyOverlay) }, new SettingsCheckbox { - LabelText = "Positional hitsounds", + LabelText = GameplaySettingsStrings.PositionalHitsounds, Current = config.GetBindable(OsuSetting.PositionalHitSounds) }, new SettingsCheckbox { - LabelText = "Always play first combo break sound", + LabelText = GameplaySettingsStrings.AlwaysPlayFirstComboBreak, Current = config.GetBindable(OsuSetting.AlwaysPlayFirstComboBreak) }, new SettingsEnumDropdown { - LabelText = "Score display mode", + LabelText = GameplaySettingsStrings.ScoreDisplayMode, Current = config.GetBindable(OsuSetting.ScoreDisplayMode), Keywords = new[] { "scoring" } }, @@ -86,7 +87,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Add(new SettingsCheckbox { - LabelText = "Disable Windows key during gameplay", + LabelText = GameplaySettingsStrings.DisableWinKey, Current = config.GetBindable(OsuSetting.GameplayDisableWinKey) }); } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index ec9ddde2da..dfa060e8d5 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -6,12 +6,13 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay { public class ModsSettings : SettingsSubsection { - protected override LocalisableString Header => "Mods"; + protected override LocalisableString Header => GameplaySettingsStrings.ModsHeader; public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "mod" }); @@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsCheckbox { - LabelText = "Increase visibility of first object when visual impairment mods are enabled", + LabelText = GameplaySettingsStrings.IncreaseFirstObjectVisibility, Current = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), }, }; diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index acb94a6a01..42d9d48d73 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -9,12 +9,14 @@ using osu.Game.Rulesets; using System.Linq; using osu.Framework.Graphics.Sprites; using osu.Framework.Logging; +using osu.Framework.Localisation; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections { public class GameplaySection : SettingsSection { - public override string Header => "Gameplay"; + public override LocalisableString Header => GameplaySettingsStrings.GameplaySectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 61502e977afcaa4731fb8d6f2b3d2f6c46eb11b8 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 11:40:22 +0800 Subject: [PATCH 034/366] Add SkinSettingsStrings --- osu.Game/Localisation/SkinSettingsStrings.cs | 54 +++++++++++++++++++ .../Overlays/Settings/Sections/SkinSection.cs | 17 +++--- 2 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Localisation/SkinSettingsStrings.cs diff --git a/osu.Game/Localisation/SkinSettingsStrings.cs b/osu.Game/Localisation/SkinSettingsStrings.cs new file mode 100644 index 0000000000..848c01b93a --- /dev/null +++ b/osu.Game/Localisation/SkinSettingsStrings.cs @@ -0,0 +1,54 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class SkinSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.SkinSettings"; + + /// + /// "Skin" + /// + public static LocalisableString SkinSectionHeader => new TranslatableString(getKey(@"skin_section_header"), @"Skin"); + + /// + /// "Skin layout editor" + /// + public static LocalisableString SkinLayoutEditor => new TranslatableString(getKey(@"skin_layout_editor"), @"Skin layout editor"); + + /// + /// "Gameplay cursor size" + /// + public static LocalisableString CursorSize => new TranslatableString(getKey(@"cursor_size"), @"Gameplay cursor size"); + + /// + /// "Adjust gameplay cursor size based on current beatmap" + /// + public static LocalisableString AutoCursorSize => new TranslatableString(getKey(@"auto_cursor_size"), @"Adjust gameplay cursor size based on current beatmap"); + + /// + /// "Beatmap skins" + /// + public static LocalisableString BeatmapSkins => new TranslatableString(getKey(@"beatmap_skins"), @"Beatmap skins"); + + /// + /// "Beatmap colours" + /// + public static LocalisableString BeatmapColours => new TranslatableString(getKey(@"beatmap_colours"), @"Beatmap colours"); + + /// + /// "Beatmap hitsounds" + /// + public static LocalisableString BeatmapHitsounds => new TranslatableString(getKey(@"beatmap_hitsounds"), @"Beatmap hitsounds"); + + /// + /// "Export selected skin" + /// + public static LocalisableString ExportSkinButton => new TranslatableString(getKey(@"export_skin_button"), @"Export selected skin"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 9f3543d059..007302c584 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -13,6 +13,7 @@ using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Skinning; using osu.Game.Skinning.Editor; using osuTK; @@ -23,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections { private SkinSettingsDropdown skinDropdown; - public override string Header => "Skin"; + public override LocalisableString Header => SkinSettingsStrings.SkinSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { @@ -69,34 +70,34 @@ namespace osu.Game.Overlays.Settings.Sections skinDropdown = new SkinSettingsDropdown(), new SettingsButton { - Text = "Skin layout editor", + Text = SkinSettingsStrings.SkinLayoutEditor, Action = () => skinEditor?.Toggle(), }, new ExportSkinButton(), new SettingsSlider { - LabelText = "Gameplay cursor size", + LabelText = SkinSettingsStrings.CursorSize, Current = config.GetBindable(OsuSetting.GameplayCursorSize), KeyboardStep = 0.01f }, new SettingsCheckbox { - LabelText = "Adjust gameplay cursor size based on current beatmap", + LabelText = SkinSettingsStrings.AutoCursorSize, Current = config.GetBindable(OsuSetting.AutoCursorSize) }, new SettingsCheckbox { - LabelText = "Beatmap skins", + LabelText = SkinSettingsStrings.BeatmapSkins, Current = config.GetBindable(OsuSetting.BeatmapSkins) }, new SettingsCheckbox { - LabelText = "Beatmap colours", + LabelText = SkinSettingsStrings.BeatmapColours, Current = config.GetBindable(OsuSetting.BeatmapColours) }, new SettingsCheckbox { - LabelText = "Beatmap hitsounds", + LabelText = SkinSettingsStrings.BeatmapHitsounds, Current = config.GetBindable(OsuSetting.BeatmapHitsounds) }, }; @@ -200,7 +201,7 @@ namespace osu.Game.Overlays.Settings.Sections [BackgroundDependencyLoader] private void load() { - Text = "Export selected skin"; + Text = SkinSettingsStrings.ExportSkinButton; Action = export; currentSkin = skins.CurrentSkin.GetBoundCopy(); From 9d391ad13817df8a81c5733fa7ee4f759852e095 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 11:57:51 +0800 Subject: [PATCH 035/366] Add OnlineSettingsStrings --- .../Localisation/OnlineSettingsStrings.cs | 69 +++++++++++++++++++ .../Online/AlertsAndPrivacySettings.cs | 7 +- .../Sections/Online/IntegrationSettings.cs | 5 +- .../Settings/Sections/Online/WebSettings.cs | 11 +-- .../Settings/Sections/OnlineSection.cs | 4 +- 5 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Localisation/OnlineSettingsStrings.cs diff --git a/osu.Game/Localisation/OnlineSettingsStrings.cs b/osu.Game/Localisation/OnlineSettingsStrings.cs new file mode 100644 index 0000000000..0ef98a720c --- /dev/null +++ b/osu.Game/Localisation/OnlineSettingsStrings.cs @@ -0,0 +1,69 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class OnlineSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.OnlineSettings"; + + /// + /// "Online" + /// + public static LocalisableString OnlineSectionHeader => new TranslatableString(getKey(@"online_section_header"), @"Online"); + + /// + /// "Alerts and Privacy" + /// + public static LocalisableString AlertsAndPrivacyHeader => new TranslatableString(getKey(@"alerts_and_privacy_header"), @"Alerts and Privacy"); + + /// + /// "Show a notification when someone mentions your name" + /// + public static LocalisableString NotifyOnMentioned => new TranslatableString(getKey(@"notify_on_mentioned"), @"Show a notification when someone mentions your name"); + + /// + /// "Show a notification when you receive a private message" + /// + public static LocalisableString NotifyOnPM => new TranslatableString(getKey(@"notify_on_pm"), @"Show a notification when you receive a private message"); + + /// + /// "Integrations" + /// + public static LocalisableString IntegrationHeader => new TranslatableString(getKey(@"integration_header"), @"Integrations"); + + /// + /// "Discord Rich Presence" + /// + public static LocalisableString DiscordRichPresence => new TranslatableString(getKey(@"discord_rich_presence"), @"Discord Rich Presence"); + + /// + /// "Web" + /// + public static LocalisableString WebHeader => new TranslatableString(getKey(@"web_header"), @"Web"); + + /// + /// "Warn about opening external links" + /// + public static LocalisableString ExternalLinkWarning => new TranslatableString(getKey(@"external_link_warning"), @"Warn about opening external links"); + + /// + /// "Prefer downloads without video" + /// + public static LocalisableString PreferNoVideo => new TranslatableString(getKey(@"prefer_no_video"), @"Prefer downloads without video"); + + /// + /// "Automatically download beatmaps when spectating" + /// + public static LocalisableString AutomaticallyDownload => new TranslatableString(getKey(@"automatically_download"), @"Automatically download beatmaps when spectating"); + + /// + /// "Show explicit content in search results" + /// + public static LocalisableString ShowExplicitContent => new TranslatableString(getKey(@"show_explicit_content"), @"Show explicit content in search results"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs index 3a2de2ee36..1728b565c2 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs @@ -5,12 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { public class AlertsAndPrivacySettings : SettingsSubsection { - protected override LocalisableString Header => "Alerts and Privacy"; + protected override LocalisableString Header => OnlineSettingsStrings.AlertsAndPrivacyHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -19,12 +20,12 @@ namespace osu.Game.Overlays.Settings.Sections.Online { new SettingsCheckbox { - LabelText = "Show a notification when someone mentions your name", + LabelText = OnlineSettingsStrings.NotifyOnMentioned, Current = config.GetBindable(OsuSetting.NotifyOnUsernameMentioned) }, new SettingsCheckbox { - LabelText = "Show a notification when you receive a private message", + LabelText = OnlineSettingsStrings.NotifyOnPM, Current = config.GetBindable(OsuSetting.NotifyOnPrivateMessage) }, }; diff --git a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs index f2012f0d9c..f2a516feef 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs @@ -5,12 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { public class IntegrationSettings : SettingsSubsection { - protected override LocalisableString Header => "Integrations"; + protected override LocalisableString Header => OnlineSettingsStrings.IntegrationHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -19,7 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online { new SettingsEnumDropdown { - LabelText = "Discord Rich Presence", + LabelText = OnlineSettingsStrings.DiscordRichPresence, Current = config.GetBindable(OsuSetting.DiscordRichPresence) } }; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index 89e7b096f3..4200ddda3d 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -5,12 +5,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online { public class WebSettings : SettingsSubsection { - protected override LocalisableString Header => "Web"; + protected override LocalisableString Header => OnlineSettingsStrings.WebHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) @@ -19,24 +20,24 @@ namespace osu.Game.Overlays.Settings.Sections.Online { new SettingsCheckbox { - LabelText = "Warn about opening external links", + LabelText = OnlineSettingsStrings.ExternalLinkWarning, Current = config.GetBindable(OsuSetting.ExternalLinkWarning) }, new SettingsCheckbox { - LabelText = "Prefer downloads without video", + LabelText = OnlineSettingsStrings.PreferNoVideo, Keywords = new[] { "no-video" }, Current = config.GetBindable(OsuSetting.PreferNoVideo) }, new SettingsCheckbox { - LabelText = "Automatically download beatmaps when spectating", + LabelText = OnlineSettingsStrings.AutomaticallyDownload, Keywords = new[] { "spectator" }, Current = config.GetBindable(OsuSetting.AutomaticallyDownloadWhenSpectating), }, new SettingsCheckbox { - LabelText = "Show explicit content in search results", + LabelText = OnlineSettingsStrings.ShowExplicitContent, Keywords = new[] { "nsfw", "18+", "offensive" }, Current = config.GetBindable(OsuSetting.ShowOnlineExplicitContent), } diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index 680d11f7da..8b523b90b9 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Online; namespace osu.Game.Overlays.Settings.Sections { public class OnlineSection : SettingsSection { - public override string Header => "Online"; + public override LocalisableString Header => OnlineSettingsStrings.OnlineSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From ac52b891489afc591ee4d5b08c54547c5c43de52 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 12:26:42 +0800 Subject: [PATCH 036/366] Add Maintenance and Debug SettingsStrings --- osu.Game/Localisation/DebugSettingsStrings.cs | 49 ++++++++++++ .../MaintenanceSettingsStrings.cs | 74 +++++++++++++++++++ .../Sections/Debug/GeneralSettings.cs | 9 ++- .../Settings/Sections/Debug/MemorySettings.cs | 5 +- .../Settings/Sections/DebugSection.cs | 4 +- .../Maintenance/DirectorySelectScreen.cs | 3 +- .../Sections/Maintenance/GeneralSettings.cs | 21 +++--- .../Settings/Sections/MaintenanceSection.cs | 4 +- 8 files changed, 150 insertions(+), 19 deletions(-) create mode 100644 osu.Game/Localisation/DebugSettingsStrings.cs create mode 100644 osu.Game/Localisation/MaintenanceSettingsStrings.cs diff --git a/osu.Game/Localisation/DebugSettingsStrings.cs b/osu.Game/Localisation/DebugSettingsStrings.cs new file mode 100644 index 0000000000..dd21739096 --- /dev/null +++ b/osu.Game/Localisation/DebugSettingsStrings.cs @@ -0,0 +1,49 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class DebugSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.DebugSettings"; + + /// + /// "Debug" + /// + public static LocalisableString DebugSectionHeader => new TranslatableString(getKey(@"debug_section_header"), @"Debug"); + + /// + /// "General" + /// + public static LocalisableString GeneralHeader => new TranslatableString(getKey(@"general_header"), @"General"); + + /// + /// "Show log overlay" + /// + public static LocalisableString ShowLogOverlay => new TranslatableString(getKey(@"show_log_overlay"), @"Show log overlay"); + + /// + /// "Bypass front-to-back render pass" + /// + public static LocalisableString BypassFrontToBackPass => new TranslatableString(getKey(@"bypass_front_to_back_pass"), @"Bypass front-to-back render pass"); + + /// + /// "Import files" + /// + public static LocalisableString ImportFiles => new TranslatableString(getKey(@"import_files"), @"Import files"); + + /// + /// "Memory" + /// + public static LocalisableString MemoryHeader => new TranslatableString(getKey(@"memory_header"), @"Memory"); + + /// + /// "Clear all caches" + /// + public static LocalisableString ClearAllCaches => new TranslatableString(getKey(@"clear_all_caches"), @"Clear all caches"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Localisation/MaintenanceSettingsStrings.cs b/osu.Game/Localisation/MaintenanceSettingsStrings.cs new file mode 100644 index 0000000000..a0e1a9ddab --- /dev/null +++ b/osu.Game/Localisation/MaintenanceSettingsStrings.cs @@ -0,0 +1,74 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class MaintenanceSettingsStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.MaintenanceSettings"; + + /// + /// "Maintenance" + /// + public static LocalisableString MaintenanceSectionHeader => new TranslatableString(getKey(@"maintenance_section_header"), @"Maintenance"); + + /// + /// "Select directory" + /// + public static LocalisableString SelectDirectory => new TranslatableString(getKey(@"select_directory"), @"Select directory"); + + /// + /// "Import beatmaps from stable" + /// + public static LocalisableString ImportBeatmapsFromStable => new TranslatableString(getKey(@"import_beatmaps_from_stable"), @"Import beatmaps from stable"); + + /// + /// "Delete ALL beatmaps" + /// + public static LocalisableString DeleteAllBeatmaps => new TranslatableString(getKey(@"delete_all_beatmaps"), @"Delete ALL beatmaps"); + + /// + /// "Import scores from stable" + /// + public static LocalisableString ImportScoresFromStable => new TranslatableString(getKey(@"import_scores_from_stable"), @"Import scores from stable"); + + /// + /// "Delete ALL scores" + /// + public static LocalisableString DeleteAllScores => new TranslatableString(getKey(@"delete_all_scores"), @"Delete ALL scores"); + + /// + /// "Import skins from stable" + /// + public static LocalisableString ImportSkinsFromStable => new TranslatableString(getKey(@"import_skins_from_stable"), @"Import skins from stable"); + + /// + /// "Delete ALL skins" + /// + public static LocalisableString DeleteAllSkins => new TranslatableString(getKey(@"delete_all_skins"), @"Delete ALL skins"); + + /// + /// "Import collections from stable" + /// + public static LocalisableString ImportCollectionsFromStable => new TranslatableString(getKey(@"import_collections_from_stable"), @"Import collections from stable"); + + /// + /// "Delete ALL collections" + /// + public static LocalisableString DeleteAllCollections => new TranslatableString(getKey(@"delete_all_collections"), @"Delete ALL collections"); + + /// + /// "Restore all hidden difficulties" + /// + public static LocalisableString RestoreAllHiddenDifficulties => new TranslatableString(getKey(@"restore_all_hidden_difficulties"), @"Restore all hidden difficulties"); + + /// + /// "Restore all recently deleted beatmaps" + /// + public static LocalisableString RestoreAllRecentlyDeletedBeatmaps => new TranslatableString(getKey(@"restore_all_recently_deleted_beatmaps"), @"Restore all recently deleted beatmaps"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs index 2b868cab85..25e20911b8 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs @@ -6,13 +6,14 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Screens; +using osu.Game.Localisation; using osu.Game.Screens.Import; namespace osu.Game.Overlays.Settings.Sections.Debug { public class GeneralSettings : SettingsSubsection { - protected override LocalisableString Header => "General"; + protected override LocalisableString Header => DebugSettingsStrings.GeneralHeader; [BackgroundDependencyLoader(true)] private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig, OsuGame game) @@ -21,18 +22,18 @@ namespace osu.Game.Overlays.Settings.Sections.Debug { new SettingsCheckbox { - LabelText = "Show log overlay", + LabelText = DebugSettingsStrings.ShowLogOverlay, Current = frameworkConfig.GetBindable(FrameworkSetting.ShowLogOverlay) }, new SettingsCheckbox { - LabelText = "Bypass front-to-back render pass", + LabelText = DebugSettingsStrings.BypassFrontToBackPass, Current = config.GetBindable(DebugSetting.BypassFrontToBackPass) } }; Add(new SettingsButton { - Text = "Import files", + Text = DebugSettingsStrings.ImportFiles, Action = () => game?.PerformFromScreen(menu => menu.Push(new FileImportScreen())) }); } diff --git a/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs index bf7fb351c0..07fb0aca5a 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/MemorySettings.cs @@ -6,12 +6,13 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Debug { public class MemorySettings : SettingsSubsection { - protected override LocalisableString Header => "Memory"; + protected override LocalisableString Header => DebugSettingsStrings.MemoryHeader; [BackgroundDependencyLoader] private void load(FrameworkDebugConfigManager config, GameHost host) @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug { new SettingsButton { - Text = "Clear all caches", + Text = DebugSettingsStrings.ClearAllCaches, Action = host.Collect }, }; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index 44d4088972..aa85ec920c 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Debug; namespace osu.Game.Overlays.Settings.Sections { public class DebugSection : SettingsSection { - public override string Header => "Debug"; + public override LocalisableString Header => DebugSettingsStrings.DebugSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs index 5392ba5d93..e509cac2f1 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs @@ -14,6 +14,7 @@ using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; using osu.Framework.Screens; using osu.Game.Graphics.Containers; +using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Maintenance { @@ -104,7 +105,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Origin = Anchor.Centre, Width = 300, Margin = new MarginPadding(10), - Text = "Select directory", + Text = MaintenanceSettingsStrings.SelectDirectory, Action = () => OnSelection(directorySelector.CurrentPath.Value) }, } diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index b9a408b1f8..803c8332c1 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps; using osu.Game.Collections; using osu.Game.Database; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Scoring; using osu.Game.Skinning; @@ -37,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importBeatmapsButton = new SettingsButton { - Text = "Import beatmaps from stable", + Text = MaintenanceSettingsStrings.ImportBeatmapsFromStable, Action = () => { importBeatmapsButton.Enabled.Value = false; @@ -48,7 +49,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Add(deleteBeatmapsButton = new DangerousSettingsButton { - Text = "Delete ALL beatmaps", + Text = MaintenanceSettingsStrings.DeleteAllBeatmaps, Action = () => { dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => @@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importScoresButton = new SettingsButton { - Text = "Import scores from stable", + Text = MaintenanceSettingsStrings.ImportScoresFromStable, Action = () => { importScoresButton.Enabled.Value = false; @@ -74,7 +75,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Add(deleteScoresButton = new DangerousSettingsButton { - Text = "Delete ALL scores", + Text = MaintenanceSettingsStrings.DeleteAllScores, Action = () => { dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => @@ -89,7 +90,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importSkinsButton = new SettingsButton { - Text = "Import skins from stable", + Text = MaintenanceSettingsStrings.ImportSkinsFromStable, Action = () => { importSkinsButton.Enabled.Value = false; @@ -100,7 +101,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Add(deleteSkinsButton = new DangerousSettingsButton { - Text = "Delete ALL skins", + Text = MaintenanceSettingsStrings.DeleteAllSkins, Action = () => { dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => @@ -117,7 +118,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Add(importCollectionsButton = new SettingsButton { - Text = "Import collections from stable", + Text = MaintenanceSettingsStrings.ImportCollectionsFromStable, Action = () => { importCollectionsButton.Enabled.Value = false; @@ -128,7 +129,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Add(new DangerousSettingsButton { - Text = "Delete ALL collections", + Text = MaintenanceSettingsStrings.DeleteAllCollections, Action = () => { dialogOverlay?.Push(new DeleteAllBeatmapsDialog(collectionManager.DeleteAll)); @@ -140,7 +141,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { restoreButton = new SettingsButton { - Text = "Restore all hidden difficulties", + Text = MaintenanceSettingsStrings.RestoreAllHiddenDifficulties, Action = () => { restoreButton.Enabled.Value = false; @@ -153,7 +154,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance }, undeleteButton = new SettingsButton { - Text = "Restore all recently deleted beatmaps", + Text = MaintenanceSettingsStrings.RestoreAllRecentlyDeletedBeatmaps, Action = () => { undeleteButton.Enabled.Value = false; diff --git a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs index 73c88b8e71..fa0c06167b 100644 --- a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs @@ -3,6 +3,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings.Sections.Maintenance; using osuTK; @@ -10,7 +12,7 @@ namespace osu.Game.Overlays.Settings.Sections { public class MaintenanceSection : SettingsSection { - public override string Header => "Maintenance"; + public override LocalisableString Header => MaintenanceSettingsStrings.MaintenanceSectionHeader; public override Drawable CreateIcon() => new SpriteIcon { From 3f434c8474f19be27afc46254461bd5bfceeadfe Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 12 Aug 2021 13:42:16 +0800 Subject: [PATCH 037/366] Resolve code quality issue --- osu.Game/Localisation/GameplaySettingsStrings.cs | 1 - osu.sln.DotSettings | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index 172387bbb8..4354272ab5 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -89,7 +89,6 @@ namespace osu.Game.Localisation /// public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled"); - private static string getKey(string key) => $"{prefix}:{key}"; } } diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 139ee02b96..d884ea31c5 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -304,6 +304,7 @@ AABB API BPM + FPS GC GL GLSL From f4591b01d7a4bb4f8e6ef8a9eb02bd47fe527a39 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 15:21:00 +0900 Subject: [PATCH 038/366] Add test step to show leaderboard in expanded state by default --- osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index 17fe09f2c6..950f255a02 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -40,6 +40,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); AddStep("add local player", () => createLeaderboardScore(playerScore, new User { Username = "You", Id = 3 }, true)); + AddStep("toggle expanded", () => leaderboard.Expanded.Value = !leaderboard.Expanded.Value); AddSliderStep("set player score", 50, 5000000, 1222333, v => playerScore.Value = v); } From 68dbbc17e88f89ca19cdd58436811e308f4411fa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 16:17:14 +0900 Subject: [PATCH 039/366] Add support for automatic scrolling in gameplay leaderboard --- .../Gameplay/TestSceneGameplayLeaderboard.cs | 21 ++- .../Screens/Play/HUD/GameplayLeaderboard.cs | 131 ++++++++++++++++-- .../Play/HUD/GameplayLeaderboardScore.cs | 13 +- 3 files changed, 144 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index 950f255a02..10257f9027 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -84,6 +84,23 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("add frenzibyte", () => createRandomScore(new User { Username = "frenzibyte", Id = 14210502 })); } + [Test] + public void TestMaxHeight() + { + int playerNumber = 1; + AddRepeatStep("add 3 other players", () => createRandomScore(new User { Username = $"Player {playerNumber++}" }), 3); + checkHeight(4); + + AddRepeatStep("add 4 other players", () => createRandomScore(new User { Username = $"Player {playerNumber++}" }), 4); + checkHeight(8); + + AddRepeatStep("add 4 other players", () => createRandomScore(new User { Username = $"Player {playerNumber++}" }), 4); + checkHeight(8); + + void checkHeight(int panelCount) + => AddAssert($"leaderboard height is {panelCount} panels high", () => leaderboard.DrawHeight == (GameplayLeaderboardScore.PANEL_HEIGHT + leaderboard.Spacing) * panelCount); + } + private void createRandomScore(User user) => createLeaderboardScore(new BindableDouble(RNG.Next(0, 5_000_000)), user); private void createLeaderboardScore(BindableDouble score, User user, bool isTracked = false) @@ -94,9 +111,11 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestGameplayLeaderboard : GameplayLeaderboard { + public float Spacing => Flow.Spacing.Y; + public bool CheckPositionByUsername(string username, int? expectedPosition) { - var scoreItem = this.FirstOrDefault(i => i.User?.Username == username); + var scoreItem = Flow.FirstOrDefault(i => i.User?.Username == username); return scoreItem != null && scoreItem.ScorePosition == expectedPosition; } diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 63cb4f89f5..807289d664 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -6,29 +6,58 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Caching; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; using osu.Game.Users; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD { - public class GameplayLeaderboard : FillFlowContainer + public class GameplayLeaderboard : CompositeDrawable { + private readonly int maxPanels; private readonly Cached sorting = new Cached(); public Bindable Expanded = new Bindable(); - public GameplayLeaderboard() + protected readonly FillFlowContainer Flow; + + private bool requiresScroll; + private readonly OsuScrollContainer scroll; + + private GameplayLeaderboardScore trackedScore; + + /// + /// Create a new leaderboard. + /// + /// The maximum panels to show at once. Defines the maximum height of this component. + public GameplayLeaderboard(int maxPanels = 8) { + this.maxPanels = maxPanels; + Width = GameplayLeaderboardScore.EXTENDED_WIDTH + GameplayLeaderboardScore.SHEAR_WIDTH; - Direction = FillDirection.Vertical; - - Spacing = new Vector2(2.5f); - - LayoutDuration = 250; - LayoutEasing = Easing.OutQuint; + InternalChildren = new Drawable[] + { + scroll = new ManualScrollScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = Flow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + X = GameplayLeaderboardScore.SHEAR_WIDTH, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(2.5f), + LayoutDuration = 450, + LayoutEasing = Easing.OutQuint, + } + } + }; } protected override void LoadComplete() @@ -50,22 +79,83 @@ namespace osu.Game.Screens.Play.HUD { var drawable = CreateLeaderboardScoreDrawable(user, isTracked); + if (isTracked) + { + if (trackedScore != null) + throw new InvalidOperationException("Cannot track more than one scores."); + + trackedScore = drawable; + } + drawable.Expanded.BindTo(Expanded); - base.Add(drawable); + Flow.Add(drawable); drawable.TotalScore.BindValueChanged(_ => sorting.Invalidate(), true); - Height = Count * (GameplayLeaderboardScore.PANEL_HEIGHT + Spacing.Y); + int displayCount = Math.Min(Flow.Count, maxPanels); + Height = displayCount * (GameplayLeaderboardScore.PANEL_HEIGHT + Flow.Spacing.Y); + requiresScroll = displayCount != Flow.Count; return drawable; } + public void Clear() + { + Flow.Clear(); + trackedScore = null; + scroll.ScrollToStart(false); + } + protected virtual GameplayLeaderboardScore CreateLeaderboardScoreDrawable(User user, bool isTracked) => new GameplayLeaderboardScore(user, isTracked); - public sealed override void Add(GameplayLeaderboardScore drawable) + protected override void Update() { - throw new NotSupportedException($"Use {nameof(AddPlayer)} instead."); + base.Update(); + + if (requiresScroll && trackedScore != null) + { + float scrollTarget = scroll.GetChildPosInContent(trackedScore) + trackedScore.DrawHeight / 2 - scroll.DrawHeight / 2; + scroll.ScrollTo(scrollTarget, false); + } + + const float panel_height = GameplayLeaderboardScore.PANEL_HEIGHT; + + float fadeBottom = scroll.Current + scroll.DrawHeight; + float fadeTop = scroll.Current + panel_height; + + if (scroll.Current <= 0) fadeTop -= panel_height; + if (!scroll.IsScrolledToEnd()) fadeBottom -= panel_height; + + // logic is mostly shared with Leaderboard, copied here for simplicity. + foreach (var c in Flow.Children) + { + float topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, Flow).Y; + float bottomY = topY + panel_height; + + bool requireTopFade = requiresScroll && topY <= fadeTop; + bool requireBottomFade = requiresScroll && bottomY >= fadeBottom; + + if (!requireTopFade && !requireBottomFade) + c.Colour = Color4.White; + else if (topY > fadeBottom + panel_height || bottomY < fadeTop - panel_height) + c.Colour = Color4.Transparent; + else + { + if (bottomY - fadeBottom > 0 && requiresScroll) + { + c.Colour = ColourInfo.GradientVertical( + Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / panel_height, 1)), + Color4.White.Opacity(Math.Min(1 - (bottomY - fadeBottom) / panel_height, 1))); + } + else if (requiresScroll) + { + c.Colour = ColourInfo.GradientVertical( + Color4.White.Opacity(Math.Min(1 - (fadeTop - topY) / panel_height, 1)), + Color4.White.Opacity(Math.Min(1 - (fadeTop - bottomY) / panel_height, 1))); + } + } + } } private void sort() @@ -73,15 +163,26 @@ namespace osu.Game.Screens.Play.HUD if (sorting.IsValid) return; - var orderedByScore = this.OrderByDescending(i => i.TotalScore.Value).ToList(); + var orderedByScore = Flow.OrderByDescending(i => i.TotalScore.Value).ToList(); - for (int i = 0; i < Count; i++) + for (int i = 0; i < Flow.Count; i++) { - SetLayoutPosition(orderedByScore[i], i); + Flow.SetLayoutPosition(orderedByScore[i], i); orderedByScore[i].ScorePosition = i + 1; } sorting.Validate(); } + + private class ManualScrollScrollContainer : OsuScrollContainer + { + public ManualScrollScrollContainer() + { + ScrollbarVisible = false; + } + + public override bool HandlePositionalInput => false; + public override bool HandleNonPositionalInput => false; + } } } diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 433bf78e9b..85cf9d1966 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -81,7 +81,10 @@ namespace osu.Game.Screens.Play.HUD [CanBeNull] public User User { get; } - private readonly bool trackedPlayer; + /// + /// Whether this score is the local user or a replay player (and should be focused / always visible). + /// + public readonly bool Tracked; private Container mainFillContainer; @@ -97,11 +100,11 @@ namespace osu.Game.Screens.Play.HUD /// Creates a new . /// /// The score's player. - /// Whether the player is the local user or a replay player. - public GameplayLeaderboardScore([CanBeNull] User user, bool trackedPlayer) + /// Whether the player is the local user or a replay player. + public GameplayLeaderboardScore([CanBeNull] User user, bool tracked) { User = user; - this.trackedPlayer = trackedPlayer; + Tracked = tracked; AutoSizeAxes = Axes.X; Height = PANEL_HEIGHT; @@ -338,7 +341,7 @@ namespace osu.Game.Screens.Play.HUD panelColour = BackgroundColour ?? Color4Extensions.FromHex("7fcc33"); textColour = TextColour ?? Color4.White; } - else if (trackedPlayer) + else if (Tracked) { widthExtension = true; panelColour = BackgroundColour ?? Color4Extensions.FromHex("ffd966"); From e84224f64c057f0d2caac52ad54ac06dc92a77e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Aug 2021 16:17:27 +0900 Subject: [PATCH 040/366] Rename `AddPlayer` method now that there's no conflict --- osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs | 2 +- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 2 +- osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index 10257f9027..0441c5641e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void createLeaderboardScore(BindableDouble score, User user, bool isTracked = false) { - var leaderboardScore = leaderboard.AddPlayer(user, isTracked); + var leaderboardScore = leaderboard.Add(user, isTracked); leaderboardScore.TotalScore.BindTo(score); } diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 807289d664..14fcaa91fa 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Play.HUD /// Whether the player should be tracked on the leaderboard. /// Set to true for the local player or a player whose replay is currently being played. /// - public ILeaderboardScore AddPlayer([CanBeNull] User user, bool isTracked) + public ILeaderboardScore Add([CanBeNull] User user, bool isTracked) { var drawable = CreateLeaderboardScoreDrawable(user, isTracked); diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 3f9258930e..1c5743a656 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -85,7 +85,7 @@ namespace osu.Game.Screens.Play.HUD var trackedUser = UserScores[user.Id]; - var leaderboardScore = AddPlayer(user, user.Id == api.LocalUser.Value.Id); + var leaderboardScore = Add(user, user.Id == api.LocalUser.Value.Id); leaderboardScore.Accuracy.BindTo(trackedUser.Accuracy); leaderboardScore.TotalScore.BindTo(trackedUser.Score); leaderboardScore.Combo.BindTo(trackedUser.CurrentCombo); From 5f67d991b4a02ad983cda08c4fc673618c6fc93e Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 12 Aug 2021 19:17:32 +0200 Subject: [PATCH 041/366] Localise beatmap info. --- osu.Game/Overlays/BeatmapSet/MetadataSection.cs | 3 ++- osu.Game/Overlays/BeatmapSet/MetadataType.cs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSection.cs b/osu.Game/Overlays/BeatmapSet/MetadataSection.cs index 3648c55714..f1b9f98528 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataSection.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataSection.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.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -46,7 +47,7 @@ namespace osu.Game.Overlays.BeatmapSet AutoSizeAxes = Axes.Y, Child = new OsuSpriteText { - Text = this.type.ToString(), + Text = this.type.GetLocalisableDescription(), Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), }, }, diff --git a/osu.Game/Overlays/BeatmapSet/MetadataType.cs b/osu.Game/Overlays/BeatmapSet/MetadataType.cs index 1ab4c6887e..f992dca0ef 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataType.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataType.cs @@ -1,14 +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.Localisation; +using osu.Game.Resources.Localisation.Web; + namespace osu.Game.Overlays.BeatmapSet { public enum MetadataType { + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoTags))] Tags, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoSource))] Source, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoDescription))] Description, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoGenre))] Genre, + + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowInfoLanguage))] Language } } From 4b4c1448eadd3837117ac2814ffd89f145e804cc Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 12 Aug 2021 19:19:03 +0200 Subject: [PATCH 042/366] Localise success rate metrics. --- osu.Game/Overlays/BeatmapSet/SuccessRate.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index 3bb36545cd..d370e57f14 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -4,10 +4,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osu.Game.Screens.Select.Details; namespace osu.Game.Overlays.BeatmapSet @@ -42,7 +44,7 @@ namespace osu.Game.Overlays.BeatmapSet int playCount = beatmap?.OnlineInfo?.PlayCount ?? 0; var rate = playCount != 0 ? (float)passCount / playCount : 0; - successPercent.Text = rate.ToString("0.#%"); + successPercent.Text = rate.ToLocalisableString("0.#%"); successRate.Length = rate; percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic); @@ -64,7 +66,7 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = "Success Rate", + Text = BeatmapsetsStrings.ShowInfoSuccessRate, Font = OsuFont.GetFont(size: 12) }, successRate = new Bar @@ -89,7 +91,7 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = "Points of Failure", + Text = BeatmapsetsStrings.ShowInfoPointsOfFailure, Font = OsuFont.GetFont(size: 12), Margin = new MarginPadding { Vertical = 20 }, }, From 2b86416cb268e717633b8f6d65d9772bb1ea022b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 06:27:57 +0300 Subject: [PATCH 043/366] Hide player settings overlay on multi-spectator player loader --- .../Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs | 7 +++++++ osu.Game/Screens/Play/PlayerLoader.cs | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index 5a1d28e9c4..52e4a6e012 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -3,6 +3,7 @@ using System; using JetBrains.Annotations; +using osu.Framework.Allocation; using osu.Game.Scoring; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; @@ -19,6 +20,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { } + [BackgroundDependencyLoader] + private void load() + { + PlayerSettingsGroups.Alpha = 0f; + } + protected override void LogoArriving(OsuLogo logo, bool resuming) { } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 5f6b4ca2b0..1f8387ac67 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -48,6 +48,11 @@ namespace osu.Game.Screens.Play protected BeatmapMetadataDisplay MetadataInfo; + /// + /// A fill flow containing the player settings groups, exposed for the ability to hide it from inheritors of the player loader. + /// + protected FillFlowContainer PlayerSettingsGroups; + protected VisualSettings VisualSettings; protected Task LoadTask { get; private set; } @@ -140,7 +145,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - new FillFlowContainer + PlayerSettingsGroups = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From c10320f23914fd8f15ff0c5ee30ca943a5de8519 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 06:28:07 +0300 Subject: [PATCH 044/366] Hide and disable player settings overlay on multi-spectator player --- .../Multiplayer/Spectate/MultiSpectatorPlayer.cs | 4 ++++ osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs | 2 +- osu.Game/Screens/Play/HUDOverlay.cs | 8 ++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 2c157b0564..71defa2e07 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -4,6 +4,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Scoring; @@ -34,6 +35,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private void load() { spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); + + HUDOverlay.PlayerSettingsOverlay.State.Value = Visibility.Hidden; + HUDOverlay.PlayerSettingsOverlay.State.Disabled = true; } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index ffcbb06fb3..efd37194d3 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Play.HUD if (e.ControlPressed) { - if (e.Key == Key.H && ReplayLoaded) + if (e.Key == Key.H && ReplayLoaded && !State.Disabled) { ToggleVisibility(); return true; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 2cf2555b3e..919886cae7 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -240,13 +240,17 @@ namespace osu.Game.Screens.Play if (e.NewValue) { - PlayerSettingsOverlay.Show(); + if (!PlayerSettingsOverlay.State.Disabled) + PlayerSettingsOverlay.Show(); + ModDisplay.FadeIn(200); KeyCounter.Margin = new MarginPadding(10) { Bottom = 30 }; } else { - PlayerSettingsOverlay.Hide(); + if (!PlayerSettingsOverlay.State.Disabled) + PlayerSettingsOverlay.Hide(); + ModDisplay.Delay(2000).FadeOut(200); KeyCounter.Margin = new MarginPadding(10); } From 1892db7f37e0d916826fef0d4788da4d78ce2531 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 06:31:39 +0300 Subject: [PATCH 045/366] Add test coverage --- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 65b1d6d53a..ad60582ace 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -6,6 +6,7 @@ using System.Linq; 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.Online.Multiplayer; @@ -13,6 +14,8 @@ using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Rulesets.UI; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; +using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Tests.Beatmaps.IO; using osu.Game.Users; @@ -80,6 +83,19 @@ namespace osu.Game.Tests.Visual.Multiplayer AddWaitStep("wait a bit", 20); } + [Test] + public void TestSpectatorPlayerSettingsHidden() + { + start(new[] { PLAYER_1_ID, PLAYER_2_ID }); + loadSpectateScreen(false); + + AddUntilStep("wait for player loaders", () => this.ChildrenOfType().Count() == 2); + AddAssert("all player loader settings hidden", () => this.ChildrenOfType().All(l => l.ChildrenOfType>().Single().Alpha == 0f)); + + AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded); + AddAssert("all player settings hidden", () => this.ChildrenOfType().All(p => p.ChildrenOfType().Single().State.Value == Visibility.Hidden)); + } + [Test] public void TestTeamDisplay() { From cbeecff347b350458f4858ab97722f39c875bccf Mon Sep 17 00:00:00 2001 From: LiangXiang Shen Date: Fri, 13 Aug 2021 12:17:38 +0800 Subject: [PATCH 046/366] Apply suggestions from code review Co-authored-by: Joseph Madamba --- osu.Game/Localisation/GraphicsSettingsStrings.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index 989eaf19b9..0e384f983f 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -55,14 +55,14 @@ namespace osu.Game.Localisation public static LocalisableString Resolution => new TranslatableString(getKey(@"resolution"), @"Resolution"); /// - /// "UI Scaling" + /// "UI scaling" /// - public static LocalisableString UIScaling => new TranslatableString(getKey(@"ui_scaling"), @"UI Scaling"); + public static LocalisableString UIScaling => new TranslatableString(getKey(@"ui_scaling"), @"UI scaling"); /// - /// "Screen Scaling" + /// "Screen scaling" /// - public static LocalisableString ScreenScaling => new TranslatableString(getKey(@"screen_scaling"), @"Screen Scaling"); + public static LocalisableString ScreenScaling => new TranslatableString(getKey(@"screen_scaling"), @"Screen scaling"); /// /// "Horizontal position" @@ -95,14 +95,14 @@ namespace osu.Game.Localisation public static LocalisableString DetailSettingsHeader => new TranslatableString(getKey(@"detail_settings_header"), @"Detail Settings"); /// - /// "Storyboard / Video" + /// "Storyboard / video" /// - public static LocalisableString StoryboardVideo => new TranslatableString(getKey(@"storyboard_video"), @"Storyboard / Video"); + public static LocalisableString StoryboardVideo => new TranslatableString(getKey(@"storyboard_video"), @"Storyboard / video"); /// - /// "Hit Lighting" + /// "Hit lighting" /// - public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit Lighting"); + public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit lighting"); /// /// "Screenshot format" From 8dc7a925e7e4a05de0f288fa9bee5dc684169f54 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 07:28:57 +0300 Subject: [PATCH 047/366] Expire instead of hiding and disabling visibility state Since it's a temporary change until the spectator interface gets improved, no need to add further logic. --- .../Multiplayer/Spectate/MultiSpectatorPlayer.cs | 4 +--- .../Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs | 2 +- osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs | 2 +- osu.Game/Screens/Play/HUDOverlay.cs | 8 ++------ 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 71defa2e07..b0ea361dbb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -4,7 +4,6 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Scoring; @@ -36,8 +35,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); - HUDOverlay.PlayerSettingsOverlay.State.Value = Visibility.Hidden; - HUDOverlay.PlayerSettingsOverlay.State.Disabled = true; + HUDOverlay.PlayerSettingsOverlay.Expire(); } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index 52e4a6e012..f28c2a1d48 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate [BackgroundDependencyLoader] private void load() { - PlayerSettingsGroups.Alpha = 0f; + PlayerSettingsGroups.Expire(); } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index efd37194d3..ffcbb06fb3 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Play.HUD if (e.ControlPressed) { - if (e.Key == Key.H && ReplayLoaded && !State.Disabled) + if (e.Key == Key.H && ReplayLoaded) { ToggleVisibility(); return true; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 919886cae7..2cf2555b3e 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -240,17 +240,13 @@ namespace osu.Game.Screens.Play if (e.NewValue) { - if (!PlayerSettingsOverlay.State.Disabled) - PlayerSettingsOverlay.Show(); - + PlayerSettingsOverlay.Show(); ModDisplay.FadeIn(200); KeyCounter.Margin = new MarginPadding(10) { Bottom = 30 }; } else { - if (!PlayerSettingsOverlay.State.Disabled) - PlayerSettingsOverlay.Hide(); - + PlayerSettingsOverlay.Hide(); ModDisplay.Delay(2000).FadeOut(200); KeyCounter.Margin = new MarginPadding(10); } From e7cf6b2d2337168ecfd0442e3518efa87d7d2c07 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 07:29:55 +0300 Subject: [PATCH 048/366] Expire hold-to-quit button on multi-spectator player --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index b0ea361dbb..20381e0c48 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -36,6 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); HUDOverlay.PlayerSettingsOverlay.Expire(); + HUDOverlay.HoldToQuit.Expire(); } protected override void UpdateAfterChildren() From 34c2b317e240821b5c7038fa0b3d1afb45ac3be5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 07:30:09 +0300 Subject: [PATCH 049/366] Hide song progress bar on multi-spectator player --- .../Multiplayer/Spectate/MultiSpectatorPlayer.cs | 2 ++ osu.Game/Screens/Play/Player.cs | 12 +++++++++++- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 20381e0c48..1b1dee5ae2 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -35,6 +35,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); + AllowUserSeekingState.Value = false; + AllowUserSeekingState.Disabled = true; HUDOverlay.PlayerSettingsOverlay.Expire(); HUDOverlay.HoldToQuit.Expire(); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 09eaf1c543..dc37464a61 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -77,6 +77,10 @@ namespace osu.Game.Screens.Play protected readonly Bindable LocalUserPlaying = new Bindable(); + protected readonly Bindable AllowUserSeekingState = new Bindable(); + + public IBindable AllowUserSeeking => AllowUserSeekingState; + public int RestartCount; [Resolved] @@ -269,7 +273,13 @@ namespace osu.Game.Screens.Play DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState()); - DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); + DrawableRuleset.HasReplayLoaded.BindValueChanged(r => + { + if (!AllowUserSeekingState.Disabled) + AllowUserSeekingState.Value = r.NewValue; + + updateGameplayState(); + }); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index f28622f42e..8debe6243d 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Play if (drawableRuleset != null) { - AllowSeeking.BindTo(drawableRuleset.HasReplayLoaded); + ((IBindable)AllowSeeking).BindTo(player.AllowUserSeeking); referenceClock = drawableRuleset.FrameStableClock; Objects = drawableRuleset.Objects; From fc22e806f44abddf493ab87bbe15f91a14e7c8c2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 07:30:24 +0300 Subject: [PATCH 050/366] Cover newly hidden/expired elements in existing test --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index ad60582ace..a9004987df 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -90,10 +90,13 @@ namespace osu.Game.Tests.Visual.Multiplayer loadSpectateScreen(false); AddUntilStep("wait for player loaders", () => this.ChildrenOfType().Count() == 2); - AddAssert("all player loader settings hidden", () => this.ChildrenOfType().All(l => l.ChildrenOfType>().Single().Alpha == 0f)); + AddAssert("all player loader settings hidden", () => this.ChildrenOfType().All(l => !l.ChildrenOfType>().Any())); AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded); - AddAssert("all player settings hidden", () => this.ChildrenOfType().All(p => p.ChildrenOfType().Single().State.Value == Visibility.Hidden)); + AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => + !p.ChildrenOfType().Any() && + !p.ChildrenOfType().Any() && + !p.ChildrenOfType().Single().ShowHandle)); } [Test] From b9721f5261c52a42e6eabec465a55e6b6d024431 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:37:43 +0900 Subject: [PATCH 051/366] Centralise screen exit logic and guard against non-current screen --- .../Multiplayer/MultiplayerMatchSubScreen.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 36b86737bc..265b68afea 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -274,7 +274,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer isConnected.BindValueChanged(connected => { if (!connected.NewValue) - Schedule(this.Exit); + handleRoomLost(); }, true); currentRoom.BindValueChanged(room => @@ -284,7 +284,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // the room has gone away. // this could mean something happened during the join process, or an external connection issue occurred. // one specific scenario is where the underlying room is created, but the signalr server returns an error during the join process. this triggers a PartRoom operation (see https://github.com/ppy/osu/blob/7654df94f6f37b8382be7dfcb4f674e03bd35427/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs#L97) - Schedule(this.Exit); + handleRoomLost(); } }, true); } @@ -451,13 +451,21 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // may happen if the client is kicked or otherwise removed from the room. if (client.Room == null) { - Schedule(this.Exit); + handleRoomLost(); return; } Scheduler.AddOnce(UpdateMods); } + private void handleRoomLost() => Schedule(() => + { + if (this.IsCurrentScreen()) + this.Exit(); + else + ValidForResume = false; + }); + private void onLoadRequested() { if (BeatmapAvailability.Value.State != DownloadState.LocallyAvailable) From 641d57e5e1657cc8ca26aea5031e47de7d3256ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:46:28 +0900 Subject: [PATCH 052/366] Change scroll container subclass name to hopefully read better --- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 14fcaa91fa..0f1ddedcf0 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play.HUD InternalChildren = new Drawable[] { - scroll = new ManualScrollScrollContainer + scroll = new InputDisabledScrollContainer { RelativeSizeAxes = Axes.Both, Child = Flow = new FillFlowContainer @@ -174,9 +174,9 @@ namespace osu.Game.Screens.Play.HUD sorting.Validate(); } - private class ManualScrollScrollContainer : OsuScrollContainer + private class InputDisabledScrollContainer : OsuScrollContainer { - public ManualScrollScrollContainer() + public InputDisabledScrollContainer() { ScrollbarVisible = false; } From 93574acf729981a8e925fc3edd0342bb444e56f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:46:57 +0900 Subject: [PATCH 053/366] Fix exception messaging --- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 0f1ddedcf0..312eeec949 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Play.HUD if (isTracked) { if (trackedScore != null) - throw new InvalidOperationException("Cannot track more than one scores."); + throw new InvalidOperationException("Cannot track more than one score."); trackedScore = drawable; } From 90755c0307b8af7de3c7c3d624be9d0b012e8d9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:50:59 +0900 Subject: [PATCH 054/366] Replace condition with matching precalculated bool --- osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 312eeec949..871555e5a3 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -142,7 +142,7 @@ namespace osu.Game.Screens.Play.HUD c.Colour = Color4.Transparent; else { - if (bottomY - fadeBottom > 0 && requiresScroll) + if (requireBottomFade) { c.Colour = ColourInfo.GradientVertical( Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / panel_height, 1)), From c5ee8753b43a3713073707aeb799d20fc1d82378 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 09:20:52 +0300 Subject: [PATCH 055/366] Notify users to read OpenTabletDriver's FAQ when tablet not detected --- .../Settings/Sections/Input/TabletSettings.cs | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index c7342c251d..7595ca59cb 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.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; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -9,9 +10,12 @@ using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Framework.Threading; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; using osu.Game.Localisation; +using osu.Game.Online.Chat; namespace osu.Game.Overlays.Settings.Sections.Input { @@ -52,7 +56,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private FillFlowContainer mainSettings; - private OsuSpriteText noTabletMessage; + private FillFlowContainer noTabletMessage; protected override LocalisableString Header => TabletSettingsStrings.Tablet; @@ -62,7 +66,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { Children = new Drawable[] { @@ -73,12 +77,41 @@ namespace osu.Game.Overlays.Settings.Sections.Input Origin = Anchor.TopCentre, Current = tabletHandler.Enabled }, - noTabletMessage = new OsuSpriteText + noTabletMessage = new FillFlowContainer { - Text = TabletSettingsStrings.NoTabletDetected, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, + Spacing = new Vector2(5f), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = TabletSettingsStrings.NoTabletDetected, + }, + new LinkFlowContainer + { + TextAnchor = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }.With(t => + { + t.NewLine(); + t.AddText("If your tablet is not getting detected properly,", s => s.Colour = colours.Yellow); + t.NewParagraph(); + t.AddText("read ", s => s.Colour = colours.Yellow); + t.AddLink("the driver's FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows + ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" + : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); + + t.AddText(" to troubleshoot the problem further.", s => s.Colour = colours.Yellow); + }), + } }, mainSettings = new FillFlowContainer { From 543f6039e24071c28e18ae838185d863257638cb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 09:26:53 +0300 Subject: [PATCH 056/366] Display on Windows and Linux only --- .../Settings/Sections/Input/TabletSettings.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 7595ca59cb..9ed85e44ec 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -101,15 +101,18 @@ namespace osu.Game.Overlays.Settings.Sections.Input AutoSizeAxes = Axes.Y, }.With(t => { - t.NewLine(); - t.AddText("If your tablet is not getting detected properly,", s => s.Colour = colours.Yellow); - t.NewParagraph(); - t.AddText("read ", s => s.Colour = colours.Yellow); - t.AddLink("the driver's FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows - ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" - : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); + if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux) + { + t.NewLine(); + t.AddText("If your tablet is not getting detected properly,", s => s.Colour = colours.Yellow); + t.NewParagraph(); + t.AddText("read ", s => s.Colour = colours.Yellow); + t.AddLink("the driver's FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows + ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" + : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); - t.AddText(" to troubleshoot the problem further.", s => s.Colour = colours.Yellow); + t.AddText(" to troubleshoot the problem further.", s => s.Colour = colours.Yellow); + } }), } }, From cd842ccef8f1221eb59a71defb2dc19348e9ccd9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 10:15:50 +0300 Subject: [PATCH 057/366] Improve message Co-authored-by: Dean Herbert --- .../Overlays/Settings/Sections/Input/TabletSettings.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 9ed85e44ec..af94dcdaca 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -104,14 +104,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux) { t.NewLine(); - t.AddText("If your tablet is not getting detected properly,", s => s.Colour = colours.Yellow); - t.NewParagraph(); - t.AddText("read ", s => s.Colour = colours.Yellow); - t.AddLink("the driver's FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows + t.AddText("If your tablet is not detected, please read ", s => s.Colour = colours.Yellow); + t.AddLink("this FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); - - t.AddText(" to troubleshoot the problem further.", s => s.Colour = colours.Yellow); + t.AddText(" for troubleshooting steps.", s => s.Colour = colours.Yellow); } }), } From f43ab323ffad425b250c0ed761c8c00c8895349b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 11:12:26 +0300 Subject: [PATCH 058/366] Add shared class for notice text in settings --- .../Settings/Sections/Input/TabletSettings.cs | 9 +++----- osu.Game/Overlays/Settings/SettingsItem.cs | 8 +------ .../Overlays/Settings/SettingsNoticeText.cs | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 osu.Game/Overlays/Settings/SettingsNoticeText.cs diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index af94dcdaca..2816eb7037 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -11,7 +11,6 @@ using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; using osu.Game.Localisation; @@ -92,23 +91,21 @@ namespace osu.Game.Overlays.Settings.Sections.Input Origin = Anchor.TopCentre, Text = TabletSettingsStrings.NoTabletDetected, }, - new LinkFlowContainer + new SettingsNoticeText { TextAnchor = Anchor.TopCentre, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, }.With(t => { if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux) { t.NewLine(); - t.AddText("If your tablet is not detected, please read ", s => s.Colour = colours.Yellow); + t.AddText("If your tablet is not detected, please read "); t.AddLink("this FAQ", LinkAction.External, RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Windows-FAQ" : @"https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ"); - t.AddText(" for troubleshooting steps.", s => s.Colour = colours.Yellow); + t.AddText(" for troubleshooting steps."); } }), } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index bd17c02af9..5d25605360 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -73,13 +73,7 @@ namespace osu.Game.Overlays.Settings return; // 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, - }); + FlowContent.Add(warningText = new SettingsNoticeText { Margin = new MarginPadding { Bottom = 5 } }); } warningText.Alpha = hasValue ? 0 : 1; diff --git a/osu.Game/Overlays/Settings/SettingsNoticeText.cs b/osu.Game/Overlays/Settings/SettingsNoticeText.cs new file mode 100644 index 0000000000..6bb4a3f11c --- /dev/null +++ b/osu.Game/Overlays/Settings/SettingsNoticeText.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.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Overlays.Settings +{ + public class SettingsNoticeText : LinkFlowContainer + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + } + } +} From 8910781bcdb4dac3a18e17c1962c6dd34421b550 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 17:39:09 +0900 Subject: [PATCH 059/366] Move listing polling component to LoungeSubScreen --- .../TestSceneLoungeRoomsContainer.cs | 2 +- .../TestSceneMultiplayerRoomManager.cs | 314 +++++++++--------- .../TestScenePlaylistsMatchSettingsOverlay.cs | 12 + osu.Game/Online/Rooms/Room.cs | 2 +- .../Components/ListingPollingComponent.cs | 23 +- .../OnlinePlay/Components/RoomManager.cs | 73 ++-- .../Components/RoomPollingComponent.cs | 15 +- .../Components/SelectionPollingComponent.cs | 14 +- osu.Game/Screens/OnlinePlay/IRoomManager.cs | 11 +- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 53 ++- .../OnlinePlay/Multiplayer/Multiplayer.cs | 30 -- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 33 ++ .../Multiplayer/MultiplayerMatchSubScreen.cs | 9 +- .../Multiplayer/MultiplayerRoomManager.cs | 73 ---- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 22 +- .../Screens/OnlinePlay/Playlists/Playlists.cs | 39 --- .../Playlists/PlaylistsLoungeSubScreen.cs | 3 + .../Playlists/PlaylistsRoomManager.cs | 21 -- .../Visual/OnlinePlay/BasicTestRoomManager.cs | 10 +- 19 files changed, 308 insertions(+), 451 deletions(-) delete mode 100644 osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomManager.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index bcbdcd2a4f..f3d961a646 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual.Multiplayer var room = RoomManager.Rooms[1]; RoomManager.RemoveRoom(room); - RoomManager.AddRoom(room); + RoomManager.AddOrUpdateRoom(room); }); AddAssert("no selection", () => checkRoomSelected(null)); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs index b17427a30b..15e9112c47 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs @@ -1,157 +1,157 @@ -// 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 NUnit.Framework; -using osu.Framework.Testing; -using osu.Game.Online.Rooms; -using osu.Game.Screens.OnlinePlay.Components; -using osu.Game.Tests.Beatmaps; -using osu.Game.Tests.Visual.OnlinePlay; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - [HeadlessTest] - public class TestSceneMultiplayerRoomManager : MultiplayerTestScene - { - protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); - - public TestSceneMultiplayerRoomManager() - : base(false) - { - } - - [Test] - public void TestPollsInitially() - { - AddStep("create room manager with a few rooms", () => - { - RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1")); - RoomManager.PartRoom(); - RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2")); - RoomManager.PartRoom(); - RoomManager.ClearRooms(); - }); - - AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); - AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); - } - - [Test] - public void TestRoomsClearedOnDisconnection() - { - AddStep("create room manager with a few rooms", () => - { - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - }); - - AddStep("disconnect", () => Client.Disconnect()); - - AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0); - AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); - } - - [Test] - public void TestRoomsPolledOnReconnect() - { - AddStep("create room manager with a few rooms", () => - { - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - }); - - AddStep("disconnect", () => Client.Disconnect()); - AddStep("connect", () => Client.Connect()); - - AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); - AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); - } - - [Test] - public void TestRoomsNotPolledWhenJoined() - { - AddStep("create room manager with a room", () => - { - RoomManager.CreateRoom(createRoom()); - RoomManager.ClearRooms(); - }); - - AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0); - AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); - } - - [Test] - public void TestMultiplayerRoomJoinedWhenCreated() - { - AddStep("create room manager with a room", () => - { - RoomManager.CreateRoom(createRoom()); - }); - - AddUntilStep("multiplayer room joined", () => Client.Room != null); - } - - [Test] - public void TestMultiplayerRoomPartedWhenAPIRoomParted() - { - AddStep("create room manager with a room", () => - { - RoomManager.CreateRoom(createRoom()); - RoomManager.PartRoom(); - }); - - AddAssert("multiplayer room parted", () => Client.Room == null); - } - - [Test] - public void TestMultiplayerRoomJoinedWhenAPIRoomJoined() - { - AddStep("create room manager with a room", () => - { - var r = createRoom(); - RoomManager.CreateRoom(r); - RoomManager.PartRoom(); - RoomManager.JoinRoom(r); - }); - - AddUntilStep("multiplayer room joined", () => Client.Room != null); - } - - private Room createRoom(Action initFunc = null) - { - var room = new Room - { - Name = - { - Value = "test room" - }, - Playlist = - { - new PlaylistItem - { - Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, - Ruleset = { Value = Ruleset.Value } - } - } - }; - - initFunc?.Invoke(room); - return room; - } - - private class TestDependencies : MultiplayerTestSceneDependencies - { - public TestDependencies() - { - // Need to set these values as early as possible. - RoomManager.TimeBetweenListingPolls.Value = 1; - RoomManager.TimeBetweenSelectionPolls.Value = 1; - } - } - } -} +// // 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 NUnit.Framework; +// using osu.Framework.Testing; +// using osu.Game.Online.Rooms; +// using osu.Game.Screens.OnlinePlay.Components; +// using osu.Game.Tests.Beatmaps; +// using osu.Game.Tests.Visual.OnlinePlay; +// +// namespace osu.Game.Tests.Visual.Multiplayer +// { +// [HeadlessTest] +// public class TestSceneMultiplayerRoomManager : MultiplayerTestScene +// { +// protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); +// +// public TestSceneMultiplayerRoomManager() +// : base(false) +// { +// } +// +// [Test] +// public void TestPollsInitially() +// { +// AddStep("create room manager with a few rooms", () => +// { +// RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1")); +// RoomManager.PartRoom(); +// RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2")); +// RoomManager.PartRoom(); +// RoomManager.ClearRooms(); +// }); +// +// AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); +// AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); +// } +// +// [Test] +// public void TestRoomsClearedOnDisconnection() +// { +// AddStep("create room manager with a few rooms", () => +// { +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// }); +// +// AddStep("disconnect", () => Client.Disconnect()); +// +// AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0); +// AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); +// } +// +// [Test] +// public void TestRoomsPolledOnReconnect() +// { +// AddStep("create room manager with a few rooms", () => +// { +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// }); +// +// AddStep("disconnect", () => Client.Disconnect()); +// AddStep("connect", () => Client.Connect()); +// +// AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); +// AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); +// } +// +// [Test] +// public void TestRoomsNotPolledWhenJoined() +// { +// AddStep("create room manager with a room", () => +// { +// RoomManager.CreateRoom(createRoom()); +// RoomManager.ClearRooms(); +// }); +// +// AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0); +// AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); +// } +// +// [Test] +// public void TestMultiplayerRoomJoinedWhenCreated() +// { +// AddStep("create room manager with a room", () => +// { +// RoomManager.CreateRoom(createRoom()); +// }); +// +// AddUntilStep("multiplayer room joined", () => Client.Room != null); +// } +// +// [Test] +// public void TestMultiplayerRoomPartedWhenAPIRoomParted() +// { +// AddStep("create room manager with a room", () => +// { +// RoomManager.CreateRoom(createRoom()); +// RoomManager.PartRoom(); +// }); +// +// AddAssert("multiplayer room parted", () => Client.Room == null); +// } +// +// [Test] +// public void TestMultiplayerRoomJoinedWhenAPIRoomJoined() +// { +// AddStep("create room manager with a room", () => +// { +// var r = createRoom(); +// RoomManager.CreateRoom(r); +// RoomManager.PartRoom(); +// RoomManager.JoinRoom(r); +// }); +// +// AddUntilStep("multiplayer room joined", () => Client.Room != null); +// } +// +// private Room createRoom(Action initFunc = null) +// { +// var room = new Room +// { +// Name = +// { +// Value = "test room" +// }, +// Playlist = +// { +// new PlaylistItem +// { +// Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, +// Ruleset = { Value = Ruleset.Value } +// } +// } +// }; +// +// initFunc?.Invoke(room); +// return room; +// } +// +// private class TestDependencies : MultiplayerTestSceneDependencies +// { +// public TestDependencies() +// { +// // Need to set these values as early as possible. +// RoomManager.TimeBetweenListingPolls.Value = 1; +// RoomManager.TimeBetweenSelectionPolls.Value = 1; +// } +// } +// } +// } diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index cdc655500d..79af2d3099 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -141,6 +141,18 @@ namespace osu.Game.Tests.Visual.Playlists public IBindableList Rooms => null; + public void AddOrUpdateRoom(Room room) + { + } + + public void RemoveRoom(Room room) + { + } + + public void ClearRooms() + { + } + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { if (CreateRequested == null) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 4bd5b1a788..364336783d 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -134,7 +134,7 @@ namespace osu.Game.Online.Rooms /// The position of this in the list. This is not read from or written to the API. /// [JsonIgnore] - public readonly Bindable Position = new Bindable(-1); + public readonly Bindable Position = new Bindable(-1); public Room() { diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index e50784fcbe..f686326d08 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -14,6 +15,9 @@ namespace osu.Game.Screens.OnlinePlay.Components /// public class ListingPollingComponent : RoomPollingComponent { + public IBindable HasPolledOnce => hasPolledOnce; + private readonly Bindable hasPolledOnce = new Bindable(); + [Resolved] private Bindable currentFilter { get; set; } @@ -25,7 +29,9 @@ namespace osu.Game.Screens.OnlinePlay.Components { currentFilter.BindValueChanged(_ => { - NotifyRoomsReceived(null); + RoomManager.ClearRooms(); + hasPolledOnce.Value = false; + if (IsLoaded) PollImmediately(); }); @@ -45,17 +51,16 @@ namespace osu.Game.Screens.OnlinePlay.Components pollReq.Success += result => { - for (int i = 0; i < result.Count; i++) + foreach (var existing in RoomManager.Rooms.ToArray()) { - if (result[i].RoomID.Value == selectedRoom.Value?.RoomID.Value) - { - // The listing request always has less information than the opened room, so don't include it. - result[i] = selectedRoom.Value; - break; - } + if (result.All(r => r.RoomID.Value != existing.RoomID.Value)) + RoomManager.RemoveRoom(existing); } - NotifyRoomsReceived(result); + foreach (var incoming in result) + RoomManager.AddOrUpdateRoom(incoming); + + hasPolledOnce.Value = true; tcs.SetResult(true); }; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index 422576648c..ab92adcac7 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -8,7 +8,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Online.API; @@ -17,15 +16,12 @@ using osu.Game.Rulesets; namespace osu.Game.Screens.OnlinePlay.Components { - public abstract class RoomManager : CompositeDrawable, IRoomManager + public class RoomManager : Component, IRoomManager { public event Action RoomsUpdated; private readonly BindableList rooms = new BindableList(); - public IBindable InitialRoomsReceived => initialRoomsReceived; - private readonly Bindable initialRoomsReceived = new Bindable(); - public IBindableList Rooms => rooms; protected IBindable JoinedRoom => joinedRoom; @@ -40,15 +36,9 @@ namespace osu.Game.Screens.OnlinePlay.Components [Resolved] private IAPIProvider api { get; set; } - protected RoomManager() + public RoomManager() { RelativeSizeAxes = Axes.Both; - - InternalChildren = CreatePollingComponents().Select(p => - { - p.RoomsReceived = onRoomsReceived; - return p; - }).ToList(); } protected override void Dispose(bool isDisposing) @@ -118,56 +108,41 @@ namespace osu.Game.Screens.OnlinePlay.Components private readonly HashSet ignoredRooms = new HashSet(); - private void onRoomsReceived(List received) + public void AddOrUpdateRoom(Room room) { - if (received == null) - { - ClearRooms(); + Debug.Assert(room.RoomID.Value != null); + + if (ignoredRooms.Contains(room.RoomID.Value.Value)) return; - } - // Remove past matches - foreach (var r in rooms.ToList()) + room.Position.Value = -room.RoomID.Value.Value; + + try { - if (received.All(e => e.RoomID.Value != r.RoomID.Value)) - rooms.Remove(r); + update(room, room); + addRoom(room); } - - for (int i = 0; i < received.Count; i++) + catch (Exception ex) { - var room = received[i]; + Logger.Error(ex, $"Failed to update room: {room.Name.Value}."); - Debug.Assert(room.RoomID.Value != null); - - if (ignoredRooms.Contains(room.RoomID.Value.Value)) - continue; - - room.Position.Value = i; - - try - { - update(room, room); - addRoom(room); - } - catch (Exception ex) - { - Logger.Error(ex, $"Failed to update room: {room.Name.Value}."); - - ignoredRooms.Add(room.RoomID.Value.Value); - rooms.Remove(room); - } + ignoredRooms.Add(room.RoomID.Value.Value); + rooms.Remove(room); } - RoomsUpdated?.Invoke(); - initialRoomsReceived.Value = true; + notifyRoomsUpdated(); } - protected void RemoveRoom(Room room) => rooms.Remove(room); + public void RemoveRoom(Room room) + { + rooms.Remove(room); + notifyRoomsUpdated(); + } - protected void ClearRooms() + public void ClearRooms() { rooms.Clear(); - initialRoomsReceived.Value = false; + notifyRoomsUpdated(); } /// @@ -196,6 +171,6 @@ namespace osu.Game.Screens.OnlinePlay.Components existing.CopyFrom(room); } - protected abstract IEnumerable CreatePollingComponents(); + private void notifyRoomsUpdated() => Scheduler.AddOnce(() => RoomsUpdated?.Invoke()); } } diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs index b2ea3a05d6..95b4c4284c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs @@ -1,29 +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 System; -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Online; using osu.Game.Online.API; -using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components { public abstract class RoomPollingComponent : PollingComponent { - /// - /// Invoked when any s have been received from the API. - /// - /// Any s present locally but not returned by this event are to be removed from display. - /// If null, the display of local rooms is reset to an initial state. - /// - /// - public Action> RoomsReceived; - [Resolved] protected IAPIProvider API { get; private set; } - protected void NotifyRoomsReceived(List rooms) => RoomsReceived?.Invoke(rooms); + [Resolved] + protected IRoomManager RoomManager { get; set; } } } diff --git a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs index dcf3c94b76..88d9469f8c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.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 System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -48,17 +46,7 @@ namespace osu.Game.Screens.OnlinePlay.Components pollReq.Success += result => { - // existing rooms need to be ordered by their position because the received of NotifyRoomsReceives expects to be able to sort them based on this order. - var rooms = new List(roomManager.Rooms.OrderBy(r => r.Position.Value)); - - int index = rooms.FindIndex(r => r.RoomID.Value == result.RoomID.Value); - - if (index < 0) - return; - - rooms[index] = result; - - NotifyRoomsReceived(rooms); + RoomManager.AddOrUpdateRoom(result); tcs.SetResult(true); }; diff --git a/osu.Game/Screens/OnlinePlay/IRoomManager.cs b/osu.Game/Screens/OnlinePlay/IRoomManager.cs index 34c1393ff1..baf84e25f9 100644 --- a/osu.Game/Screens/OnlinePlay/IRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/IRoomManager.cs @@ -18,16 +18,17 @@ namespace osu.Game.Screens.OnlinePlay /// event Action RoomsUpdated; - /// - /// Whether an initial listing of rooms has been received. - /// - IBindable InitialRoomsReceived { get; } - /// /// All the active s. /// IBindableList Rooms { get; } + void AddOrUpdateRoom(Room room); + + void RemoveRoom(Room room); + + void ClearRooms(); + /// /// Creates a new . /// diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 7249ccdd93..50f7baa44c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -12,14 +12,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Framework.Logging; using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Input; using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Rulesets; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Users; @@ -41,10 +44,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge AutoSizeAxes = Axes.Both }; - private readonly IBindable initialRoomsReceived = new Bindable(); - private readonly IBindable operationInProgress = new Bindable(); - - private LoadingLayer loadingLayer; + protected ListingPollingComponent ListingPollingComponent { get; private set; } [Resolved] private Bindable selectedRoom { get; set; } @@ -61,9 +61,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [Resolved] private IBindable ruleset { get; set; } + [Resolved(CanBeNull = true)] + private IdleTracker idleTracker { get; set; } + [CanBeNull] private IDisposable joiningRoomOperation { get; set; } + private readonly IBindable operationInProgress = new Bindable(); + private readonly IBindable isIdle = new BindableBool(); + private LoadingLayer loadingLayer; private RoomsContainer roomsContainer; private SearchTextBox searchTextBox; private Dropdown statusDropdown; @@ -77,6 +83,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { + ListingPollingComponent = CreatePollingComponent(), new Container { RelativeSizeAxes = Axes.Both, @@ -176,8 +183,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - initialRoomsReceived.BindTo(RoomManager.InitialRoomsReceived); - initialRoomsReceived.BindValueChanged(_ => updateLoadingLayer()); + ListingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); + + if (idleTracker != null) + { + isIdle.BindTo(idleTracker.IsIdle); + isIdle.BindValueChanged(_ => updatePollingRate(), true); + } if (ongoingOperationTracker != null) { @@ -231,7 +243,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge public override void OnEntering(IScreen last) { base.OnEntering(last); - onReturning(); } @@ -266,11 +277,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void onReturning() { + updatePollingRate(); searchTextBox.HoldFocus = true; } private void onLeaving() { + updatePollingRate(); searchTextBox.HoldFocus = false; // ensure any password prompt is dismissed. @@ -316,6 +329,24 @@ namespace osu.Game.Screens.OnlinePlay.Lounge this.Push(CreateRoomSubScreen(room)); } + private void updateLoadingLayer() + { + if (operationInProgress.Value || !ListingPollingComponent.HasPolledOnce.Value) + loadingLayer.Show(); + else + loadingLayer.Hide(); + } + + private void updatePollingRate() + { + if (!this.IsCurrentScreen()) + ListingPollingComponent.TimeBetweenPolls.Value = 0; + else + ListingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; + + Logger.Log($"Polling adjusted (listing: {ListingPollingComponent.TimeBetweenPolls.Value})"); + } + protected abstract OsuButton CreateNewRoomButton(); /// @@ -326,13 +357,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected abstract RoomSubScreen CreateRoomSubScreen(Room room); - private void updateLoadingLayer() - { - if (operationInProgress.Value || !initialRoomsReceived.Value) - loadingLayer.Show(); - else - loadingLayer.Hide(); - } + protected abstract ListingPollingComponent CreatePollingComponent(); private class LoungeSearchTextBox : SearchTextBox { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index 45928505bb..58b5b7bbeb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay.Components; @@ -23,35 +22,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer client.ChangeState(MultiplayerUserState.Idle); } - protected override void UpdatePollingRate(bool isIdle) - { - var multiplayerRoomManager = (MultiplayerRoomManager)RoomManager; - - if (!this.IsCurrentScreen()) - { - multiplayerRoomManager.TimeBetweenListingPolls.Value = 0; - multiplayerRoomManager.TimeBetweenSelectionPolls.Value = 0; - } - else - { - switch (CurrentSubScreen) - { - case LoungeSubScreen _: - multiplayerRoomManager.TimeBetweenListingPolls.Value = isIdle ? 120000 : 15000; - multiplayerRoomManager.TimeBetweenSelectionPolls.Value = isIdle ? 120000 : 15000; - break; - - // Don't poll inside the match or anywhere else. - default: - multiplayerRoomManager.TimeBetweenListingPolls.Value = 0; - multiplayerRoomManager.TimeBetweenSelectionPolls.Value = 0; - break; - } - } - - Logger.Log($"Polling adjusted (listing: {multiplayerRoomManager.TimeBetweenListingPolls.Value}, selection: {multiplayerRoomManager.TimeBetweenSelectionPolls.Value})"); - } - protected override string ScreenTitle => "Multiplayer"; protected override RoomManager CreateRoomManager() => new MultiplayerRoomManager(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index ad7882abc2..db6096e93b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -1,12 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Logging; +using osu.Framework.Screens; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; @@ -21,6 +25,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } + public override void OnResuming(IScreen last) + { + base.OnResuming(last); + ListingPollingComponent.PollImmediately(); + } + protected override FilterCriteria CreateFilterCriteria() { var criteria = base.CreateFilterCriteria(); @@ -39,6 +49,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room); + protected override ListingPollingComponent CreatePollingComponent() => new MultiplayerListingPollingComponent(); + protected override void OpenNewRoom(Room room) { if (client?.IsConnected.Value != true) @@ -49,5 +61,26 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.OpenNewRoom(room); } + + private class MultiplayerListingPollingComponent : ListingPollingComponent + { + public readonly IBindable AllowPolling = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + AllowPolling.BindValueChanged(allowPolling => + { + if (!allowPolling.NewValue) + return; + + if (IsLoaded) + PollImmediately(); + }); + } + + protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); + } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index a8e44dd56c..ec011634b1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -49,9 +49,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private OngoingOperationTracker ongoingOperationTracker { get; set; } [Resolved] - private Bindable currentRoom { get; set; } - - private MultiplayerMatchSettingsOverlay settingsOverlay; + private Bindable currentRoom { get; set; } // Todo: This should not exist. private readonly IBindable isConnected = new Bindable(); @@ -59,6 +57,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private IDisposable readyClickOperation; private GridContainer mainContent; + private MultiplayerMatchSettingsOverlay settingsOverlay; public MultiplayerMatchSubScreen(Room room) { @@ -324,6 +323,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override bool OnExiting(IScreen next) { + // We don't know whether we're the only participant in the room, and whether the room will close after we leave it as a result. + // To work around this, temporarily remove the room until the next listing poll retrieves it. + RoomManager?.RemoveRoom(currentRoom.Value); + // the room may not be left immediately after a disconnection due to async flow, // so checking the IsConnected status is also required. if (client.Room == null || !client.IsConnected.Value) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index cbba4babe5..ae8c3113ff 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -2,9 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.ExceptionExtensions; @@ -21,13 +19,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient multiplayerClient { get; set; } - public readonly Bindable TimeBetweenListingPolls = new Bindable(); - public readonly Bindable TimeBetweenSelectionPolls = new Bindable(); private readonly IBindable isConnected = new Bindable(); private readonly Bindable allowPolling = new Bindable(); - private ListingPollingComponent listingPollingComponent; - protected override void LoadComplete() { base.LoadComplete(); @@ -64,19 +58,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (JoinedRoom.Value == null) return; - var joinedRoom = JoinedRoom.Value; - base.PartRoom(); - multiplayerClient.LeaveRoom(); - - // Todo: This is not the way to do this. Basically when we're the only participant and the room closes, there's no way to know if this is actually the case. - // This is delayed one frame because upon exiting the match subscreen, multiplayer updates the polling rate and messes with polling. - Schedule(() => - { - RemoveRoom(joinedRoom); - listingPollingComponent.PollImmediately(); - }); } private void joinMultiplayerRoom(Room room, string password, Action onSuccess = null, Action onError = null) @@ -108,61 +91,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // Don't poll when not connected or when a room has been joined. allowPolling.Value = isConnected.Value && JoinedRoom.Value == null; } - - protected override IEnumerable CreatePollingComponents() => new RoomPollingComponent[] - { - listingPollingComponent = new MultiplayerListingPollingComponent - { - TimeBetweenPolls = { BindTarget = TimeBetweenListingPolls }, - AllowPolling = { BindTarget = allowPolling } - }, - new MultiplayerSelectionPollingComponent - { - TimeBetweenPolls = { BindTarget = TimeBetweenSelectionPolls }, - AllowPolling = { BindTarget = allowPolling } - } - }; - - private class MultiplayerListingPollingComponent : ListingPollingComponent - { - public readonly IBindable AllowPolling = new Bindable(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - AllowPolling.BindValueChanged(allowPolling => - { - if (!allowPolling.NewValue) - return; - - if (IsLoaded) - PollImmediately(); - }); - } - - protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); - } - - private class MultiplayerSelectionPollingComponent : SelectionPollingComponent - { - public readonly IBindable AllowPolling = new Bindable(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - AllowPolling.BindValueChanged(allowPolling => - { - if (!allowPolling.NewValue) - return; - - if (IsLoaded) - PollImmediately(); - }); - } - - protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); - } } } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index c2ad0285b1..cfb19ca3d7 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -13,7 +13,6 @@ using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; -using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Overlays; @@ -43,8 +42,6 @@ namespace osu.Game.Screens.OnlinePlay private LoungeSubScreen loungeSubScreen; private ScreenStack screenStack; - private readonly IBindable isIdle = new BindableBool(); - [Cached(Type = typeof(IRoomManager))] protected RoomManager RoomManager { get; private set; } @@ -66,9 +63,6 @@ namespace osu.Game.Screens.OnlinePlay [Resolved] protected IAPIProvider API { get; private set; } - [Resolved(CanBeNull = true)] - private IdleTracker idleTracker { get; set; } - [Resolved(CanBeNull = true)] private OsuLogo logo { get; set; } @@ -151,12 +145,6 @@ namespace osu.Game.Screens.OnlinePlay apiState.BindTo(API.State); apiState.BindValueChanged(onlineStateChanged, true); - - if (idleTracker != null) - { - isIdle.BindTo(idleTracker.IsIdle); - isIdle.BindValueChanged(idle => UpdatePollingRate(idle.NewValue), true); - } } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -166,8 +154,6 @@ namespace osu.Game.Screens.OnlinePlay return dependencies; } - protected abstract void UpdatePollingRate(bool isIdle); - private void forcefullyExit() { // This is temporary since we don't currently have a way to force screens to be exited @@ -203,8 +189,6 @@ namespace osu.Game.Screens.OnlinePlay screenStack.CurrentScreen.OnResuming(last); base.OnResuming(last); - - UpdatePollingRate(isIdle.Value); } public override void OnSuspending(IScreen next) @@ -214,8 +198,6 @@ namespace osu.Game.Screens.OnlinePlay Debug.Assert(screenStack.CurrentScreen != null); screenStack.CurrentScreen.OnSuspending(next); - - UpdatePollingRate(isIdle.Value); } public override bool OnExiting(IScreen next) @@ -279,15 +261,13 @@ namespace osu.Game.Screens.OnlinePlay if (newScreen is IOsuScreen newOsuScreen) ((IBindable)Activity).BindTo(newOsuScreen.Activity); - - UpdatePollingRate(isIdle.Value); } protected IScreen CurrentSubScreen => screenStack.CurrentScreen; protected abstract string ScreenTitle { get; } - protected abstract RoomManager CreateRoomManager(); + protected virtual RoomManager CreateRoomManager() => new RoomManager(); protected abstract LoungeSubScreen CreateLounge(); diff --git a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs index 6a78e24ba1..1edeef77df 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs @@ -1,53 +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.Logging; -using osu.Framework.Screens; -using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; -using osu.Game.Screens.OnlinePlay.Match; namespace osu.Game.Screens.OnlinePlay.Playlists { public class Playlists : OnlinePlayScreen { - protected override void UpdatePollingRate(bool isIdle) - { - var playlistsManager = (PlaylistsRoomManager)RoomManager; - - if (!this.IsCurrentScreen()) - { - playlistsManager.TimeBetweenListingPolls.Value = 0; - playlistsManager.TimeBetweenSelectionPolls.Value = 0; - } - else - { - switch (CurrentSubScreen) - { - case LoungeSubScreen _: - playlistsManager.TimeBetweenListingPolls.Value = isIdle ? 120000 : 15000; - playlistsManager.TimeBetweenSelectionPolls.Value = isIdle ? 120000 : 15000; - break; - - case RoomSubScreen _: - playlistsManager.TimeBetweenListingPolls.Value = 0; - playlistsManager.TimeBetweenSelectionPolls.Value = isIdle ? 30000 : 5000; - break; - - default: - playlistsManager.TimeBetweenListingPolls.Value = 0; - playlistsManager.TimeBetweenSelectionPolls.Value = 0; - break; - } - } - - Logger.Log($"Polling adjusted (listing: {playlistsManager.TimeBetweenListingPolls.Value}, selection: {playlistsManager.TimeBetweenSelectionPolls.Value})"); - } - protected override string ScreenTitle => "Playlists"; - protected override RoomManager CreateRoomManager() => new PlaylistsRoomManager(); - protected override LoungeSubScreen CreateLounge() => new PlaylistsLoungeSubScreen(); } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs index eee4d4f407..dced9b8691 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; @@ -66,6 +67,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override RoomSubScreen CreateRoomSubScreen(Room room) => new PlaylistsRoomSubScreen(room); + protected override ListingPollingComponent CreatePollingComponent() => new ListingPollingComponent(); + private enum PlaylistsCategory { Any, diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomManager.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomManager.cs deleted file mode 100644 index c55d1c3e94..0000000000 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomManager.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Bindables; -using osu.Game.Screens.OnlinePlay.Components; - -namespace osu.Game.Screens.OnlinePlay.Playlists -{ - public class PlaylistsRoomManager : RoomManager - { - public readonly Bindable TimeBetweenListingPolls = new Bindable(); - public readonly Bindable TimeBetweenSelectionPolls = new Bindable(); - - protected override IEnumerable CreatePollingComponents() => new RoomPollingComponent[] - { - new ListingPollingComponent { TimeBetweenPolls = { BindTarget = TimeBetweenListingPolls } }, - new SelectionPollingComponent { TimeBetweenPolls = { BindTarget = TimeBetweenSelectionPolls } } - }; - } -} diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index d37a64fa4b..2e9c0d1d53 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -33,10 +33,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1; onSuccess?.Invoke(room); - AddRoom(room); + AddOrUpdateRoom(room); } - public void AddRoom(Room room) + public void AddOrUpdateRoom(Room room) { Rooms.Add(room); RoomsUpdated?.Invoke(); @@ -48,6 +48,12 @@ namespace osu.Game.Tests.Visual.OnlinePlay RoomsUpdated?.Invoke(); } + public void ClearRooms() + { + Rooms.Clear(); + RoomsUpdated?.Invoke(); + } + public void JoinRoom(Room room, string password, Action onSuccess = null, Action onError = null) { JoinRoomRequested?.Invoke(room, password); From 7cbf4c48edc94af45f10468eb34ca24565d55e28 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 17:59:18 +0900 Subject: [PATCH 060/366] Fix multiplayer polling when not connected --- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 15 ++++---- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 37 ++++++++++++++----- .../Multiplayer/MultiplayerRoomManager.cs | 22 ----------- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 50f7baa44c..4525599a52 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -44,8 +44,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge AutoSizeAxes = Axes.Both }; - protected ListingPollingComponent ListingPollingComponent { get; private set; } - [Resolved] private Bindable selectedRoom { get; set; } @@ -73,6 +71,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private RoomsContainer roomsContainer; private SearchTextBox searchTextBox; private Dropdown statusDropdown; + private ListingPollingComponent listingPollingComponent; [BackgroundDependencyLoader] private void load() @@ -83,7 +82,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { - ListingPollingComponent = CreatePollingComponent(), + listingPollingComponent = CreatePollingComponent(), new Container { RelativeSizeAxes = Axes.Both, @@ -183,7 +182,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - ListingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); + listingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); if (idleTracker != null) { @@ -331,7 +330,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void updateLoadingLayer() { - if (operationInProgress.Value || !ListingPollingComponent.HasPolledOnce.Value) + if (operationInProgress.Value || !listingPollingComponent.HasPolledOnce.Value) loadingLayer.Show(); else loadingLayer.Hide(); @@ -340,11 +339,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void updatePollingRate() { if (!this.IsCurrentScreen()) - ListingPollingComponent.TimeBetweenPolls.Value = 0; + listingPollingComponent.TimeBetweenPolls.Value = 0; else - ListingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; + listingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; - Logger.Log($"Polling adjusted (listing: {ListingPollingComponent.TimeBetweenPolls.Value})"); + Logger.Log($"Polling adjusted (listing: {listingPollingComponent.TimeBetweenPolls.Value})"); } protected abstract OsuButton CreateNewRoomButton(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index db6096e93b..3f20202ec7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -25,10 +25,23 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } + private MultiplayerListingPollingComponent listingPollingComponent; + + private readonly IBindable isConnected = new Bindable(); + private readonly Bindable allowPolling = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + isConnected.BindTo(client.IsConnected); + isConnected.BindValueChanged(c => Scheduler.AddOnce(() => listingPollingComponent.AllowPolling = c.NewValue)); + } + public override void OnResuming(IScreen last) { base.OnResuming(last); - ListingPollingComponent.PollImmediately(); + listingPollingComponent.PollImmediately(); } protected override FilterCriteria CreateFilterCriteria() @@ -49,7 +62,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room); - protected override ListingPollingComponent CreatePollingComponent() => new MultiplayerListingPollingComponent(); + protected override ListingPollingComponent CreatePollingComponent() => listingPollingComponent = new MultiplayerListingPollingComponent(); protected override void OpenNewRoom(Room room) { @@ -64,23 +77,27 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private class MultiplayerListingPollingComponent : ListingPollingComponent { - public readonly IBindable AllowPolling = new Bindable(); + private bool allowPolling; - protected override void LoadComplete() + public bool AllowPolling { - base.LoadComplete(); - - AllowPolling.BindValueChanged(allowPolling => + get => allowPolling; + set { - if (!allowPolling.NewValue) + if (allowPolling == value) + return; + + allowPolling = value; + + if (!allowPolling) return; if (IsLoaded) PollImmediately(); - }); + } } - protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); + protected override Task Poll() => !AllowPolling ? Task.CompletedTask : base.Poll(); } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index ae8c3113ff..2d94b2328d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Logging; using osu.Game.Online.Multiplayer; @@ -19,18 +18,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient multiplayerClient { get; set; } - private readonly IBindable isConnected = new Bindable(); - private readonly Bindable allowPolling = new Bindable(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - isConnected.BindTo(multiplayerClient.IsConnected); - isConnected.BindValueChanged(_ => Scheduler.AddOnce(updatePolling)); - JoinedRoom.BindValueChanged(_ => Scheduler.AddOnce(updatePolling), true); - } - public override void CreateRoom(Room room, Action onSuccess = null, Action onError = null) => base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), onError); @@ -82,14 +69,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } }); } - - private void updatePolling() - { - if (!isConnected.Value) - ClearRooms(); - - // Don't poll when not connected or when a room has been joined. - allowPolling.Value = isConnected.Value && JoinedRoom.Value == null; - } } } From 83935540caf400882750283724326934c556110b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:11:52 +0900 Subject: [PATCH 061/366] Add selection polling component to PlaylistsRoomSubScreen --- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 16 +++++-------- .../Playlists/PlaylistsRoomSubScreen.cs | 24 +++++++++++++++---- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 4525599a52..06db462205 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -59,9 +59,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [Resolved] private IBindable ruleset { get; set; } - [Resolved(CanBeNull = true)] - private IdleTracker idleTracker { get; set; } - [CanBeNull] private IDisposable joiningRoomOperation { get; set; } @@ -73,9 +70,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private Dropdown statusDropdown; private ListingPollingComponent listingPollingComponent; - [BackgroundDependencyLoader] - private void load() + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] IdleTracker idleTracker) { + if (idleTracker != null) + isIdle.BindTo(idleTracker.IsIdle); + filter ??= new Bindable(new FilterCriteria()); OsuScrollContainer scrollContainer; @@ -184,11 +184,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge listingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); - if (idleTracker != null) - { - isIdle.BindTo(idleTracker.IsIdle); - isIdle.BindValueChanged(_ => updatePollingRate(), true); - } + isIdle.BindValueChanged(_ => updatePollingRate(), true); if (ongoingOperationTracker != null) { diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 953c687087..682b055766 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -3,11 +3,14 @@ using System.Diagnostics; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; @@ -33,12 +36,13 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [Resolved(typeof(Room), nameof(Room.Playlist))] private BindableList playlist { get; set; } + private readonly IBindable isIdle = new BindableBool(); + private MatchSettingsOverlay settingsOverlay; private MatchLeaderboard leaderboard; - private OverlinedHeader participantsHeader; - private GridContainer mainContent; + private SelectionPollingComponent selectionPollingComponent; public PlaylistsRoomSubScreen(Room room) { @@ -46,11 +50,15 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Activity.Value = new UserActivity.InLobby(room); } - [BackgroundDependencyLoader] - private void load() + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] IdleTracker idleTracker) { + if (idleTracker != null) + isIdle.BindTo(idleTracker.IsIdle); + AddRangeInternal(new Drawable[] { + selectionPollingComponent = new SelectionPollingComponent(), mainContent = new GridContainer { RelativeSizeAxes = Axes.Both, @@ -260,6 +268,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { base.LoadComplete(); + isIdle.BindValueChanged(_ => updatePollingRate(), true); + roomId.BindValueChanged(id => { if (id.NewValue == null) @@ -275,6 +285,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, true); } + private void updatePollingRate() + { + selectionPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 30000 : 5000; + Logger.Log($"Polling adjusted (selection: {selectionPollingComponent.TimeBetweenPolls.Value})"); + } + protected override Screen CreateGameplayScreen() => new PlayerLoader(() => new PlaylistsPlayer(SelectedItem.Value) { Exited = () => leaderboard.RefreshScores() From f5cea0cacd34535f58b43c216f03ed60b1bb31ec Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 12:12:20 +0300 Subject: [PATCH 062/366] Fix failing test and rename to match new behaviour --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index a9004987df..080a1502b0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -84,7 +84,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] - public void TestSpectatorPlayerSettingsHidden() + public void TestSpectatorPlayerInteractiveElementsHidden() { start(new[] { PLAYER_1_ID, PLAYER_2_ID }); loadSpectateScreen(false); @@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && - !p.ChildrenOfType().Single().ShowHandle)); + p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); } [Test] From 6a46105b5efe9b6a2fcaa95838f53d1793daeb90 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:12:32 +0900 Subject: [PATCH 063/366] Fix incorrect dependency --- osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs index 95b4c4284c..cd224a7347 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs @@ -13,6 +13,6 @@ namespace osu.Game.Screens.OnlinePlay.Components protected IAPIProvider API { get; private set; } [Resolved] - protected IRoomManager RoomManager { get; set; } + protected IRoomManager RoomManager { get; private set; } } } From 1bae7173d3794d1cecca63fb31fecbc4a64ef3f9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:13:55 +0900 Subject: [PATCH 064/366] Fix initial multiplayer poll --- .../OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 3f20202ec7..d36462f482 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -28,7 +28,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerListingPollingComponent listingPollingComponent; private readonly IBindable isConnected = new Bindable(); - private readonly Bindable allowPolling = new Bindable(); protected override void LoadComplete() { @@ -36,6 +35,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer isConnected.BindTo(client.IsConnected); isConnected.BindValueChanged(c => Scheduler.AddOnce(() => listingPollingComponent.AllowPolling = c.NewValue)); + listingPollingComponent.AllowPolling = isConnected.Value; } public override void OnResuming(IScreen last) From d527eb3d8b8f89bafa8870fe691f3ef6127fca67 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Fri, 13 Aug 2021 17:15:18 +0800 Subject: [PATCH 065/366] Apply suggestions from code review Co-authored-by: Dean Herbert --- osu.Game/Localisation/GameplaySettingsStrings.cs | 6 +++--- osu.Game/Localisation/GeneralSettingsStrings.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 6 +++--- .../Overlays/Settings/Sections/General/LanguageSettings.cs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index 4354272ab5..c63fa5ddcc 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -22,12 +22,12 @@ namespace osu.Game.Localisation /// /// "Background dim" /// - public static LocalisableString Dim => new TranslatableString(getKey(@"dim"), @"Background dim"); + public static LocalisableString BackgroundDim => new TranslatableString(getKey(@"dim"), @"Background dim"); /// /// "Background blur" /// - public static LocalisableString Blur => new TranslatableString(getKey(@"blur"), @"Background blur"); + public static LocalisableString BackgroundBlur => new TranslatableString(getKey(@"blur"), @"Background blur"); /// /// "Lighten playfield during breaks" @@ -57,7 +57,7 @@ namespace osu.Game.Localisation /// /// "Always show key overlay" /// - public static LocalisableString KeyOverlay => new TranslatableString(getKey(@"key_overlay"), @"Always show key overlay"); + public static LocalisableString AlwaysShowKeyOverlay => new TranslatableString(getKey(@"key_overlay"), @"Always show key overlay"); /// /// "Positional hitsounds" diff --git a/osu.Game/Localisation/GeneralSettingsStrings.cs b/osu.Game/Localisation/GeneralSettingsStrings.cs index 19fb8de972..a60e4891f4 100644 --- a/osu.Game/Localisation/GeneralSettingsStrings.cs +++ b/osu.Game/Localisation/GeneralSettingsStrings.cs @@ -27,7 +27,7 @@ namespace osu.Game.Localisation /// /// "Prefer metadata in original language" /// - public static LocalisableString PreferOriginal => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language"); + public static LocalisableString PreferOriginalMetadataLanguage => new TranslatableString(getKey(@"prefer_original"), @"Prefer metadata in original language"); /// /// "Updates" diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index efb586fdca..04332fcdd3 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -22,14 +22,14 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsSlider { - LabelText = GameplaySettingsStrings.Dim, + LabelText = GameplaySettingsStrings.BackgroundDim, Current = config.GetBindable(OsuSetting.DimLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true }, new SettingsSlider { - LabelText = GameplaySettingsStrings.Blur, + LabelText = GameplaySettingsStrings.BackgroundBlur, Current = config.GetBindable(OsuSetting.BlurLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - LabelText = GameplaySettingsStrings.KeyOverlay, + LabelText = GameplaySettingsStrings.AlwaysShowKeyOverlay, Current = config.GetBindable(OsuSetting.KeyOverlay) }, new SettingsCheckbox diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index ac95a713bf..200618c469 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections.General }, new SettingsCheckbox { - LabelText = GeneralSettingsStrings.PreferOriginal, + LabelText = GeneralSettingsStrings.PreferOriginalMetadataLanguage, Current = frameworkConfig.GetBindable(FrameworkSetting.ShowUnicode) }, }; From 1f992e67f3b29f63a0f965eb6c4e3ed26a6699c8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:17:18 +0900 Subject: [PATCH 066/366] Fix listing polling rate when entering room --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 06db462205..abe06bae9e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -184,7 +184,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge listingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); - isIdle.BindValueChanged(_ => updatePollingRate(), true); + isIdle.BindValueChanged(_ => updatePollingRate(this.IsCurrentScreen()), true); if (ongoingOperationTracker != null) { @@ -272,13 +272,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void onReturning() { - updatePollingRate(); + updatePollingRate(true); searchTextBox.HoldFocus = true; } private void onLeaving() { - updatePollingRate(); + updatePollingRate(false); searchTextBox.HoldFocus = false; // ensure any password prompt is dismissed. @@ -332,9 +332,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge loadingLayer.Hide(); } - private void updatePollingRate() + private void updatePollingRate(bool isCurrentScreen) { - if (!this.IsCurrentScreen()) + if (!isCurrentScreen) listingPollingComponent.TimeBetweenPolls.Value = 0; else listingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; From c71a581106f1640a4303ead14755820cfc1c29d7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:24:19 +0900 Subject: [PATCH 067/366] Fix exception when leaving match --- .../OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs | 9 ++++++++- .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index d36462f482..0756c78211 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -41,7 +41,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override void OnResuming(IScreen last) { base.OnResuming(last); - listingPollingComponent.PollImmediately(); + + // Upon having left a room, we don't know whether we were the only participant, and whether the room is now closed as a result of leaving it. + // To work around this, temporarily clear all rooms until the next listing poll. + if (last is MultiplayerMatchSubScreen match) + { + RoomManager.RemoveRoom(match.Room); + listingPollingComponent.PollImmediately(); + } } protected override FilterCriteria CreateFilterCriteria() diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index ec011634b1..72ba4d62fb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -42,6 +42,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override string ShortTitle => "room"; + public readonly Room Room; + [Resolved] private MultiplayerClient client { get; set; } @@ -61,6 +63,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public MultiplayerMatchSubScreen(Room room) { + Room = room; + Title = room.RoomID.Value == null ? "New room" : room.Name.Value; Activity.Value = new UserActivity.InLobby(room); } @@ -323,10 +327,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override bool OnExiting(IScreen next) { - // We don't know whether we're the only participant in the room, and whether the room will close after we leave it as a result. - // To work around this, temporarily remove the room until the next listing poll retrieves it. - RoomManager?.RemoveRoom(currentRoom.Value); - // the room may not be left immediately after a disconnection due to async flow, // so checking the IsConnected status is also required. if (client.Room == null || !client.IsConnected.Value) From fbadc4897e211db035eb495d19cc797535e4fbc1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 18:28:20 +0900 Subject: [PATCH 068/366] Remove test scene --- .../TestSceneMultiplayerRoomManager.cs | 157 ------------------ 1 file changed, 157 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs deleted file mode 100644 index 15e9112c47..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ /dev/null @@ -1,157 +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 NUnit.Framework; -// using osu.Framework.Testing; -// using osu.Game.Online.Rooms; -// using osu.Game.Screens.OnlinePlay.Components; -// using osu.Game.Tests.Beatmaps; -// using osu.Game.Tests.Visual.OnlinePlay; -// -// namespace osu.Game.Tests.Visual.Multiplayer -// { -// [HeadlessTest] -// public class TestSceneMultiplayerRoomManager : MultiplayerTestScene -// { -// protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); -// -// public TestSceneMultiplayerRoomManager() -// : base(false) -// { -// } -// -// [Test] -// public void TestPollsInitially() -// { -// AddStep("create room manager with a few rooms", () => -// { -// RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1")); -// RoomManager.PartRoom(); -// RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2")); -// RoomManager.PartRoom(); -// RoomManager.ClearRooms(); -// }); -// -// AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); -// AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); -// } -// -// [Test] -// public void TestRoomsClearedOnDisconnection() -// { -// AddStep("create room manager with a few rooms", () => -// { -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// }); -// -// AddStep("disconnect", () => Client.Disconnect()); -// -// AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0); -// AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); -// } -// -// [Test] -// public void TestRoomsPolledOnReconnect() -// { -// AddStep("create room manager with a few rooms", () => -// { -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// }); -// -// AddStep("disconnect", () => Client.Disconnect()); -// AddStep("connect", () => Client.Connect()); -// -// AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); -// AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); -// } -// -// [Test] -// public void TestRoomsNotPolledWhenJoined() -// { -// AddStep("create room manager with a room", () => -// { -// RoomManager.CreateRoom(createRoom()); -// RoomManager.ClearRooms(); -// }); -// -// AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0); -// AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); -// } -// -// [Test] -// public void TestMultiplayerRoomJoinedWhenCreated() -// { -// AddStep("create room manager with a room", () => -// { -// RoomManager.CreateRoom(createRoom()); -// }); -// -// AddUntilStep("multiplayer room joined", () => Client.Room != null); -// } -// -// [Test] -// public void TestMultiplayerRoomPartedWhenAPIRoomParted() -// { -// AddStep("create room manager with a room", () => -// { -// RoomManager.CreateRoom(createRoom()); -// RoomManager.PartRoom(); -// }); -// -// AddAssert("multiplayer room parted", () => Client.Room == null); -// } -// -// [Test] -// public void TestMultiplayerRoomJoinedWhenAPIRoomJoined() -// { -// AddStep("create room manager with a room", () => -// { -// var r = createRoom(); -// RoomManager.CreateRoom(r); -// RoomManager.PartRoom(); -// RoomManager.JoinRoom(r); -// }); -// -// AddUntilStep("multiplayer room joined", () => Client.Room != null); -// } -// -// private Room createRoom(Action initFunc = null) -// { -// var room = new Room -// { -// Name = -// { -// Value = "test room" -// }, -// Playlist = -// { -// new PlaylistItem -// { -// Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, -// Ruleset = { Value = Ruleset.Value } -// } -// } -// }; -// -// initFunc?.Invoke(room); -// return room; -// } -// -// private class TestDependencies : MultiplayerTestSceneDependencies -// { -// public TestDependencies() -// { -// // Need to set these values as early as possible. -// RoomManager.TimeBetweenListingPolls.Value = 1; -// RoomManager.TimeBetweenSelectionPolls.Value = 1; -// } -// } -// } -// } From 7cf6b551d353ffd8393b3ed4d7489f5c6d23bca3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 13:01:17 +0300 Subject: [PATCH 069/366] Replace until step with wait step with explanatory comment --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 080a1502b0..62a9b597ad 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -93,10 +93,15 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("all player loader settings hidden", () => this.ChildrenOfType().All(l => !l.ChildrenOfType>().Any())); AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded); - AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => + + // components wrapped in skinnable target containers load asynchronously, potentially taking more than one frame to load. + // wait once to properly execute the assert. + AddWaitStep("wait for async load", 1); + + AddAssert("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && - p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); + !p.ChildrenOfType().Single().ShowHandle)); } [Test] From c32ba9e38fe45f6200c8305fcc0938046cb792e6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 15:06:11 +0300 Subject: [PATCH 070/366] Remove arbitrarily-set wait step with until step instead, keeping the comment --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 62a9b597ad..f1ddfefe33 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -95,10 +95,8 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for players to load", () => spectatorScreen.AllPlayersLoaded); // components wrapped in skinnable target containers load asynchronously, potentially taking more than one frame to load. - // wait once to properly execute the assert. - AddWaitStep("wait for async load", 1); - - AddAssert("all interactive elements removed", () => this.ChildrenOfType().All(p => + // therefore use until step rather than direct assert to account for that. + AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && !p.ChildrenOfType().Single().ShowHandle)); From 1fed9193f86c4052393c1a58ea09c0f8c2756272 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 13 Aug 2021 15:24:10 +0300 Subject: [PATCH 071/366] Revert reverted segment to fix failure --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index f1ddfefe33..9bb9c24c6b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -99,7 +99,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("all interactive elements removed", () => this.ChildrenOfType().All(p => !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && - !p.ChildrenOfType().Single().ShowHandle)); + p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); } [Test] From 1fcb1cdb108fb4049a8aa3f0d0de78408e50e187 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 22:01:47 +0900 Subject: [PATCH 072/366] Add todo --- osu.Game/Online/Rooms/Room.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 364336783d..d964060f10 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -134,7 +134,7 @@ namespace osu.Game.Online.Rooms /// The position of this in the list. This is not read from or written to the API. /// [JsonIgnore] - public readonly Bindable Position = new Bindable(-1); + public readonly Bindable Position = new Bindable(-1); // Todo: This does not need to exist. public Room() { From 155e9e16a5d08d2bcb52dfaeda81af6903e478f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Aug 2021 22:08:34 +0900 Subject: [PATCH 073/366] Refactorings --- osu.Game/Screens/OnlinePlay/IRoomManager.cs | 12 ++++++++++++ .../Multiplayer/MultiplayerLoungeSubScreen.cs | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/IRoomManager.cs b/osu.Game/Screens/OnlinePlay/IRoomManager.cs index baf84e25f9..6e1ffbda74 100644 --- a/osu.Game/Screens/OnlinePlay/IRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/IRoomManager.cs @@ -23,10 +23,22 @@ namespace osu.Game.Screens.OnlinePlay /// IBindableList Rooms { get; } + /// + /// Adds a to this . + /// If already existing, the local room will be updated with the given one. + /// + /// The incoming . void AddOrUpdateRoom(Room room); + /// + /// Removes a from this . + /// + /// The to remove. void RemoveRoom(Room room); + /// + /// Removes all s from this . + /// void ClearRooms(); /// diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 0756c78211..77db955f0a 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.OnResuming(last); // Upon having left a room, we don't know whether we were the only participant, and whether the room is now closed as a result of leaving it. - // To work around this, temporarily clear all rooms until the next listing poll. + // To work around this, temporarily remove the room and trigger an immediate listing poll. if (last is MultiplayerMatchSubScreen match) { RoomManager.RemoveRoom(match.Room); From 00317c0e30b4896f5086ec1d202013799e174cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 13 Aug 2021 23:44:07 +0200 Subject: [PATCH 074/366] Round when totalling up team scores instead of truncating Matches score handling in `ScoreManager`. --- osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 3f9258930e..362ee4a373 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -184,7 +184,7 @@ namespace osu.Game.Screens.Play.HUD continue; if (TeamScores.TryGetValue(u.Team.Value, out var team)) - team.Value += (int)u.Score.Value; + team.Value += (int)Math.Round(u.Score.Value); } } From e2cc96097f1d53591bb8656bd4da2175b150d76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 13 Aug 2021 23:48:03 +0200 Subject: [PATCH 075/366] Unify match score display formatting Commas are already applied on the multiplayer leaderboard, as well as the results screen. --- osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index 607d08b8ed..68e3f0df7d 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -171,6 +172,8 @@ namespace osu.Game.Screens.Play.HUD => displayedSpriteText.Font = winning ? OsuFont.Torus.With(weight: FontWeight.Bold, size: font_size, fixedWidth: true) : OsuFont.Torus.With(weight: FontWeight.Regular, size: font_size * 0.8f, fixedWidth: true); + + protected override LocalisableString FormatCount(double count) => count.ToLocalisableString(@"N0"); } } } From 5cfb89f18ac02d26168569846255e73703dde9d2 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 14 Aug 2021 10:56:52 +0800 Subject: [PATCH 076/366] Apply suggestions from code review Co-authored-by: Joseph Madamba --- osu.Game/Localisation/UserInterfaceStrings.cs | 2 +- .../Settings/Sections/UserInterface/SongSelectSettings.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/UserInterfaceStrings.cs b/osu.Game/Localisation/UserInterfaceStrings.cs index 18a9257732..fcfaf661dc 100644 --- a/osu.Game/Localisation/UserInterfaceStrings.cs +++ b/osu.Game/Localisation/UserInterfaceStrings.cs @@ -77,7 +77,7 @@ namespace osu.Game.Localisation /// /// "Song Select" /// - public static LocalisableString SoneSelectHeader => new TranslatableString(getKey(@"song_select_header"), @"Song Select"); + public static LocalisableString SongSelectHeader => new TranslatableString(getKey(@"song_select_header"), @"Song Select"); /// /// "Right mouse drag to absolute scroll" diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index 8596cecbb8..6290046987 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface private Bindable minStars; private Bindable maxStars; - protected override LocalisableString Header => UserInterfaceStrings.SoneSelectHeader; + protected override LocalisableString Header => UserInterfaceStrings.SongSelectHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) From e26ccf786e6812a8aca382f061e346f3b5b64a76 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 14 Aug 2021 11:04:38 +0800 Subject: [PATCH 077/366] code style format --- osu.Game/Localisation/OnlineSettingsStrings.cs | 4 ++-- osu.Game/Localisation/SkinSettingsStrings.cs | 2 +- .../Settings/Sections/Online/AlertsAndPrivacySettings.cs | 2 +- osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs | 2 +- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Localisation/OnlineSettingsStrings.cs b/osu.Game/Localisation/OnlineSettingsStrings.cs index 0ef98a720c..0173cc7cbb 100644 --- a/osu.Game/Localisation/OnlineSettingsStrings.cs +++ b/osu.Game/Localisation/OnlineSettingsStrings.cs @@ -27,7 +27,7 @@ namespace osu.Game.Localisation /// /// "Show a notification when you receive a private message" /// - public static LocalisableString NotifyOnPM => new TranslatableString(getKey(@"notify_on_pm"), @"Show a notification when you receive a private message"); + public static LocalisableString NotifyOnPrivateMessage => new TranslatableString(getKey(@"notify_on_private_message"), @"Show a notification when you receive a private message"); /// /// "Integrations" @@ -57,7 +57,7 @@ namespace osu.Game.Localisation /// /// "Automatically download beatmaps when spectating" /// - public static LocalisableString AutomaticallyDownload => new TranslatableString(getKey(@"automatically_download"), @"Automatically download beatmaps when spectating"); + public static LocalisableString AutomaticallyDownloadWhenSpectating => new TranslatableString(getKey(@"automatically_download_when_spectating"), @"Automatically download beatmaps when spectating"); /// /// "Show explicit content in search results" diff --git a/osu.Game/Localisation/SkinSettingsStrings.cs b/osu.Game/Localisation/SkinSettingsStrings.cs index 848c01b93a..f22b4d6bf5 100644 --- a/osu.Game/Localisation/SkinSettingsStrings.cs +++ b/osu.Game/Localisation/SkinSettingsStrings.cs @@ -22,7 +22,7 @@ namespace osu.Game.Localisation /// /// "Gameplay cursor size" /// - public static LocalisableString CursorSize => new TranslatableString(getKey(@"cursor_size"), @"Gameplay cursor size"); + public static LocalisableString GameplayCursorSize => new TranslatableString(getKey(@"gameplay_cursor_size"), @"Gameplay cursor size"); /// /// "Adjust gameplay cursor size based on current beatmap" diff --git a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs index 1728b565c2..351a32c72e 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online }, new SettingsCheckbox { - LabelText = OnlineSettingsStrings.NotifyOnPM, + LabelText = OnlineSettingsStrings.NotifyOnPrivateMessage, Current = config.GetBindable(OsuSetting.NotifyOnPrivateMessage) }, }; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index 4200ddda3d..e864260cc6 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online }, new SettingsCheckbox { - LabelText = OnlineSettingsStrings.AutomaticallyDownload, + LabelText = OnlineSettingsStrings.AutomaticallyDownloadWhenSpectating, Keywords = new[] { "spectator" }, Current = config.GetBindable(OsuSetting.AutomaticallyDownloadWhenSpectating), }, diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 007302c584..e0d8252930 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.Settings.Sections new ExportSkinButton(), new SettingsSlider { - LabelText = SkinSettingsStrings.CursorSize, + LabelText = SkinSettingsStrings.GameplayCursorSize, Current = config.GetBindable(OsuSetting.GameplayCursorSize), KeyboardStep = 0.01f }, From e6b3aba6e19557e2f2d493fb6d5c57a9c71d3b23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 14 Aug 2021 14:08:29 +0900 Subject: [PATCH 078/366] Fix incorrectly directed call in `TestMultiplayerClient` --- osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index a28b4140ca..67b79d7390 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -178,7 +178,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { Debug.Assert(Room != null); - return ((IMultiplayerClient)this).UserLeft(Room.Users.Single(u => u.UserID == userId)); + return ((IMultiplayerClient)this).UserKicked(Room.Users.Single(u => u.UserID == userId)); } public override async Task ChangeSettings(MultiplayerRoomSettings settings) From f87f86e671190c2836b95b801fee7be50aa52b1a Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 14 Aug 2021 21:52:09 +0800 Subject: [PATCH 079/366] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Localisation/GameplaySettingsStrings.cs | 2 +- osu.Game/Localisation/OnlineSettingsStrings.cs | 2 +- osu.Game/Localisation/UserInterfaceStrings.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 2 +- .../Overlays/Settings/Sections/Online/IntegrationSettings.cs | 2 +- .../Settings/Sections/UserInterface/GeneralSettings.cs | 2 +- .../Settings/Sections/UserInterface/MainMenuSettings.cs | 2 +- osu.Game/Overlays/Settings/SettingsSubsection.cs | 5 +++++ 10 files changed, 14 insertions(+), 9 deletions(-) diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index c63fa5ddcc..868eb6b98a 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -42,7 +42,7 @@ namespace osu.Game.Localisation /// /// "Show difficulty graph on progress bar" /// - public static LocalisableString ShowProgressGraph => new TranslatableString(getKey(@"show_progress_graph"), @"Show difficulty graph on progress bar"); + public static LocalisableString ShowDifficultyGraph => new TranslatableString(getKey(@"show_progress_graph"), @"Show difficulty graph on progress bar"); /// /// "Show health display even when you can't fail" diff --git a/osu.Game/Localisation/OnlineSettingsStrings.cs b/osu.Game/Localisation/OnlineSettingsStrings.cs index 0173cc7cbb..6862f4ac2c 100644 --- a/osu.Game/Localisation/OnlineSettingsStrings.cs +++ b/osu.Game/Localisation/OnlineSettingsStrings.cs @@ -32,7 +32,7 @@ namespace osu.Game.Localisation /// /// "Integrations" /// - public static LocalisableString IntegrationHeader => new TranslatableString(getKey(@"integration_header"), @"Integrations"); + public static LocalisableString IntegrationsHeader => new TranslatableString(getKey(@"integrations_header"), @"Integrations"); /// /// "Discord Rich Presence" diff --git a/osu.Game/Localisation/UserInterfaceStrings.cs b/osu.Game/Localisation/UserInterfaceStrings.cs index fcfaf661dc..4be403edb4 100644 --- a/osu.Game/Localisation/UserInterfaceStrings.cs +++ b/osu.Game/Localisation/UserInterfaceStrings.cs @@ -37,7 +37,7 @@ namespace osu.Game.Localisation /// /// "Hold-to-confirm activation time" /// - public static LocalisableString HoldActivationDelay => new TranslatableString(getKey(@"hold_activation_delay"), @"Hold-to-confirm activation time"); + public static LocalisableString HoldToConfirmActivationTime => new TranslatableString(getKey(@"hold_to_confirm_activation_time"), @"Hold-to-confirm activation time"); /// /// "Main Menu" diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 04332fcdd3..3a0265e453 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - LabelText = GameplaySettingsStrings.ShowProgressGraph, + LabelText = GameplaySettingsStrings.ShowDifficultyGraph, Current = config.GetBindable(OsuSetting.ShowProgressGraph) }, new SettingsCheckbox diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 50bd8184ee..124b3b804c 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -146,7 +146,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { updateResolutionDropdown(); - windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : string.Empty; + windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : default; }, 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 9747f6b373..653f30a018 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 frameLimiterDropdown.Current.BindValueChanged(limit => { - frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? GraphicsSettingsStrings.UnlimitedFramesNote : string.Empty; + frameLimiterDropdown.WarningText = limit.NewValue == FrameSync.Unlimited ? GraphicsSettingsStrings.UnlimitedFramesNote : default; }, true); } } diff --git a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs index f2a516feef..0207f2fd01 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online { public class IntegrationSettings : SettingsSubsection { - protected override LocalisableString Header => OnlineSettingsStrings.IntegrationHeader; + protected override LocalisableString Header => OnlineSettingsStrings.IntegrationsHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index b26363a9da..0afbed5df5 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface }, new SettingsSlider { - LabelText = UserInterfaceStrings.HoldActivationDelay, + LabelText = UserInterfaceStrings.HoldToConfirmActivationTime, Current = config.GetBindable(OsuSetting.UIHoldActivationDelay), KeyboardStep = 50 }, diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index 976893bf0a..40485a070c 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 user.BindValueChanged(u => { - backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? UserInterfaceStrings.NotSupporterNote : string.Empty; + backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? UserInterfaceStrings.NotSupporterNote : default; }, true); } } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index df32424b67..4aa9360452 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -24,6 +24,11 @@ namespace osu.Game.Overlays.Settings protected abstract LocalisableString Header { get; } public IEnumerable FilterableChildren => Children.OfType(); + + // FilterTerms should contains both original string and localised string for user to search. + // Since LocalisableString is unable to get original string at this time (2021-08-14), + // only call .ToString() to use localised one. + // TODO: Update here when FilterTerms accept LocalisableString. public virtual IEnumerable FilterTerms => new[] { Header.ToString() }; public bool MatchingFilter From c2bbe175627ce35f1d63bc7c627b35b4883de5a0 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Sat, 14 Aug 2021 22:35:15 +0800 Subject: [PATCH 080/366] Rename element in OsuSettings enum `ShowProgressGraph` -> `ShowDifficultyGraph` --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 60a0d5a0ac..6c7adcc806 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -101,7 +101,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.HitLighting, true); SetDefault(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always); - SetDefault(OsuSetting.ShowProgressGraph, true); + SetDefault(OsuSetting.ShowDifficultyGraph, true); SetDefault(OsuSetting.ShowHealthDisplayWhenCantFail, true); SetDefault(OsuSetting.FadePlayfieldWhenHealthLow, true); SetDefault(OsuSetting.KeyOverlay, false); @@ -217,7 +217,7 @@ namespace osu.Game.Configuration AlwaysPlayFirstComboBreak, FloatingComments, HUDVisibilityMode, - ShowProgressGraph, + ShowDifficultyGraph, ShowHealthDisplayWhenCantFail, FadePlayfieldWhenHealthLow, MouseDisableButtons, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 353292606f..69aa57082a 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsCheckbox { LabelText = "Show difficulty graph on progress bar", - Current = config.GetBindable(OsuSetting.ShowProgressGraph) + Current = config.GetBindable(OsuSetting.ShowDifficultyGraph) }, new SettingsCheckbox { diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index f28622f42e..6aa7e017ce 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -125,7 +125,7 @@ namespace osu.Game.Screens.Play Objects = drawableRuleset.Objects; } - config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph); + config.BindWith(OsuSetting.ShowDifficultyGraph, ShowGraph); graph.FillColour = bar.FillColour = colours.BlueLighter; } From 498462dfd0751fbbe480161d4c66487e4f58cc39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 14 Aug 2021 17:24:14 +0200 Subject: [PATCH 081/366] Fix room null-check racing against async schedule --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 57dbfbb507..2a0635c98c 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -190,8 +190,7 @@ namespace osu.Game.Online.Multiplayer return joinOrLeaveTaskChain.Add(async () => { await scheduledReset.ConfigureAwait(false); - if (Room != null) - await LeaveRoomInternal().ConfigureAwait(false); + await LeaveRoomInternal().ConfigureAwait(false); }); } From 246a8882ce248f35ba238875db35d281473e12f6 Mon Sep 17 00:00:00 2001 From: LiangXiang Shen Date: Sun, 15 Aug 2021 00:23:14 +0800 Subject: [PATCH 082/366] Update translation key --- osu.Game/Localisation/GameplaySettingsStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index 868eb6b98a..6d6381b429 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -42,7 +42,7 @@ namespace osu.Game.Localisation /// /// "Show difficulty graph on progress bar" /// - public static LocalisableString ShowDifficultyGraph => new TranslatableString(getKey(@"show_progress_graph"), @"Show difficulty graph on progress bar"); + public static LocalisableString ShowDifficultyGraph => new TranslatableString(getKey(@"show_difficulty_graph"), @"Show difficulty graph on progress bar"); /// /// "Show health display even when you can't fail" From 2ddf28346aa2873bef9cb9edf313f8fe0b52e721 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 14 Aug 2021 19:58:20 +0300 Subject: [PATCH 083/366] PlayerSettingsGroups -> PlayerSettings --- .../Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs | 2 +- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index f28c2a1d48..14bd8fa6dc 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate [BackgroundDependencyLoader] private void load() { - PlayerSettingsGroups.Expire(); + PlayerSettings.Expire(); } protected override void LogoArriving(OsuLogo logo, bool resuming) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 1f8387ac67..a6592e4d24 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Play /// /// A fill flow containing the player settings groups, exposed for the ability to hide it from inheritors of the player loader. /// - protected FillFlowContainer PlayerSettingsGroups; + protected FillFlowContainer PlayerSettings; protected VisualSettings VisualSettings; @@ -145,7 +145,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - PlayerSettingsGroups = new FillFlowContainer + PlayerSettings = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From c8fb79666064f6ead2485aeec1757d1407cda909 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 14 Aug 2021 20:14:21 +0300 Subject: [PATCH 084/366] Fix settings notice text class tinting everything with yellow --- osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs | 2 +- osu.Game/Overlays/Settings/SettingsItem.cs | 2 +- osu.Game/Overlays/Settings/SettingsNoticeText.cs | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 2816eb7037..c561b693d8 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -91,7 +91,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input Origin = Anchor.TopCentre, Text = TabletSettingsStrings.NoTabletDetected, }, - new SettingsNoticeText + new SettingsNoticeText(colours) { TextAnchor = Anchor.TopCentre, Anchor = Anchor.TopCentre, diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 5d25605360..ef2027fdab 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Settings return; // construct lazily for cases where the label is not needed (may be provided by the Control). - FlowContent.Add(warningText = new SettingsNoticeText { Margin = new MarginPadding { Bottom = 5 } }); + FlowContent.Add(warningText = new SettingsNoticeText(colours) { Margin = new MarginPadding { Bottom = 5 } }); } warningText.Alpha = hasValue ? 0 : 1; diff --git a/osu.Game/Overlays/Settings/SettingsNoticeText.cs b/osu.Game/Overlays/Settings/SettingsNoticeText.cs index 6bb4a3f11c..76ecf7edd4 100644 --- a/osu.Game/Overlays/Settings/SettingsNoticeText.cs +++ b/osu.Game/Overlays/Settings/SettingsNoticeText.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.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -10,10 +9,9 @@ namespace osu.Game.Overlays.Settings { public class SettingsNoticeText : LinkFlowContainer { - [BackgroundDependencyLoader] - private void load(OsuColour colours) + public SettingsNoticeText(OsuColour colours) + : base(s => s.Colour = colours.Yellow) { - Colour = colours.Yellow; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; } From 95943fdb25c763a10849f9dff6dffb4fa7466919 Mon Sep 17 00:00:00 2001 From: Jacob Van Meter Date: Sat, 14 Aug 2021 20:00:26 -0400 Subject: [PATCH 085/366] Add glow to supporter promo on changelog Added glow to the supporter promo at the end of the changelog, as it is on the website. --- .../Changelog/ChangelogSupporterPromo.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index f617b4fc82..46fab30d5e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -138,14 +138,28 @@ namespace osu.Game.Overlays.Changelog FillMode = FillMode.Fill, Texture = textures.Get(@"Online/supporter-pippi"), }, - new Sprite + new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Width = 75, Height = 75, - Margin = new MarginPadding { Top = 70 }, - Texture = textures.Get(@"Online/supporter-heart"), + Margin = new MarginPadding { Top = 83 }, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.HotPink.Opacity(0.88f), + Offset = new Vector2(0, 0), + Radius = 17, + Roundness = 39f, + }, + Child = new Sprite + { + Width = 75, + Height = 75, + Texture = textures.Get(@"Online/supporter-heart"), + }, }, }; } From 772860232cbbfad9ca85c68d413465405828279b Mon Sep 17 00:00:00 2001 From: Jacob Van Meter Date: Sat, 14 Aug 2021 20:32:38 -0400 Subject: [PATCH 086/366] Removed empty offset and corrected colour --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 46fab30d5e..203a371f43 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -149,8 +149,7 @@ namespace osu.Game.Overlays.Changelog EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, - Colour = Color4.HotPink.Opacity(0.88f), - Offset = new Vector2(0, 0), + Colour = colour.Pink, Radius = 17, Roundness = 39f, }, From 71ccd38bb35e6276205152edb953daedc0affb34 Mon Sep 17 00:00:00 2001 From: Jacob Van Meter Date: Sat, 14 Aug 2021 20:36:43 -0400 Subject: [PATCH 087/366] Corrected pippi background and promo positioning --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 203a371f43..f8613b101e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -134,6 +134,7 @@ namespace osu.Game.Overlays.Changelog { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Margin = new MarginPadding { Bottom = 28 }, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fill, Texture = textures.Get(@"Online/supporter-pippi"), @@ -144,7 +145,7 @@ namespace osu.Game.Overlays.Changelog Origin = Anchor.TopCentre, Width = 75, Height = 75, - Margin = new MarginPadding { Top = 83 }, + Margin = new MarginPadding { Top = 70 }, Masking = true, EdgeEffect = new EdgeEffectParameters { From 7d6f7ac75e496c6cff379c7f471e805267e02047 Mon Sep 17 00:00:00 2001 From: Opelkuh <25430283+Opelkuh@users.noreply.github.com> Date: Sun, 15 Aug 2021 02:57:11 +0200 Subject: [PATCH 088/366] Fix mark channel as read error --- osu.Game/Online/Chat/ChannelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 3136a3960d..1937019ef6 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -553,7 +553,7 @@ namespace osu.Game.Online.Chat if (channel.LastMessageId == channel.LastReadId) return; - var message = channel.Messages.LastOrDefault(); + var message = channel.Messages.FindLast(msg => !(msg is LocalMessage)); if (message == null) return; From 6472d85aae3377c7f37bb233aace478cfad8ab06 Mon Sep 17 00:00:00 2001 From: Jacob Van Meter Date: Sat, 14 Aug 2021 21:48:57 -0400 Subject: [PATCH 089/366] Added heart_size constant and adjusted the glow radius value Added heart_size constant and adjusted the glow radius value to be more in line with the website --- .../Overlays/Changelog/ChangelogSupporterPromo.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index f8613b101e..c51f927f9f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -24,6 +24,7 @@ namespace osu.Game.Overlays.Changelog public class ChangelogSupporterPromo : CompositeDrawable { private const float image_container_width = 164; + private const float heart_size = 75; private readonly FillFlowContainer textContainer; private readonly Container imageContainer; @@ -143,21 +144,21 @@ namespace osu.Game.Overlays.Changelog { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Width = 75, - Height = 75, + Width = heart_size, + Height = heart_size, Margin = new MarginPadding { Top = 70 }, Masking = true, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, Colour = colour.Pink, - Radius = 17, - Roundness = 39f, + Radius = 10, + Roundness = heart_size / 2, }, Child = new Sprite { - Width = 75, - Height = 75, + Width = heart_size, + Height = heart_size, Texture = textures.Get(@"Online/supporter-heart"), }, }, From d287db796172a213dce4a079e27b22e42a320bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Sch=C3=BCrz?= Date: Sun, 15 Aug 2021 14:48:56 +0200 Subject: [PATCH 090/366] Clamping seekTime to beatmap length --- osu.Game/Screens/Edit/EditorClock.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 772f6ea192..52c95088f3 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -118,6 +118,7 @@ namespace osu.Game.Screens.Edit if (!snapped || ControlPointInfo.TimingPoints.Count == 0) { + seekTime = Math.Clamp(seekTime, 0, TrackLength); SeekSmoothlyTo(seekTime); return; } From f9e2e808743403cafd862f1fd1177a1bc0f8b4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 15:04:14 +0200 Subject: [PATCH 091/366] Add testing for auto-restart behaviour --- .../Visual/Mods/TestSceneModFailCondition.cs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs new file mode 100644 index 0000000000..af874cec91 --- /dev/null +++ b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs @@ -0,0 +1,55 @@ +// 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.Containers; +using osu.Framework.Testing; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Mods +{ + public class TestSceneModFailCondition : ModTestScene + { + private bool restartRequested; + + protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); + + protected override TestPlayer CreateModPlayer(Ruleset ruleset) + { + var player = base.CreateModPlayer(ruleset); + player.RestartRequested = () => restartRequested = true; + return player; + } + + protected override bool AllowFail => true; + + [SetUpSteps] + public void SetUp() + { + AddStep("reset flag", () => restartRequested = false); + } + + [Test] + public void TestRestartOnFailDisabled() => CreateModTest(new ModTestData + { + Autoplay = false, + Mod = new OsuModSuddenDeath(), + PassCondition = () => !restartRequested && Player.ChildrenOfType().Single().State.Value == Visibility.Visible + }); + + [Test] + public void TestRestartOnFailEnabled() => CreateModTest(new ModTestData + { + Autoplay = false, + Mod = new OsuModSuddenDeath + { + Restart = { Value = true } + }, + PassCondition = () => restartRequested && Player.ChildrenOfType().Single().State.Value == Visibility.Hidden + }); + } +} From 2f9f1ba862cf7c54dca3063e0c33dee9fef55c01 Mon Sep 17 00:00:00 2001 From: Opelkuh <25430283+Opelkuh@users.noreply.github.com> Date: Sun, 15 Aug 2021 15:44:23 +0200 Subject: [PATCH 092/366] Add test for `ChannelManager.MarkChannelAsRead` --- .../Chat/TestSceneChannelManager.cs | 57 ++++++++++++++++++- .../API/Requests/MarkChannelAsReadRequest.cs | 10 ++-- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index 0ec21a4c7b..7b6d2078ca 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -19,6 +20,7 @@ namespace osu.Game.Tests.Chat { private ChannelManager channelManager; private int currentMessageId; + List sentMessages; [SetUp] public void Setup() => Schedule(() => @@ -34,6 +36,7 @@ namespace osu.Game.Tests.Chat AddStep("register request handling", () => { currentMessageId = 0; + sentMessages = new List(); ((DummyAPIAccess)API).HandleRequest = req => { @@ -44,7 +47,7 @@ namespace osu.Game.Tests.Chat return true; case PostMessageRequest postMessage: - postMessage.TriggerSuccess(new Message(++currentMessageId) + var message = new Message(++currentMessageId) { IsAction = postMessage.Message.IsAction, ChannelId = postMessage.Message.ChannelId, @@ -52,7 +55,10 @@ namespace osu.Game.Tests.Chat Links = postMessage.Message.Links, Timestamp = postMessage.Message.Timestamp, Sender = postMessage.Message.Sender - }); + }; + + sentMessages.Add(message); + postMessage.TriggerSuccess(message); return true; } @@ -83,12 +89,59 @@ namespace osu.Game.Tests.Chat AddAssert("/np command received by channel 2", () => channel2.Messages.Last().Content.Contains("is listening to")); } + [Test] + public void TestMarkAsReadIgnoringLocalMessages() { + Channel channel = null; + + AddStep("join channel and select it", () => + { + channelManager.JoinChannel(channel = createChannel(1, ChannelType.Public)); + + channelManager.CurrentChannel.Value = channel; + }); + + AddStep("post message", () => channelManager.PostMessage("Something interesting")); + AddUntilStep("wait until the message is posted", () => channel.Messages.Count == sentMessages.Count); + + AddStep("post /help command", () => channelManager.PostCommand("help", channel)); + AddStep("post /me command with no action", () => channelManager.PostCommand("me", channel)); + AddStep("post /join command with no channel", () => channelManager.PostCommand("join", channel)); + AddStep("post /join command with non-existent channel", () => channelManager.PostCommand("join i-dont-exist", channel)); + AddStep("post non-existent command", () => channelManager.PostCommand("non-existent-cmd arg", channel)); + + AddStep("register mark channel as read request handler", () => { + ((DummyAPIAccess)API).HandleRequest = req => + { + switch (req) + { + case MarkChannelAsReadRequest markRead: + var isSentMessage = sentMessages.Contains(markRead.Message); + + AddAssert("mark channel as read called with a real message", () => isSentMessage); + + if(isSentMessage) { + markRead.TriggerSuccess(); + } else { + markRead.TriggerFailure(new APIException("unknown message!", null)); + } + + return true; + } + + return false; + }; + }); + + AddStep("mark channel as read", () => channelManager.MarkChannelAsRead(channel)); + } + private Channel createChannel(int id, ChannelType type) => new Channel(new User()) { Id = id, Name = $"Channel {id}", Topic = $"Topic of channel {id} with type {type}", Type = type, + LastMessageId = 0, }; private class ChannelManagerContainer : CompositeDrawable diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index 95a5d0acbd..594ab2accc 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -9,16 +9,16 @@ namespace osu.Game.Online.API.Requests { public class MarkChannelAsReadRequest : APIRequest { - private readonly Channel channel; - private readonly Message message; + public readonly Channel Channel; + public readonly Message Message; public MarkChannelAsReadRequest(Channel channel, Message message) { - this.channel = channel; - this.message = message; + this.Channel = channel; + this.Message = message; } - protected override string Target => $"chat/channels/{channel.Id}/mark-as-read/{message.Id}"; + protected override string Target => $"chat/channels/{Channel.Id}/mark-as-read/{Message.Id}"; protected override WebRequest CreateWebRequest() { From 7d7c5c06f06a3d5f987623defcdc878e518fed26 Mon Sep 17 00:00:00 2001 From: Opelkuh <25430283+Opelkuh@users.noreply.github.com> Date: Sun, 15 Aug 2021 16:02:25 +0200 Subject: [PATCH 093/366] Fix code formatting --- .../Chat/TestSceneChannelManager.cs | 41 ++++++++++--------- .../API/Requests/MarkChannelAsReadRequest.cs | 4 +- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index 7b6d2078ca..fcb602cb04 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Chat { private ChannelManager channelManager; private int currentMessageId; - List sentMessages; + private List sentMessages; [SetUp] public void Setup() => Schedule(() => @@ -90,46 +90,49 @@ namespace osu.Game.Tests.Chat } [Test] - public void TestMarkAsReadIgnoringLocalMessages() { + public void TestMarkAsReadIgnoringLocalMessages() + { Channel channel = null; AddStep("join channel and select it", () => { channelManager.JoinChannel(channel = createChannel(1, ChannelType.Public)); - channelManager.CurrentChannel.Value = channel; }); AddStep("post message", () => channelManager.PostMessage("Something interesting")); AddUntilStep("wait until the message is posted", () => channel.Messages.Count == sentMessages.Count); - AddStep("post /help command", () => channelManager.PostCommand("help", channel)); AddStep("post /me command with no action", () => channelManager.PostCommand("me", channel)); AddStep("post /join command with no channel", () => channelManager.PostCommand("join", channel)); AddStep("post /join command with non-existent channel", () => channelManager.PostCommand("join i-dont-exist", channel)); AddStep("post non-existent command", () => channelManager.PostCommand("non-existent-cmd arg", channel)); - AddStep("register mark channel as read request handler", () => { + AddStep("register mark channel as read request handler", () => + { ((DummyAPIAccess)API).HandleRequest = req => + { + switch (req) { - switch (req) - { - case MarkChannelAsReadRequest markRead: - var isSentMessage = sentMessages.Contains(markRead.Message); + case MarkChannelAsReadRequest markRead: + var isSentMessage = sentMessages.Contains(markRead.Message); - AddAssert("mark channel as read called with a real message", () => isSentMessage); + AddAssert("mark channel as read called with a real message", () => isSentMessage); - if(isSentMessage) { - markRead.TriggerSuccess(); - } else { - markRead.TriggerFailure(new APIException("unknown message!", null)); - } + if (isSentMessage) + { + markRead.TriggerSuccess(); + } + else + { + markRead.TriggerFailure(new APIException("unknown message!", null)); + } - return true; - } + return true; + } - return false; - }; + return false; + }; }); AddStep("mark channel as read", () => channelManager.MarkChannelAsRead(channel)); diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index 594ab2accc..b24669e6d5 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -14,8 +14,8 @@ namespace osu.Game.Online.API.Requests public MarkChannelAsReadRequest(Channel channel, Message message) { - this.Channel = channel; - this.Message = message; + Channel = channel; + Message = message; } protected override string Target => $"chat/channels/{Channel.Id}/mark-as-read/{Message.Id}"; From 7c88a1c6dee143dbea7f60530c7fe17acd50cf0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 16:00:22 +0200 Subject: [PATCH 094/366] Add a way to change custom combo colours via `IHasComboColours` `IHasComboColours` was already mutable (via a strange `AddComboColours()` method) and exposing a straight list is easier to work with. `IHasCustomColours` is also similarly externally mutable (in a way which is not easily removable). --- osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs | 5 +++-- osu.Game/Beatmaps/Formats/IHasComboColours.cs | 9 +++++++++ osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- osu.Game/Skinning/DefaultLegacySkin.cs | 6 ++++-- osu.Game/Skinning/SkinConfiguration.cs | 8 ++++---- osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs | 4 ++-- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index c15d804a19..aadabec100 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -133,11 +133,12 @@ namespace osu.Game.Tests.Skins [Test] public void TestEmptyComboColoursNoFallback() { - AddStep("Add custom combo colours to user skin", () => userSource.Configuration.AddComboColours( + AddStep("Add custom combo colours to user skin", () => userSource.Configuration.CustomComboColours = new List + { new Color4(100, 150, 200, 255), new Color4(55, 110, 166, 255), new Color4(75, 125, 175, 255) - )); + }); AddStep("Disallow default colours fallback in beatmap skin", () => beatmapSource.Configuration.AllowDefaultComboColoursFallback = false); diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index 41c85db063..91d960a2fb 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using osuTK.Graphics; @@ -13,9 +14,17 @@ namespace osu.Game.Beatmaps.Formats /// IReadOnlyList ComboColours { get; } + /// + /// The list of custom combo colours. + /// If non-empty, will return these colours; + /// if empty, will fall back to default combo colours. + /// + List CustomComboColours { get; } + /// /// Adds combo colours to the list. /// + [Obsolete("Use SkinConfiguration.ComboColours directly.")] // can be removed 20220215 void AddComboColours(params Color4[] colours); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index b39890084f..20080308f9 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -123,7 +123,7 @@ namespace osu.Game.Beatmaps.Formats { if (!(output is IHasComboColours tHasComboColours)) return; - tHasComboColours.AddComboColours(colour); + tHasComboColours.CustomComboColours.Add(colour); } else { diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 30192182f3..16ac17546d 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using JetBrains.Annotations; using osu.Framework.IO.Stores; using osu.Game.Extensions; @@ -21,12 +22,13 @@ namespace osu.Game.Skinning : base(skin, new NamespacedResourceStore(resources.Resources, "Skins/Legacy"), resources, string.Empty) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); - Configuration.AddComboColours( + Configuration.CustomComboColours = new List + { new Color4(255, 192, 0, 255), new Color4(0, 202, 0, 255), new Color4(18, 124, 255, 255), new Color4(242, 24, 57, 255) - ); + }; Configuration.LegacyVersion = 2.7m; } diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 25a924c929..a18144246f 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -27,14 +27,14 @@ namespace osu.Game.Skinning new Color4(242, 24, 57, 255), }; - private readonly List comboColours = new List(); + public List CustomComboColours { get; set; } = new List(); public IReadOnlyList ComboColours { get { - if (comboColours.Count > 0) - return comboColours; + if (CustomComboColours.Count > 0) + return CustomComboColours; if (AllowDefaultComboColoursFallback) return DefaultComboColours; @@ -43,7 +43,7 @@ namespace osu.Game.Skinning } } - public void AddComboColours(params Color4[] colours) => comboColours.AddRange(colours); + void IHasComboColours.AddComboColours(params Color4[] colours) => CustomComboColours.AddRange(colours); public Dictionary CustomColours { get; } = new Dictionary(); diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index cdf6a9a2b4..356d2c848c 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -116,7 +116,7 @@ namespace osu.Game.Tests.Beatmaps { if (hasColours) { - Configuration.AddComboColours(Colours); + Configuration.CustomComboColours = Colours.ToList(); Configuration.CustomColours.Add("HyperDash", HYPER_DASH_COLOUR); Configuration.CustomColours.Add("HyperDashAfterImage", HYPER_DASH_AFTER_IMAGE_COLOUR); Configuration.CustomColours.Add("HyperDashFruit", HYPER_DASH_FRUIT_COLOUR); @@ -145,7 +145,7 @@ namespace osu.Game.Tests.Beatmaps { if (hasCustomColours) { - Configuration.AddComboColours(Colours); + Configuration.CustomComboColours = Colours.ToList(); Configuration.CustomColours.Add("HyperDash", HYPER_DASH_COLOUR); Configuration.CustomColours.Add("HyperDashAfterImage", HYPER_DASH_AFTER_IMAGE_COLOUR); Configuration.CustomColours.Add("HyperDashFruit", HYPER_DASH_FRUIT_COLOUR); From 8f698a42f727472723668931713ae4671af2ace0 Mon Sep 17 00:00:00 2001 From: Opelkuh <25430283+Opelkuh@users.noreply.github.com> Date: Sun, 15 Aug 2021 20:35:52 +0200 Subject: [PATCH 095/366] Refactor `MarkChannelAsRead` test assert --- .../Chat/TestSceneChannelManager.cs | 75 +++++++++---------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index fcb602cb04..5e22101e5c 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -47,19 +47,11 @@ namespace osu.Game.Tests.Chat return true; case PostMessageRequest postMessage: - var message = new Message(++currentMessageId) - { - IsAction = postMessage.Message.IsAction, - ChannelId = postMessage.Message.ChannelId, - Content = postMessage.Message.Content, - Links = postMessage.Message.Links, - Timestamp = postMessage.Message.Timestamp, - Sender = postMessage.Message.Sender - }; - - sentMessages.Add(message); - postMessage.TriggerSuccess(message); + handlePostMessageRequest(postMessage); + return true; + case MarkChannelAsReadRequest markRead: + handleMarkChannelAsReadRequest(markRead); return true; } @@ -101,41 +93,44 @@ namespace osu.Game.Tests.Chat }); AddStep("post message", () => channelManager.PostMessage("Something interesting")); - AddUntilStep("wait until the message is posted", () => channel.Messages.Count == sentMessages.Count); + AddStep("post /help command", () => channelManager.PostCommand("help", channel)); AddStep("post /me command with no action", () => channelManager.PostCommand("me", channel)); AddStep("post /join command with no channel", () => channelManager.PostCommand("join", channel)); AddStep("post /join command with non-existent channel", () => channelManager.PostCommand("join i-dont-exist", channel)); AddStep("post non-existent command", () => channelManager.PostCommand("non-existent-cmd arg", channel)); - AddStep("register mark channel as read request handler", () => - { - ((DummyAPIAccess)API).HandleRequest = req => - { - switch (req) - { - case MarkChannelAsReadRequest markRead: - var isSentMessage = sentMessages.Contains(markRead.Message); - - AddAssert("mark channel as read called with a real message", () => isSentMessage); - - if (isSentMessage) - { - markRead.TriggerSuccess(); - } - else - { - markRead.TriggerFailure(new APIException("unknown message!", null)); - } - - return true; - } - - return false; - }; - }); - AddStep("mark channel as read", () => channelManager.MarkChannelAsRead(channel)); + AddAssert("channel's last read ID is set to the latest message", () => channel.LastReadId == sentMessages.Last().Id); + } + + private void handlePostMessageRequest(PostMessageRequest request) + { + var message = new Message(++currentMessageId) + { + IsAction = request.Message.IsAction, + ChannelId = request.Message.ChannelId, + Content = request.Message.Content, + Links = request.Message.Links, + Timestamp = request.Message.Timestamp, + Sender = request.Message.Sender + }; + + sentMessages.Add(message); + request.TriggerSuccess(message); + } + + private void handleMarkChannelAsReadRequest(MarkChannelAsReadRequest request) + { + // only accept messages that were sent through the API + if (sentMessages.Contains(request.Message)) + { + request.TriggerSuccess(); + } + else + { + request.TriggerFailure(new APIException("unknown message!", null)); + } } private Channel createChannel(int id, ChannelType type) => new Channel(new User()) From 29a22bd11f4b82304a14a1501ec48a373d4c1651 Mon Sep 17 00:00:00 2001 From: emu1337 Date: Sun, 15 Aug 2021 20:48:00 +0200 Subject: [PATCH 096/366] added rhythm multiplier for strain sections --- osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 15 +++++++++++++++ .../Rulesets/Difficulty/Skills/StrainSkill.cs | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index f0eb199e5f..b1373cd215 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -34,6 +34,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills { } + private double calculateRhythmBonus(double time) + { + return 1.0; + } + + protected override double StrainValueOf(DifficultyHitObject current) { if (current.BaseObject is Spinner) @@ -66,5 +72,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / osuCurrent.StrainTime; } + protected override double GetTotalCurrentStrain(DifficultyHitObject current) + { + return base.GetTotalCurrentStrain(current) * calculateRhythmBonus(current.StartTime); + } + + protected override double GetPeakStrain(double time) + { + return base.GetPeakStrain(time) * calculateRhythmBonus(time); + } } } diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index d4fcefab9b..95b0fe43fc 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -71,7 +71,12 @@ namespace osu.Game.Rulesets.Difficulty.Skills CurrentStrain *= strainDecay(current.DeltaTime); CurrentStrain += StrainValueOf(current) * SkillMultiplier; - currentSectionPeak = Math.Max(CurrentStrain, currentSectionPeak); + currentSectionPeak = Math.Max(GetTotalCurrentStrain(current), currentSectionPeak); + } + + protected virtual double GetTotalCurrentStrain(DifficultyHitObject current) + { + return CurrentStrain; } /// From df43e758ee18c95ca49e36c05e526517b38646b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 16:13:59 +0200 Subject: [PATCH 097/366] Add editable beatmap skin --- osu.Game/Screens/Edit/EditorBeatmap.cs | 5 +- osu.Game/Screens/Edit/EditorBeatmapSkin.cs | 59 ++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/Edit/EditorBeatmapSkin.cs diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 7de98e5e85..3402bf653a 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Edit private readonly Bindable hasTiming = new Bindable(); [CanBeNull] - public readonly ISkin BeatmapSkin; + public readonly EditorBeatmapSkin BeatmapSkin; [Resolved] private BindableBeatDivisor beatDivisor { get; set; } @@ -69,7 +69,8 @@ namespace osu.Game.Screens.Edit public EditorBeatmap(IBeatmap playableBeatmap, ISkin beatmapSkin = null) { PlayableBeatmap = playableBeatmap; - BeatmapSkin = beatmapSkin; + if (beatmapSkin is Skin skin) + BeatmapSkin = new EditorBeatmapSkin(skin); beatmapProcessor = playableBeatmap.BeatmapInfo.Ruleset?.CreateInstance().CreateBeatmapProcessor(PlayableBeatmap); diff --git a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs new file mode 100644 index 0000000000..6745f08b80 --- /dev/null +++ b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs @@ -0,0 +1,59 @@ +// 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.Linq; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.OpenGL.Textures; +using osu.Framework.Graphics.Textures; +using osu.Game.Audio; +using osu.Game.Skinning; +using osuTK.Graphics; + +namespace osu.Game.Screens.Edit +{ + /// + /// A beatmap skin which is being edited. + /// + public class EditorBeatmapSkin : ISkin + { + public event Action BeatmapSkinChanged; + + /// + /// The combo colours of this skin. + /// If empty, the default combo colours will be used. + /// + public BindableList ComboColours; + + private readonly Skin skin; + + public EditorBeatmapSkin(Skin skin) + { + this.skin = skin; + + ComboColours = new BindableList(); + if (skin.Configuration.ComboColours != null) + ComboColours.AddRange(skin.Configuration.ComboColours.Select(c => (Colour4)c)); + ComboColours.BindCollectionChanged((_, __) => updateColours()); + } + + private void invokeSkinChanged() => BeatmapSkinChanged?.Invoke(); + + private void updateColours() + { + skin.Configuration.CustomComboColours = ComboColours.Select(c => (Color4)c).ToList(); + invokeSkinChanged(); + } + + #region Delegated ISkin implementation + + public Drawable GetDrawableComponent(ISkinComponent component) => skin.GetDrawableComponent(component); + public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => skin.GetTexture(componentName, wrapModeS, wrapModeT); + public ISample GetSample(ISampleInfo sampleInfo) => skin.GetSample(sampleInfo); + public IBindable GetConfig(TLookup lookup) => skin.GetConfig(lookup); + + #endregion + } +} From 0d64da8c63f1e6533f62defaddc21d6b6bc727ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 16:14:41 +0200 Subject: [PATCH 098/366] Add skin providing container responding to beatmap skin edits --- .../Screens/Edit/Compose/ComposeScreen.cs | 3 +- .../Edit/EditorSkinProvidingContainer.cs | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 4a1f1196a9..62b3d33069 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -15,7 +15,6 @@ using osu.Game.Extensions; using osu.Game.Rulesets; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; -using osu.Game.Skinning; namespace osu.Game.Screens.Edit.Compose { @@ -73,7 +72,7 @@ namespace osu.Game.Screens.Edit.Compose { Debug.Assert(ruleset != null); - return new RulesetSkinProvidingContainer(ruleset, EditorBeatmap.PlayableBeatmap, beatmap.Value.Skin).WithChild(content); + return new EditorSkinProvidingContainer(EditorBeatmap).WithChild(content); } #region Input Handling diff --git a/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs b/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs new file mode 100644 index 0000000000..27563b5a0f --- /dev/null +++ b/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs @@ -0,0 +1,40 @@ +// 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.Skinning; + +#nullable enable + +namespace osu.Game.Screens.Edit +{ + /// + /// A that fires when users have made a change to the beatmap skin + /// of the map being edited. + /// + public class EditorSkinProvidingContainer : RulesetSkinProvidingContainer + { + private readonly EditorBeatmapSkin? beatmapSkin; + + public EditorSkinProvidingContainer(EditorBeatmap editorBeatmap) + : base(editorBeatmap.PlayableBeatmap.BeatmapInfo.Ruleset.CreateInstance(), editorBeatmap, editorBeatmap.BeatmapSkin) + { + beatmapSkin = editorBeatmap.BeatmapSkin; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (beatmapSkin != null) + beatmapSkin.BeatmapSkinChanged += TriggerSourceChanged; + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (beatmapSkin != null) + beatmapSkin.BeatmapSkinChanged -= TriggerSourceChanged; + } + } +} From 81280dfd257fe482e0baeab20c828849b26837a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 16:32:26 +0200 Subject: [PATCH 099/366] Use editable skin structure in combo colour picker --- osu.Game/Screens/Edit/Setup/ColoursSection.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/ColoursSection.cs b/osu.Game/Screens/Edit/Setup/ColoursSection.cs index d7e16645f2..05d9855a24 100644 --- a/osu.Game/Screens/Edit/Setup/ColoursSection.cs +++ b/osu.Game/Screens/Edit/Setup/ColoursSection.cs @@ -1,14 +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.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Skinning; -using osuTK.Graphics; namespace osu.Game.Screens.Edit.Setup { @@ -31,9 +27,8 @@ namespace osu.Game.Screens.Edit.Setup } }; - var colours = Beatmap.BeatmapSkin?.GetConfig>(GlobalSkinColours.ComboColours)?.Value; - if (colours != null) - comboColours.Colours.AddRange(colours.Select(c => (Colour4)c)); + if (Beatmap.BeatmapSkin != null) + comboColours.Colours.BindTo(Beatmap.BeatmapSkin.ComboColours); } } } From 6108451449c8b5a56734a28b4fb034226b01ee53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Aug 2021 18:38:01 +0200 Subject: [PATCH 100/366] Retrieve separated skin instance from working beatmap for editing --- .../Beatmaps/Formats/LegacyBeatmapEncoderTest.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs | 2 +- .../Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs | 2 +- osu.Game.Tests/WaveformTestBeatmap.cs | 2 +- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 10 +++++++++- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs | 2 +- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 2 +- osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs | 2 +- osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 +- 14 files changed, 22 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index 059432eeaf..855a75117d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -169,7 +169,7 @@ namespace osu.Game.Tests.Beatmaps.Formats protected override Track GetBeatmapTrack() => throw new NotImplementedException(); - protected override ISkin GetSkin() => throw new NotImplementedException(); + protected internal override ISkin GetSkin() => throw new NotImplementedException(); public override Stream GetStream(string storagePath) => throw new NotImplementedException(); } diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index aed28f5f84..3bf6aaac7a 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -204,7 +204,7 @@ namespace osu.Game.Tests.Gameplay this.resources = resources; } - protected override ISkin GetSkin() => new TestSkin("test-sample", resources); + protected internal override ISkin GetSkin() => new TestSkin("test-sample", resources); } private class TestDrawableStoryboardSample : DrawableStoryboardSample diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs index 13e84e335d..e560c81fb2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs @@ -111,7 +111,7 @@ namespace osu.Game.Tests.Visual.Gameplay this.beatmapSkin = beatmapSkin; } - protected override ISkin GetSkin() => beatmapSkin; + protected internal override ISkin GetSkin() => beatmapSkin; } private class TestOsuRuleset : OsuRuleset diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 5477e4a0f8..9c85fa0c9c 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile)); - protected override ISkin GetSkin() => null; + protected internal override ISkin GetSkin() => null; public override Stream GetStream(string storagePath) => null; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 0d16294c68..4a78ceb299 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -534,7 +534,7 @@ namespace osu.Game.Beatmaps protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; protected override Track GetBeatmapTrack() => null; - protected override ISkin GetSkin() => null; + protected internal override ISkin GetSkin() => null; public override Stream GetStream(string storagePath) => null; } } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index d78ffbbfb6..45112ae74c 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -128,7 +128,7 @@ namespace osu.Game.Beatmaps return storyboard; } - protected override ISkin GetSkin() + protected internal override ISkin GetSkin() { try { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index ea7f45e53f..acfd01a3c8 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -50,7 +50,7 @@ namespace osu.Game.Beatmaps protected override Track GetBeatmapTrack() => GetVirtualTrack(); - protected override ISkin GetSkin() => null; + protected internal override ISkin GetSkin() => null; public override Stream GetStream(string storagePath) => null; diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 662d24cc83..61760e69b0 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -327,7 +327,15 @@ namespace osu.Game.Beatmaps public bool SkinLoaded => skin.IsResultAvailable; public ISkin Skin => skin.Value; - protected abstract ISkin GetSkin(); + /// + /// Creates a new skin instance for this beatmap. + /// + /// + /// This should only be called externally in scenarios where it is explicitly desired to get a new instance of a skin + /// (e.g. for editing purposes, to avoid state pollution). + /// For standard reading purposes, should always be used directly. + /// + protected internal abstract ISkin GetSkin(); private readonly RecyclableLazy skin; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 61a3b0f5cc..e8d919311b 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -153,7 +153,7 @@ namespace osu.Game.Screens.Edit // todo: remove caching of this and consume via editorBeatmap? dependencies.Cache(beatDivisor); - AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, loadableBeatmap.Skin)); + AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, loadableBeatmap.GetSkin())); dependencies.CacheAs(editorBeatmap); changeHandler = new EditorChangeHandler(editorBeatmap); dependencies.CacheAs(changeHandler); diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index 6f92db98ee..d26856365e 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -118,7 +118,7 @@ namespace osu.Game.Screens.Edit protected override Track GetBeatmapTrack() => throw new NotImplementedException(); - protected override ISkin GetSkin() => throw new NotImplementedException(); + protected internal override ISkin GetSkin() => throw new NotImplementedException(); public override Stream GetStream(string storagePath) => throw new NotImplementedException(); } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 4935f7fc13..64f1ee4a7a 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -217,7 +217,7 @@ namespace osu.Game.Tests.Beatmaps protected override Track GetBeatmapTrack() => throw new NotImplementedException(); - protected override ISkin GetSkin() => throw new NotImplementedException(); + protected internal override ISkin GetSkin() => throw new NotImplementedException(); public override Stream GetStream(string storagePath) => throw new NotImplementedException(); diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index 7ee6c519b7..bb5dd09e16 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -211,7 +211,7 @@ namespace osu.Game.Tests.Beatmaps this.resources = resources; } - protected override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resourceStore, resources); + protected internal override ISkin GetSkin() => new LegacyBeatmapSkin(skinBeatmapInfo, resourceStore, resources); } } } diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index 356d2c848c..27162b1d66 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -92,7 +92,7 @@ namespace osu.Game.Tests.Beatmaps HasColours = hasColours; } - protected override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, HasColours); + protected internal override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, HasColours); } protected class TestBeatmapSkin : LegacyBeatmapSkin diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index bfce59c7de..19974701db 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Beatmaps protected override Storyboard GetStoryboard() => storyboard ?? base.GetStoryboard(); - protected override ISkin GetSkin() => null; + protected internal override ISkin GetSkin() => null; public override Stream GetStream(string storagePath) => null; From f6773522d1652a94ea1618a5482e8d668758dfd7 Mon Sep 17 00:00:00 2001 From: Daniel Kariv <38776931+danielkariv@users.noreply.github.com> Date: Mon, 16 Aug 2021 00:12:27 +0300 Subject: [PATCH 101/366] Correct icons in beatmap details In relation to #13968. Replacing incorrect icons in beatmap details panel to correct ones from BeatmapStatisticsIcon class. --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 3f1034759e..21bb75b960 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -78,10 +78,10 @@ namespace osu.Game.Overlays.BeatmapSet Direction = FillDirection.Horizontal, Children = new[] { - length = new Statistic(FontAwesome.Regular.Clock, "Length") { Width = 0.25f }, - bpm = new Statistic(FontAwesome.Regular.Circle, "BPM") { Width = 0.25f }, - circleCount = new Statistic(FontAwesome.Regular.Circle, "Circle Count") { Width = 0.25f }, - sliderCount = new Statistic(FontAwesome.Regular.Circle, "Slider Count") { Width = 0.25f }, + length = new Statistic(BeatmapStatisticsIconType.Length, "Length") { Width = 0.25f }, + bpm = new Statistic(BeatmapStatisticsIconType.Bpm, "BPM") { Width = 0.25f }, + circleCount = new Statistic(BeatmapStatisticsIconType.Circles, "Circle Count") { Width = 0.25f }, + sliderCount = new Statistic(BeatmapStatisticsIconType.Sliders, "Slider Count") { Width = 0.25f }, }, }; } @@ -104,7 +104,7 @@ namespace osu.Game.Overlays.BeatmapSet set => this.value.Text = value; } - public Statistic(IconUsage icon, string name) + public Statistic(BeatmapStatisticsIconType icon, string name) { TooltipText = name; RelativeSizeAxes = Axes.X; @@ -129,11 +129,9 @@ namespace osu.Game.Overlays.BeatmapSet Rotation = 45, Colour = Color4Extensions.FromHex(@"441288"), }, - new SpriteIcon - { + new BeatmapStatisticIcon(icon){ Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, - Icon = icon, Size = new Vector2(12), Colour = Color4Extensions.FromHex(@"f7dd55"), Scale = new Vector2(0.8f), From 38828b6b82976ee3041bce446e9c21b525027ae3 Mon Sep 17 00:00:00 2001 From: Daniel Kariv <38776931+danielkariv@users.noreply.github.com> Date: Mon, 16 Aug 2021 00:40:31 +0300 Subject: [PATCH 102/366] Updating beatmap details icons changes the sizing and add yellow circle so the UI will fit more with osu-web style. --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 21bb75b960..757698e1aa 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -129,10 +129,20 @@ namespace osu.Game.Overlays.BeatmapSet Rotation = 45, Colour = Color4Extensions.FromHex(@"441288"), }, - new BeatmapStatisticIcon(icon){ + new SpriteIcon + { Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, - Size = new Vector2(12), + Icon = FontAwesome.Regular.Circle, + Size = new Vector2(10), + Rotation = 0, + Colour = Color4Extensions.FromHex(@"f7dd55"), + }, + new BeatmapStatisticIcon(icon) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre, + Size = new Vector2(10), Colour = Color4Extensions.FromHex(@"f7dd55"), Scale = new Vector2(0.8f), }, From e744629a4167586e87e41ab1ba6da547b7f5a530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 16 Aug 2021 01:01:56 +0200 Subject: [PATCH 103/366] Fix broken obsoletion message --- osu.Game/Beatmaps/Formats/IHasComboColours.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index 91d960a2fb..853a590595 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -24,7 +24,7 @@ namespace osu.Game.Beatmaps.Formats /// /// Adds combo colours to the list. /// - [Obsolete("Use SkinConfiguration.ComboColours directly.")] // can be removed 20220215 + [Obsolete("Use CustomComboColours directly.")] // can be removed 20220215 void AddComboColours(params Color4[] colours); } } From e8e387b549d1f1caa50b790bf1633ece3d0b1b7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 08:02:23 +0900 Subject: [PATCH 104/366] Cache buffered background to fix multiplayer lounge performance Consider this a request for comment. It's the cleanest solution I can come up with without dropping either the blur, or use of `ModelBackedDrawable`. Intended to resolve https://github.com/ppy/osu/issues/14276. --- .../Components/OnlinePlayBackgroundSprite.cs | 6 +-- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 48 +++++++++++++++---- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs index d8dfac496d..e2ba0b03b0 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs @@ -10,12 +10,12 @@ namespace osu.Game.Screens.OnlinePlay.Components { public class OnlinePlayBackgroundSprite : OnlinePlayComposite { - private readonly BeatmapSetCoverType beatmapSetCoverType; + protected readonly BeatmapSetCoverType BeatmapSetCoverType; private UpdateableBeatmapBackgroundSprite sprite; public OnlinePlayBackgroundSprite(BeatmapSetCoverType beatmapSetCoverType = BeatmapSetCoverType.Cover) { - this.beatmapSetCoverType = beatmapSetCoverType; + BeatmapSetCoverType = beatmapSetCoverType; } [BackgroundDependencyLoader] @@ -33,6 +33,6 @@ namespace osu.Game.Screens.OnlinePlay.Components sprite.Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap.Value; } - protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(beatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; + protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; } } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index c2ad0285b1..72b63ab4d4 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Input; @@ -104,14 +105,9 @@ namespace osu.Game.Screens.OnlinePlay RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new BufferedContainer + new BeatmapBackgroundSprite { - RelativeSizeAxes = Axes.Both, - BlurSigma = new Vector2(10), - Child = new BeatmapBackgroundSprite - { - RelativeSizeAxes = Axes.Both - } + RelativeSizeAxes = Axes.Both }, new Box { @@ -306,11 +302,45 @@ namespace osu.Game.Screens.OnlinePlay private class BeatmapBackgroundSprite : OnlinePlayBackgroundSprite { - protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; + protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BlurredBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; - private class BackgroundSprite : UpdateableBeatmapBackgroundSprite + public class BlurredBackgroundSprite : UpdateableBeatmapBackgroundSprite { + public BlurredBackgroundSprite(BeatmapSetCoverType type) + : base(type) + { + } + protected override double LoadDelay => 200; + + protected override Drawable CreateDrawable(BeatmapInfo model) => + new BufferedLoader(base.CreateDrawable(model)); + } + + // This class is an unfortunate requirement due to `LongRunningLoad` requiring direct async loading. + // It means that if the web request fetching the beatmap background takes too long, it will suddenly appear. + internal class BufferedLoader : BufferedContainer + { + private readonly Drawable drawable; + + public BufferedLoader(Drawable drawable) + { + this.drawable = drawable; + + RelativeSizeAxes = Axes.Both; + BlurSigma = new Vector2(10); + CacheDrawnFrameBuffer = true; + } + + [BackgroundDependencyLoader] + private void load() + { + LoadComponentAsync(drawable, d => + { + Add(d); + ForceRedraw(); + }); + } } } From d35886ef196c032075e68bfcc1913f6469187465 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 11:03:49 +0900 Subject: [PATCH 105/366] Reduce frame buffer render scale for blurred background --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 72b63ab4d4..fd265e9978 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -329,6 +329,7 @@ namespace osu.Game.Screens.OnlinePlay RelativeSizeAxes = Axes.Both; BlurSigma = new Vector2(10); + FrameBufferScale = new Vector2(0.5f); CacheDrawnFrameBuffer = true; } From f0fe79b568724b5151a8b9544438463ee56014a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 11:04:21 +0900 Subject: [PATCH 106/366] Remove buffered container workarounds for now --- .../Lounge/Components/DrawableRoom.cs | 65 +++++++------------ 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 193fb0cf57..c8ecd65574 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -158,21 +158,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Children = new Drawable[] { // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. - new BufferedContainer + new Box { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Background5, - }, - new OnlinePlayBackgroundSprite - { - RelativeSizeAxes = Axes.Both - }, - } + Colour = colours.Background5, + }, + new OnlinePlayBackgroundSprite + { + RelativeSizeAxes = Axes.Both }, new Container { @@ -187,37 +180,29 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components CornerRadius = corner_radius, Children = new Drawable[] { - // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. - new BufferedContainer + new GridContainer { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + ColumnDimensions = new[] { - new GridContainer - { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Relative, 0.2f) - }, - Content = new[] - { - new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Background5, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)) - }, - } - } - }, + new Dimension(GridSizeMode.Relative, 0.2f) }, + Content = new[] + { + new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Background5, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)) + }, + } + } }, new Container { From 76a8d4329fe570a10532d3cb87cd09210523abcf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 12:43:09 +0900 Subject: [PATCH 107/366] Make TestRoomManager update existing room --- osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index 2e9c0d1d53..d7c5a0a0e4 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -38,7 +38,13 @@ namespace osu.Game.Tests.Visual.OnlinePlay public void AddOrUpdateRoom(Room room) { - Rooms.Add(room); + var existing = Rooms.FirstOrDefault(r => r.RoomID.Value != null && r.RoomID.Value == room.RoomID.Value); + + if (existing != null) + existing.CopyFrom(room); + else + Rooms.Add(room); + RoomsUpdated?.Invoke(); } From 3db0b69f9247ae4037a6c6621fa7bcb9b7078f6e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 12:44:12 +0900 Subject: [PATCH 108/366] Throw not implemented exceptions --- .../TestScenePlaylistsMatchSettingsOverlay.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 79af2d3099..98882b659c 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -141,17 +141,11 @@ namespace osu.Game.Tests.Visual.Playlists public IBindableList Rooms => null; - public void AddOrUpdateRoom(Room room) - { - } + public void AddOrUpdateRoom(Room room) => throw new NotImplementedException(); - public void RemoveRoom(Room room) - { - } + public void RemoveRoom(Room room) => throw new NotImplementedException(); - public void ClearRooms() - { - } + public void ClearRooms() => throw new NotImplementedException(); public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { From 9d9974166379c78ab3208c0c3ffbaf94e985e31a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 06:56:59 +0300 Subject: [PATCH 109/366] Add failing test case --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index b7e92a79a0..3017428039 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -12,6 +12,7 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; +using osu.Game.Skinning; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay @@ -142,6 +143,22 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("return value", () => config.SetValue(OsuSetting.KeyOverlay, keyCounterVisibleValue)); } + [Test] + public void TestHiddenHUDDoesntBlockSkinnableComponentsLoad() + { + HUDVisibilityMode originalConfigValue = default; + + AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); + + AddStep("set hud to never show", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + + createNew(); + AddUntilStep("wait for hud load", () => hudOverlay.IsLoaded); + AddUntilStep("skinnable components loaded", () => hudOverlay.ChildrenOfType().Single().ComponentsLoaded); + + AddStep("set original config value", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); + } + private void createNew(Action action = null) { AddStep("create overlay", () => From 554b09ac1b28e36416c929397ffb45fa60337caf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 06:57:45 +0300 Subject: [PATCH 110/366] Fix `SkinnableTargetsContainer` blocked from processing scheduled tasks --- osu.Game/Screens/Play/HUDOverlay.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 2cf2555b3e..13df9fefa7 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -57,8 +57,6 @@ namespace osu.Game.Screens.Play private Bindable configVisibilityMode; - private readonly Container visibilityContainer; - private readonly BindableBool replayLoaded = new BindableBool(); private static bool hasShownNotificationOnce; @@ -72,7 +70,7 @@ namespace osu.Game.Screens.Play private readonly SkinnableTargetContainer mainComponents; - private IEnumerable hideTargets => new Drawable[] { visibilityContainer, KeyCounter, topRightElements }; + private IEnumerable hideTargets => new Drawable[] { mainComponents, KeyCounter, topRightElements }; public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList mods) { @@ -84,13 +82,9 @@ namespace osu.Game.Screens.Play Children = new Drawable[] { CreateFailingLayer(), - visibilityContainer = new Container + mainComponents = new SkinnableTargetContainer(SkinnableTarget.MainHUDComponents) { RelativeSizeAxes = Axes.Both, - Child = mainComponents = new SkinnableTargetContainer(SkinnableTarget.MainHUDComponents) - { - RelativeSizeAxes = Axes.Both, - }, }, topRightElements = new FillFlowContainer { From 81f94424713470101867c541b8e83d4dd719e15d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 13:04:06 +0900 Subject: [PATCH 111/366] Inline update/addRoom in usage sites --- .../OnlinePlay/Components/RoomManager.cs | 43 +++++-------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index ab92adcac7..43bf3a2ce5 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -57,11 +57,10 @@ namespace osu.Game.Screens.OnlinePlay.Components { joinedRoom.Value = room; - update(room, result); - addRoom(room); + AddOrUpdateRoom(result); + room.CopyFrom(result); // Also copy back to the source model, since this is likely to have been stored elsewhere. - RoomsUpdated?.Invoke(); - onSuccess?.Invoke(room); + onSuccess?.Invoke(result); }; req.Failure += exception => @@ -119,8 +118,14 @@ namespace osu.Game.Screens.OnlinePlay.Components try { - update(room, room); - addRoom(room); + foreach (var pi in room.Playlist) + pi.MapObjects(beatmaps, rulesets); + + var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); + if (existing == null) + rooms.Add(room); + else + existing.CopyFrom(room); } catch (Exception ex) { @@ -145,32 +150,6 @@ namespace osu.Game.Screens.OnlinePlay.Components notifyRoomsUpdated(); } - /// - /// Updates a local with a remote copy. - /// - /// The local to update. - /// The remote to update with. - private void update(Room local, Room remote) - { - foreach (var pi in remote.Playlist) - pi.MapObjects(beatmaps, rulesets); - - local.CopyFrom(remote); - } - - /// - /// Adds a to the list of available rooms. - /// - /// The to add. - private void addRoom(Room room) - { - var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); - if (existing == null) - rooms.Add(room); - else - existing.CopyFrom(room); - } - private void notifyRoomsUpdated() => Scheduler.AddOnce(() => RoomsUpdated?.Invoke()); } } From b6a2020c59ebd7667d821277fcc25493f07ff4e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 13:09:04 +0900 Subject: [PATCH 112/366] General refactorings from PR review --- .../Components/ListingPollingComponent.cs | 8 ++++---- .../Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 15 ++++++++------- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 12 ++++++------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index f686326d08..bc6480d05e 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -15,8 +15,8 @@ namespace osu.Game.Screens.OnlinePlay.Components /// public class ListingPollingComponent : RoomPollingComponent { - public IBindable HasPolledOnce => hasPolledOnce; - private readonly Bindable hasPolledOnce = new Bindable(); + public IBindable InitialRoomsReceived => initialRoomsReceived; + private readonly Bindable initialRoomsReceived = new Bindable(); [Resolved] private Bindable currentFilter { get; set; } @@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Components currentFilter.BindValueChanged(_ => { RoomManager.ClearRooms(); - hasPolledOnce.Value = false; + initialRoomsReceived.Value = false; if (IsLoaded) PollImmediately(); @@ -60,7 +60,7 @@ namespace osu.Game.Screens.OnlinePlay.Components foreach (var incoming in result) RoomManager.AddOrUpdateRoom(incoming); - hasPolledOnce.Value = true; + initialRoomsReceived.Value = true; tcs.SetResult(true); }; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 4e3f37f814..bd2648791c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -45,6 +45,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge AutoSizeAxes = Axes.Both }; + protected ListingPollingComponent ListingPollingComponent { get; private set; } + [Resolved] private Bindable selectedRoom { get; set; } @@ -72,7 +74,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private RoomsContainer roomsContainer; private SearchTextBox searchTextBox; private Dropdown statusDropdown; - private ListingPollingComponent listingPollingComponent; [BackgroundDependencyLoader(true)] private void load([CanBeNull] IdleTracker idleTracker) @@ -86,7 +87,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { - listingPollingComponent = CreatePollingComponent(), + ListingPollingComponent = CreatePollingComponent(), loadingLayer = new LoadingLayer(true), new Container { @@ -186,7 +187,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - listingPollingComponent.HasPolledOnce.BindValueChanged(_ => updateLoadingLayer()); + ListingPollingComponent.InitialRoomsReceived.BindValueChanged(_ => updateLoadingLayer()); isIdle.BindValueChanged(_ => updatePollingRate(this.IsCurrentScreen()), true); @@ -337,7 +338,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void updateLoadingLayer() { - if (operationInProgress.Value || !listingPollingComponent.HasPolledOnce.Value) + if (operationInProgress.Value || !ListingPollingComponent.InitialRoomsReceived.Value) loadingLayer.Show(); else loadingLayer.Hide(); @@ -346,11 +347,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void updatePollingRate(bool isCurrentScreen) { if (!isCurrentScreen) - listingPollingComponent.TimeBetweenPolls.Value = 0; + ListingPollingComponent.TimeBetweenPolls.Value = 0; else - listingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; + ListingPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 120000 : 15000; - Logger.Log($"Polling adjusted (listing: {listingPollingComponent.TimeBetweenPolls.Value})"); + Logger.Log($"Polling adjusted (listing: {ListingPollingComponent.TimeBetweenPolls.Value})"); } protected abstract OsuButton CreateNewRoomButton(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 77db955f0a..97fed2040d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } - private MultiplayerListingPollingComponent listingPollingComponent; + private MultiplayerListingPollingComponent multiplayerListingPollingComponent => (MultiplayerListingPollingComponent)ListingPollingComponent; private readonly IBindable isConnected = new Bindable(); @@ -34,8 +34,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.LoadComplete(); isConnected.BindTo(client.IsConnected); - isConnected.BindValueChanged(c => Scheduler.AddOnce(() => listingPollingComponent.AllowPolling = c.NewValue)); - listingPollingComponent.AllowPolling = isConnected.Value; + isConnected.BindValueChanged(c => Scheduler.AddOnce(() => multiplayerListingPollingComponent.AllowPolling = c.NewValue)); + multiplayerListingPollingComponent.AllowPolling = isConnected.Value; } public override void OnResuming(IScreen last) @@ -47,7 +47,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (last is MultiplayerMatchSubScreen match) { RoomManager.RemoveRoom(match.Room); - listingPollingComponent.PollImmediately(); + multiplayerListingPollingComponent.PollImmediately(); } } @@ -69,7 +69,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room); - protected override ListingPollingComponent CreatePollingComponent() => listingPollingComponent = new MultiplayerListingPollingComponent(); + protected override ListingPollingComponent CreatePollingComponent() => new MultiplayerListingPollingComponent(); protected override void OpenNewRoom(Room room) { @@ -104,7 +104,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } - protected override Task Poll() => !AllowPolling ? Task.CompletedTask : base.Poll(); + protected override Task Poll() => AllowPolling ? base.Poll() : Task.CompletedTask; } } } From 53c3eccfb50bfc6bd3238fa84e2c371a83b4a388 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 07:21:37 +0300 Subject: [PATCH 113/366] Force HUD visibility mode to "Always" during testing --- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 9bb9c24c6b..18e4a6c575 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Rulesets.UI; @@ -26,6 +27,9 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private OsuGameBase game { get; set; } + [Resolved] + private OsuConfigManager config { get; set; } + [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -86,6 +90,11 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestSpectatorPlayerInteractiveElementsHidden() { + HUDVisibilityMode originalConfigValue = default; + + AddStep("get original config hud visibility", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); + AddStep("set config hud visibility to always", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always)); + start(new[] { PLAYER_1_ID, PLAYER_2_ID }); loadSpectateScreen(false); @@ -100,6 +109,8 @@ namespace osu.Game.Tests.Visual.Multiplayer !p.ChildrenOfType().Any() && !p.ChildrenOfType().Any() && p.ChildrenOfType().SingleOrDefault()?.ShowHandle == false)); + + AddStep("restore config hud visibility", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); } [Test] From f82ed64aa7afc735f7092b96810c66eb45222b9d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 09:06:56 +0300 Subject: [PATCH 114/366] Fix participant panel null user test no longer functioning properly I guess the changes that involved `MultiplayerTestScene` having a test user lookup cache caused this test case to false-pass silently. Added an explicit assert which ensures the added user indeed has a null `User` value. --- .../TestSceneMultiplayerParticipantsList.cs | 4 +++- .../Multiplayer/TestMultiplayerClient.cs | 2 +- osu.Game/Tests/Visual/TestUserLookupCache.cs | 20 +++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index a3e6c8de3b..a44ce87738 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; @@ -48,7 +49,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddAssert("one unique panel", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 1); - AddStep("add non-resolvable user", () => Client.AddNullUser(-3)); + AddStep("add non-resolvable user", () => Client.AddNullUser()); + AddAssert("null user added", () => Client.Room.AsNonNull().Users.Count(u => u.User == null) == 1); AddUntilStep("two unique panels", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 2); } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 67b79d7390..f2da66d666 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tests.Visual.Multiplayer return roomUser; } - public void AddNullUser(int userId) => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(userId)); + public void AddNullUser() => ((IMultiplayerClient)this).UserJoined(new MultiplayerRoomUser(TestUserLookupCache.NULL_USER_ID)); public void RemoveUser(User user) { diff --git a/osu.Game/Tests/Visual/TestUserLookupCache.cs b/osu.Game/Tests/Visual/TestUserLookupCache.cs index d2941b5bd5..b73e81d0dd 100644 --- a/osu.Game/Tests/Visual/TestUserLookupCache.cs +++ b/osu.Game/Tests/Visual/TestUserLookupCache.cs @@ -10,10 +10,22 @@ namespace osu.Game.Tests.Visual { public class TestUserLookupCache : UserLookupCache { - protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) => Task.FromResult(new User + /// + /// A special user ID which would return a for. + /// As a simulation to what a regular would return in the case of failing to fetch the user. + /// + public const int NULL_USER_ID = -1; + + protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) { - Id = lookup, - Username = $"User {lookup}" - }); + if (lookup == NULL_USER_ID) + return Task.FromResult((User)null); + + return Task.FromResult(new User + { + Id = lookup, + Username = $"User {lookup}" + }); + } } } From 67bac207cfce01649c201721cfca1d595a388ff8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 09:37:29 +0300 Subject: [PATCH 115/366] Cover kicking a multiplayer room user with null `User` --- .../Multiplayer/TestSceneMultiplayerParticipantsList.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index a44ce87738..c4ebc13245 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -53,6 +53,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("null user added", () => Client.Room.AsNonNull().Users.Count(u => u.User == null) == 1); AddUntilStep("two unique panels", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 2); + + AddStep("kick null user", () => this.ChildrenOfType().Single(p => p.User.User == null) + .ChildrenOfType().Single().TriggerClick()); + + AddAssert("null user kicked", () => Client.Room.AsNonNull().Users.Count == 1); } [Test] From 79cd06278426fbc73c7f90f044e25a2047bed488 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 09:26:00 +0300 Subject: [PATCH 116/366] Let `TeamDisplay` take the full `MultiplayerRoomUser` rather than the underlying `User` --- .../Participants/ParticipantPanel.cs | 2 +- .../Multiplayer/Participants/TeamDisplay.cs | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index 1787480e1f..c4b4dbb777 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -83,7 +83,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants Colour = Color4Extensions.FromHex("#F7E65D"), Alpha = 0 }, - new TeamDisplay(user), + new TeamDisplay(User), new Container { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs index 5a7073f9de..351b9b3673 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs @@ -11,7 +11,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; -using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -19,16 +18,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { internal class TeamDisplay : MultiplayerRoomComposite { - private readonly User user; + private readonly MultiplayerRoomUser user; + private Drawable box; [Resolved] private OsuColour colours { get; set; } - [Resolved] - private MultiplayerClient client { get; set; } - - public TeamDisplay(User user) + public TeamDisplay(MultiplayerRoomUser user) { this.user = user; @@ -61,7 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants } }; - if (user.Id == client.LocalUser?.UserID) + if (Client.LocalUser?.Equals(user) == true) { InternalChild = new OsuClickableContainer { @@ -79,9 +76,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants private void changeTeam() { - client.SendMatchRequest(new ChangeTeamRequest + Client.SendMatchRequest(new ChangeTeamRequest { - TeamID = ((client.LocalUser?.MatchState as TeamVersusUserState)?.TeamID + 1) % 2 ?? 0, + TeamID = ((Client.LocalUser?.MatchState as TeamVersusUserState)?.TeamID + 1) % 2 ?? 0, }); } @@ -93,7 +90,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants // we don't have a way of knowing when an individual user's state has updated, so just handle on RoomUpdated for now. - var userRoomState = Room?.Users.FirstOrDefault(u => u.UserID == user.Id)?.MatchState; + var userRoomState = Room?.Users.FirstOrDefault(u => u.Equals(user))?.MatchState; const double duration = 400; From 7fe6f6dd149c97a6c0a6bae80ecdcac66691543d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 09:26:45 +0300 Subject: [PATCH 117/366] Fix kick button action asserting and using `User.User.ID` rather than `User.UserID` --- .../Multiplayer/Participants/ParticipantPanel.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index c4b4dbb777..6f8c735b6e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -168,12 +167,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants Origin = Anchor.Centre, Alpha = 0, Margin = new MarginPadding(4), - Action = () => - { - Debug.Assert(user != null); - - Client.KickUser(user.Id); - } + Action = () => Client.KickUser(User.UserID), }, }, } From 81480ac4fc5ea2e14b7790284e8eec3528329bd5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:16:02 +0900 Subject: [PATCH 118/366] Use `PlayerConfiguration` to convey no-seek state --- .../Multiplayer/Spectate/MultiSpectatorPlayer.cs | 4 +--- osu.Game/Screens/Play/Player.cs | 8 ++++---- osu.Game/Screens/Play/PlayerConfiguration.cs | 5 +++++ osu.Game/Screens/Play/SpectatorPlayer.cs | 3 ++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 1b1dee5ae2..feb1af770b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// The score containing the player's replay. /// The clock controlling the gameplay running state. public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock) - : base(score) + : base(score, new PlayerConfiguration { AllowSeeking = false }) { this.spectatorPlayerClock = spectatorPlayerClock; } @@ -35,8 +35,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { spectatorPlayerClock.WaitingOnFrames.BindTo(waitingOnFrames); - AllowUserSeekingState.Value = false; - AllowUserSeekingState.Disabled = true; HUDOverlay.PlayerSettingsOverlay.Expire(); HUDOverlay.HoldToQuit.Expire(); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index dc37464a61..73bf3f9bda 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -77,9 +77,9 @@ namespace osu.Game.Screens.Play protected readonly Bindable LocalUserPlaying = new Bindable(); - protected readonly Bindable AllowUserSeekingState = new Bindable(); + private readonly Bindable allowUserSeeking = new Bindable(); - public IBindable AllowUserSeeking => AllowUserSeekingState; + public IBindable AllowUserSeeking => allowUserSeeking; public int RestartCount; @@ -275,8 +275,8 @@ namespace osu.Game.Screens.Play DrawableRuleset.HasReplayLoaded.BindValueChanged(r => { - if (!AllowUserSeekingState.Disabled) - AllowUserSeekingState.Value = r.NewValue; + if (Configuration.AllowSeeking) + allowUserSeeking.Value = r.NewValue; updateGameplayState(); }); diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index 18ee73374f..39c7a7568e 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -20,6 +20,11 @@ namespace osu.Game.Screens.Play /// public bool AllowRestart { get; set; } = true; + /// + /// Whether the player should be allowed to seek in a displayed replay. + /// + public bool AllowSeeking { get; set; } = true; + /// /// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard. /// diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index f662a479ec..1dae28092a 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -23,7 +23,8 @@ namespace osu.Game.Screens.Play protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap - public SpectatorPlayer(Score score) + public SpectatorPlayer(Score score, PlayerConfiguration configuration = null) + : base(configuration) { this.score = score; } From 838bcc51b2922f6403a8e459aafe8d8ecde41a4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:27:19 +0900 Subject: [PATCH 119/366] Avoid new bindable requirement --- osu.Game/Screens/Play/Player.cs | 20 ++++++++------------ osu.Game/Screens/Play/SongProgress.cs | 3 ++- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 73bf3f9bda..c43b701ebf 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -77,10 +77,6 @@ namespace osu.Game.Screens.Play protected readonly Bindable LocalUserPlaying = new Bindable(); - private readonly Bindable allowUserSeeking = new Bindable(); - - public IBindable AllowUserSeeking => allowUserSeeking; - public int RestartCount; [Resolved] @@ -273,13 +269,7 @@ namespace osu.Game.Screens.Play DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState()); - DrawableRuleset.HasReplayLoaded.BindValueChanged(r => - { - if (Configuration.AllowSeeking) - allowUserSeeking.Value = r.NewValue; - - updateGameplayState(); - }); + DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); @@ -592,7 +582,13 @@ namespace osu.Game.Screens.Play /// Seek to a specific time in gameplay. /// /// The destination time to seek to. - public void Seek(double time) => GameplayClockContainer.Seek(time); + public void Seek(double time) + { + if (!Configuration.AllowSeeking) + throw new InvalidOperationException($"Seeking has ben disabled by the current {nameof(Configuration)}."); + + GameplayClockContainer.Seek(time); + } private ScheduledDelegate frameStablePlaybackResetDelegate; diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 8debe6243d..3e30cf17b3 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -119,7 +119,8 @@ namespace osu.Game.Screens.Play if (drawableRuleset != null) { - ((IBindable)AllowSeeking).BindTo(player.AllowUserSeeking); + if (player?.Configuration.AllowSeeking == true) + ((IBindable)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded); referenceClock = drawableRuleset.FrameStableClock; Objects = drawableRuleset.Objects; From ae8a1adae838648807431fec10b41826abbd9849 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:47:57 +0900 Subject: [PATCH 120/366] Allow seeking via `Player.Seek` even if disabled --- osu.Game/Screens/Play/Player.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c43b701ebf..09eaf1c543 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -582,13 +582,7 @@ namespace osu.Game.Screens.Play /// Seek to a specific time in gameplay. /// /// The destination time to seek to. - public void Seek(double time) - { - if (!Configuration.AllowSeeking) - throw new InvalidOperationException($"Seeking has ben disabled by the current {nameof(Configuration)}."); - - GameplayClockContainer.Seek(time); - } + public void Seek(double time) => GameplayClockContainer.Seek(time); private ScheduledDelegate frameStablePlaybackResetDelegate; From 8d45f86bd3ded0bb0b7c901c3fb30e1b1f7fff93 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:48:40 +0900 Subject: [PATCH 121/366] Rename variable to better reflect its purpose --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs | 2 +- osu.Game/Screens/Play/PlayerConfiguration.cs | 4 ++-- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index feb1af770b..ececa1e497 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// The score containing the player's replay. /// The clock controlling the gameplay running state. public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock) - : base(score, new PlayerConfiguration { AllowSeeking = false }) + : base(score, new PlayerConfiguration { AllowUserInteraction = false }) { this.spectatorPlayerClock = spectatorPlayerClock; } diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index 39c7a7568e..3aa424e5d5 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -21,9 +21,9 @@ namespace osu.Game.Screens.Play public bool AllowRestart { get; set; } = true; /// - /// Whether the player should be allowed to seek in a displayed replay. + /// Whether the player should be able to interact with this player instance. /// - public bool AllowSeeking { get; set; } = true; + public bool AllowUserInteraction { get; set; } = true; /// /// Whether the player should be allowed to skip intros/outros, advancing to the start of gameplay or the end of a storyboard. diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 3e30cf17b3..b27a9c5f5d 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Play if (drawableRuleset != null) { - if (player?.Configuration.AllowSeeking == true) + if (player?.Configuration.AllowUserInteraction == true) ((IBindable)AllowSeeking).BindTo(drawableRuleset.HasReplayLoaded); referenceClock = drawableRuleset.FrameStableClock; From fc89f2bac4a3971835beeeb104a10026dfb13782 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:56:48 +0900 Subject: [PATCH 122/366] Revert "Rename element in OsuSettings enum" This reverts commit c2bbe175627ce35f1d63bc7c627b35b4883de5a0. --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- osu.Game/Screens/Play/SongProgress.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6c7adcc806..60a0d5a0ac 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -101,7 +101,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.HitLighting, true); SetDefault(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always); - SetDefault(OsuSetting.ShowDifficultyGraph, true); + SetDefault(OsuSetting.ShowProgressGraph, true); SetDefault(OsuSetting.ShowHealthDisplayWhenCantFail, true); SetDefault(OsuSetting.FadePlayfieldWhenHealthLow, true); SetDefault(OsuSetting.KeyOverlay, false); @@ -217,7 +217,7 @@ namespace osu.Game.Configuration AlwaysPlayFirstComboBreak, FloatingComments, HUDVisibilityMode, - ShowDifficultyGraph, + ShowProgressGraph, ShowHealthDisplayWhenCantFail, FadePlayfieldWhenHealthLow, MouseDisableButtons, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 69aa57082a..353292606f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsCheckbox { LabelText = "Show difficulty graph on progress bar", - Current = config.GetBindable(OsuSetting.ShowDifficultyGraph) + Current = config.GetBindable(OsuSetting.ShowProgressGraph) }, new SettingsCheckbox { diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 6aa7e017ce..f28622f42e 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -125,7 +125,7 @@ namespace osu.Game.Screens.Play Objects = drawableRuleset.Objects; } - config.BindWith(OsuSetting.ShowDifficultyGraph, ShowGraph); + config.BindWith(OsuSetting.ShowProgressGraph, ShowGraph); graph.FillColour = bar.FillColour = colours.BlueLighter; } From 71fab416d8902bbf6b1657de800773e0f78fa2bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 16:59:59 +0900 Subject: [PATCH 123/366] Add a note against `OsuSetting` --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 60a0d5a0ac..9b0d7f51da 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -201,6 +201,8 @@ namespace osu.Game.Configuration public Func LookupKeyBindings { get; set; } } + // IMPORTANT: These are used in user configuration files. + // The naming of these keys should not be changed once they are deployed in a release, unless migration logic is also added. public enum OsuSetting { Ruleset, From 1c7cbc862156659d31651b3cfb748d4490e6ac6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 17:14:13 +0900 Subject: [PATCH 124/366] Add missing `readonly` keyword to new bindable --- osu.Game/Screens/Edit/EditorBeatmapSkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs index 6745f08b80..429df85904 100644 --- a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs +++ b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit /// The combo colours of this skin. /// If empty, the default combo colours will be used. /// - public BindableList ComboColours; + public readonly BindableList ComboColours; private readonly Skin skin; From db1a0ebb55448903587ce59bbdf99c5ed90744a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 16 Aug 2021 18:46:44 +0900 Subject: [PATCH 125/366] Fix preview track crashes --- .../BeatmapListing/Panels/PlayButton.cs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs b/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs index 4bbc3569fe..3aa9aa5ca5 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/PlayButton.cs @@ -139,19 +139,24 @@ namespace osu.Game.Overlays.BeatmapListing.Panels LoadComponentAsync(Preview = previewTrackManager.Get(beatmapSet), preview => { - // beatmapset may have changed. - if (Preview != preview) - return; + // Make sure that we schedule to after the next audio frame to fix crashes in single-threaded execution. + // See: https://github.com/ppy/osu-framework/issues/4692 + Schedule(() => + { + // beatmapset may have changed. + if (Preview != preview) + return; - AddInternal(preview); - loading = false; - // make sure that the update of value of Playing (and the ensuing value change callbacks) - // are marshaled back to the update thread. - preview.Stopped += () => Schedule(() => playing.Value = false); + AddInternal(preview); + loading = false; + // make sure that the update of value of Playing (and the ensuing value change callbacks) + // are marshaled back to the update thread. + preview.Stopped += () => Schedule(() => playing.Value = false); - // user may have changed their mind. - if (playing.Value) - attemptStart(); + // user may have changed their mind. + if (playing.Value) + attemptStart(); + }); }); } else From 855fff1486477eb490ed851a33a26be57b96c095 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 12:47:56 +0300 Subject: [PATCH 126/366] Fix `DifficultyAdjustSettingsControl.SliderControl` not following up with the current pattern This was causing any `ValueChanged` event bind (such as the one in `SettingsItem` to invoke `SettingsChanged`) to be overwritten when `Current` is set afterwards. --- osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs index 067657159b..186514e868 100644 --- a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs +++ b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs @@ -91,7 +91,13 @@ namespace osu.Game.Rulesets.Mods { // This is required as SettingsItem relies heavily on this bindable for internal use. // The actual update flow is done via the bindable provided in the constructor. - public Bindable Current { get; set; } = new Bindable(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } public SliderControl(BindableNumber currentNumber) { From 6653a78e659774213635568d5fd2bdcc7d693170 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 12:48:49 +0300 Subject: [PATCH 127/366] Add test coverage --- .../TestSceneModDifficultyAdjustSettings.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs index e0d76b3e4a..f8652573f4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.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.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -174,6 +176,60 @@ namespace osu.Game.Tests.Visual.UserInterface checkBindableAtValue("Circle Size", null); } + [Test] + public void TestModSettingChangeTracker() + { + ModSettingChangeTracker tracker = null; + Queue settingsChangedQueue = null; + + setBeatmapWithDifficultyParameters(5); + + AddStep("add mod settings change tracker", () => + { + settingsChangedQueue = new Queue(); + + tracker = new ModSettingChangeTracker(modDifficultyAdjust.Yield()) + { + SettingChanged = settingsChangedQueue.Enqueue + }; + }); + + AddAssert("no settings changed", () => settingsChangedQueue.Count == 0); + + setSliderValue("Circle Size", 3); + + settingsChangedFired(); + + setSliderValue("Circle Size", 5); + checkBindableAtValue("Circle Size", 5); + + settingsChangedFired(); + + AddStep("reset mod settings", () => modDifficultyAdjust.CircleSize.SetDefault()); + checkBindableAtValue("Circle Size", null); + + settingsChangedFired(); + + setExtendedLimits(true); + + settingsChangedFired(); + + AddStep("dispose tracker", () => + { + tracker.Dispose(); + tracker = null; + }); + + void settingsChangedFired() + { + AddAssert("setting changed event fired", () => + { + settingsChangedQueue.Dequeue(); + return settingsChangedQueue.Count == 0; + }); + } + } + private void resetToDefault(string name) { AddStep($"Reset {name} to default", () => From c191b3812529e9fdd0f47488fd22e21e6398ff9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 18:40:34 +0900 Subject: [PATCH 128/366] Reduce transform overhead of `RestoreDefaultValueButton` --- osu.Game/Overlays/RestoreDefaultValueButton.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/RestoreDefaultValueButton.cs b/osu.Game/Overlays/RestoreDefaultValueButton.cs index fd3ee16fe6..62f5222012 100644 --- a/osu.Game/Overlays/RestoreDefaultValueButton.cs +++ b/osu.Game/Overlays/RestoreDefaultValueButton.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; @@ -38,7 +39,9 @@ namespace osu.Game.Overlays current.ValueChanged += _ => UpdateState(); current.DefaultChanged += _ => UpdateState(); current.DisabledChanged += _ => UpdateState(); - UpdateState(); + + if (IsLoaded) + UpdateState(); } } @@ -81,7 +84,10 @@ namespace osu.Game.Overlays protected override void LoadComplete() { base.LoadComplete(); - UpdateState(); + + // avoid unnecessary transforms on first display. + Alpha = currentAlpha; + Colour = currentColour; } public LocalisableString TooltipText => "revert to default"; @@ -101,14 +107,16 @@ namespace osu.Game.Overlays public void UpdateState() => Scheduler.AddOnce(updateState); + private float currentAlpha => current.IsDefault ? 0f : hovering && !current.Disabled ? 1f : 0.65f; + private ColourInfo currentColour => current.Disabled ? Color4.Gray : buttonColour; + private void updateState() { if (current == null) return; - this.FadeTo(current.IsDefault ? 0f : - hovering && !current.Disabled ? 1f : 0.65f, 200, Easing.OutQuint); - this.FadeColour(current.Disabled ? Color4.Gray : buttonColour, 200, Easing.OutQuint); + this.FadeTo(currentAlpha, 200, Easing.OutQuint); + this.FadeColour(currentColour, 200, Easing.OutQuint); } } } From 4b975ca10d34211f6555ff0e98b49c99f23981cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 18:43:02 +0900 Subject: [PATCH 129/366] Add better test coverage of `SettingsPanel` --- .../Visual/Settings/TestSceneSettingsPanel.cs | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs index 115d2fec7d..0af77b3b5a 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Settings @@ -11,27 +12,39 @@ namespace osu.Game.Tests.Visual.Settings [TestFixture] public class TestSceneSettingsPanel : OsuTestScene { - private readonly SettingsPanel settings; - private readonly DialogOverlay dialogOverlay; + private SettingsPanel settings; + private DialogOverlay dialogOverlay; - public TestSceneSettingsPanel() + [SetUpSteps] + public void SetUpSteps() { - settings = new SettingsOverlay + AddStep("create settings", () => { - State = { Value = Visibility.Visible } - }; - Add(dialogOverlay = new DialogOverlay - { - Depth = -1 + settings?.Expire(); + + Add(settings = new SettingsOverlay + { + State = { Value = Visibility.Visible } + }); }); } + [Test] + public void ToggleVisibility() + { + AddWaitStep("wait some", 5); + AddToggleStep("toggle editor visibility", visible => settings.ToggleVisibility()); + } + [BackgroundDependencyLoader] private void load() { - Dependencies.Cache(dialogOverlay); + Add(dialogOverlay = new DialogOverlay + { + Depth = -1 + }); - Add(settings); + Dependencies.Cache(dialogOverlay); } } } From cecb312e7703e1ebacf023a13db78159607b9407 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 18:44:00 +0900 Subject: [PATCH 130/366] Ensure `TakeFocus` does not crash when not yet loaded --- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index f77a3109c9..4a42027964 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -22,7 +22,10 @@ namespace osu.Game.Graphics.UserInterface public void TakeFocus() { - if (allowImmediateFocus) GetContainingInputManager().ChangeFocus(this); + if (!allowImmediateFocus) + return; + + Schedule(() => GetContainingInputManager().ChangeFocus(this)); } public bool HoldFocus From e39a295c5c417ec6d71ded0f07b1029849436c89 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 16 Aug 2021 13:45:50 +0300 Subject: [PATCH 131/366] Hide tablet settings content when input handler is disabled --- .../Settings/Sections/Input/TabletSettings.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index c561b693d8..8303fee3ef 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -22,6 +22,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input { private readonly ITabletHandler tabletHandler; + private readonly Bindable enabled = new BindableBool(true); + private readonly Bindable areaOffset = new Bindable(); private readonly Bindable areaSize = new Bindable(); private readonly IBindable tablet = new Bindable(); @@ -74,7 +76,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input LabelText = CommonStrings.Enabled, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Current = tabletHandler.Enabled + Current = enabled, }, noTabletMessage = new FillFlowContainer { @@ -194,6 +196,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input { base.LoadComplete(); + enabled.BindTo(tabletHandler.Enabled); + enabled.BindValueChanged(_ => Scheduler.AddOnce(updateVisibility)); + rotation.BindTo(tabletHandler.Rotation); areaOffset.BindTo(tabletHandler.AreaOffset); @@ -239,7 +244,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input tablet.BindTo(tabletHandler.Tablet); tablet.BindValueChanged(val => { - Scheduler.AddOnce(toggleVisibility); + Scheduler.AddOnce(updateVisibility); var tab = val.NewValue; @@ -259,8 +264,15 @@ namespace osu.Game.Overlays.Settings.Sections.Input }, true); } - private void toggleVisibility() + private void updateVisibility() { + if (!tabletHandler.Enabled.Value) + { + mainSettings.Hide(); + noTabletMessage.Hide(); + return; + } + bool tabletFound = tablet.Value != null; if (!tabletFound) From 7bebbf9f7400e068b1378e0b6b7eec0711c8d14f Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 16 Aug 2021 12:46:41 +0200 Subject: [PATCH 132/366] Mark format strings as verbatim. --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 4 ++-- osu.Game/Overlays/BeatmapSet/SuccessRate.cs | 2 +- osu.Game/Screens/Select/Details/UserRatings.cs | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index ce348bd753..ed7676aa21 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -67,8 +67,8 @@ namespace osu.Game.Overlays.BeatmapSet length.TooltipText = BeatmapsetsStrings.ShowStatsTotalLength(TimeSpan.FromMilliseconds(beatmap.Length).ToFormattedDuration()); length.Value = TimeSpan.FromMilliseconds(beatmap.Length).ToFormattedDuration(); - circleCount.Value = beatmap.OnlineInfo.CircleCount.ToLocalisableString("N0"); - sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToLocalisableString("N0"); + circleCount.Value = beatmap.OnlineInfo.CircleCount.ToLocalisableString(@"N0"); + sliderCount.Value = beatmap.OnlineInfo.SliderCount.ToLocalisableString(@"N0"); } } diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index d370e57f14..b1e9abe3aa 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -44,7 +44,7 @@ namespace osu.Game.Overlays.BeatmapSet int playCount = beatmap?.OnlineInfo?.PlayCount ?? 0; var rate = playCount != 0 ? (float)passCount / playCount : 0; - successPercent.Text = rate.ToLocalisableString("0.#%"); + successPercent.Text = rate.ToLocalisableString(@"0.#%"); successRate.Length = rate; percentContainer.ResizeWidthTo(successRate.Length, 250, Easing.InOutCubic); diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index a45bcd0666..a7f28b932a 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -37,8 +37,8 @@ namespace osu.Game.Screens.Select.Details if (metrics == null) { - negativeRatings.Text = 0.ToLocalisableString("N0"); - positiveRatings.Text = 0.ToLocalisableString("N0"); + negativeRatings.Text = 0.ToLocalisableString(@"N0"); + positiveRatings.Text = 0.ToLocalisableString(@"N0"); ratingsBar.Length = 0; graph.Values = new float[rating_range]; } @@ -49,8 +49,8 @@ namespace osu.Game.Screens.Select.Details var negativeCount = ratings.Take(rating_range / 2).Sum(); var totalCount = ratings.Sum(); - negativeRatings.Text = negativeCount.ToLocalisableString("N0"); - positiveRatings.Text = (totalCount - negativeCount).ToLocalisableString("N0"); + negativeRatings.Text = negativeCount.ToLocalisableString(@"N0"); + positiveRatings.Text = (totalCount - negativeCount).ToLocalisableString(@"N0"); ratingsBar.Length = totalCount == 0 ? 0 : (float)negativeCount / totalCount; graph.Values = ratings.Take(rating_range).Select(r => (float)r); } @@ -90,14 +90,14 @@ namespace osu.Game.Screens.Select.Details { negativeRatings = new OsuSpriteText { - Text = 0.ToLocalisableString("N0"), + Text = 0.ToLocalisableString(@"N0"), Font = OsuFont.GetFont(size: 12) }, positiveRatings = new OsuSpriteText { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - Text = 0.ToLocalisableString("N0"), + Text = 0.ToLocalisableString(@"N0"), Font = OsuFont.GetFont(size: 12) }, }, From c0130da2359ad8947eebdf1a2743cbc2e31e5765 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 18:44:12 +0900 Subject: [PATCH 133/366] Avoid running initial layout transform in `LayoutSettings` --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 91208cb78a..277e344d84 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -97,8 +97,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - AutoSizeDuration = transition_duration, - AutoSizeEasing = Easing.OutQuint, Masking = true, Children = new[] { @@ -177,6 +175,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingMode.BindValueChanged(mode => { scalingSettings.ClearTransforms(); + + scalingSettings.AutoSizeDuration = transition_duration; + scalingSettings.AutoSizeEasing = Easing.OutQuint; scalingSettings.AutoSizeAxes = mode.NewValue != ScalingMode.Off ? Axes.Y : Axes.None; if (mode.NewValue == ScalingMode.Off) From 92ad66c86c857b7854064c6d6e87b6b107d472ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 18:56:02 +0900 Subject: [PATCH 134/366] Remove transform overhead from `OsuDropdown` on initial display --- osu.Game/Graphics/UserInterface/OsuDropdown.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index 61dd5fb2d9..42f628a75a 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -69,6 +69,7 @@ namespace osu.Game.Graphics.UserInterface BackgroundColour = Color4.Black.Opacity(0.5f); MaskingContainer.CornerRadius = corner_radius; + Alpha = 0; // todo: this uses the same styling as OsuMenu. hopefully we can just use OsuMenu in the future with some refactoring ItemsContainer.Padding = new MarginPadding(5); @@ -94,9 +95,11 @@ namespace osu.Game.Graphics.UserInterface protected override void AnimateClose() { - this.FadeOut(300, Easing.OutQuint); if (wasOpened) + { + this.FadeOut(300, Easing.OutQuint); sampleClose?.Play(); + } } // todo: this uses the same styling as OsuMenu. hopefully we can just use OsuMenu in the future with some refactoring From 237d3e656b72b2827e04a5228dae4064926a86e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 18:58:26 +0900 Subject: [PATCH 135/366] Remove initial transform overhead of `Nub` --- osu.Game/Graphics/UserInterface/Nub.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 8d686e8c2f..cbf3e6b3aa 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -6,6 +6,7 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; @@ -57,18 +58,13 @@ namespace osu.Game.Graphics.UserInterface EdgeEffect = new EdgeEffectParameters { - Colour = GlowColour, + Colour = GlowColour.Opacity(0), Type = EdgeEffectType.Glow, Radius = 10, Roundness = 8, }; } - protected override void LoadComplete() - { - FadeEdgeEffectTo(0); - } - private bool glowing; public bool Glowing From 8d051d9fa0d6c692bc740ec155d0a1bf1914cc7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 19:16:48 +0900 Subject: [PATCH 136/366] Avoid multiple synchronous overheads in `SettingsItem` --- osu.Game/Overlays/Settings/SettingsItem.cs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index ef2027fdab..c35690151c 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -93,15 +93,13 @@ namespace osu.Game.Overlays.Settings public bool MatchingFilter { - set => this.FadeTo(value ? 1 : 0); + set => Alpha = value ? 1 : 0; } public bool FilteringActive { get; set; } public event Action SettingChanged; - private readonly RestoreDefaultValueButton restoreDefaultButton; - protected SettingsItem() { RelativeSizeAxes = Axes.X; @@ -110,7 +108,6 @@ namespace osu.Game.Overlays.Settings InternalChildren = new Drawable[] { - restoreDefaultButton = new RestoreDefaultValueButton(), FlowContent = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -122,7 +119,11 @@ namespace osu.Game.Overlays.Settings }, }, }; + } + [BackgroundDependencyLoader] + private void load() + { // all bindable logic is in constructor intentionally to support "CreateSettingsControls" being used in a context it is // never loaded, but requires bindable storage. if (controlWithCurrent == null) @@ -130,14 +131,15 @@ namespace osu.Game.Overlays.Settings controlWithCurrent.Current.ValueChanged += _ => SettingChanged?.Invoke(); controlWithCurrent.Current.DisabledChanged += _ => updateDisabled(); - } - - protected override void LoadComplete() - { - base.LoadComplete(); + // intentionally done before LoadComplete to avoid overhead. if (ShowsDefaultIndicator) - restoreDefaultButton.Current = controlWithCurrent.Current; + { + AddInternal(new RestoreDefaultValueButton + { + Current = controlWithCurrent.Current, + }); + } } private void updateDisabled() From b541550ea97516b877363c2d0509848450b02a40 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 19:17:36 +0900 Subject: [PATCH 137/366] Avoid initial synchronous dropdown population overhead in `AudioDevicesSettings` --- .../Sections/Audio/AudioDevicesSettings.cs | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index d64f176468..2354475498 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -20,17 +20,26 @@ namespace osu.Game.Overlays.Settings.Sections.Audio private SettingsDropdown dropdown; - protected override void Dispose(bool isDisposing) + [BackgroundDependencyLoader] + private void load() { - base.Dispose(isDisposing); - - if (audio != null) + Children = new Drawable[] { - audio.OnNewDevice -= onDeviceChanged; - audio.OnLostDevice -= onDeviceChanged; - } + dropdown = new AudioDeviceSettingsDropdown + { + Keywords = new[] { "speaker", "headphone", "output" } + } + }; + + updateItems(); + + audio.OnNewDevice += onDeviceChanged; + audio.OnLostDevice += onDeviceChanged; + dropdown.Current = audio.AudioDevice; } + private void onDeviceChanged(string name) => updateItems(); + private void updateItems() { var deviceItems = new List { string.Empty }; @@ -49,26 +58,15 @@ namespace osu.Game.Overlays.Settings.Sections.Audio dropdown.Items = deviceItems.Distinct().ToList(); } - private void onDeviceChanged(string name) => updateItems(); - - protected override void LoadComplete() + protected override void Dispose(bool isDisposing) { - base.LoadComplete(); + base.Dispose(isDisposing); - Children = new Drawable[] + if (audio != null) { - dropdown = new AudioDeviceSettingsDropdown - { - Keywords = new[] { "speaker", "headphone", "output" } - } - }; - - updateItems(); - - dropdown.Current = audio.AudioDevice; - - audio.OnNewDevice += onDeviceChanged; - audio.OnLostDevice += onDeviceChanged; + audio.OnNewDevice -= onDeviceChanged; + audio.OnLostDevice -= onDeviceChanged; + } } private class AudioDeviceSettingsDropdown : SettingsDropdown From c6bd8520a7464f43e4ef558fd61d0015c1e1f171 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 19:18:39 +0900 Subject: [PATCH 138/366] Add basic asynchronous loading pattern to `SettingsPanel` --- osu.Game/Overlays/SettingsPanel.cs | 93 ++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 29 deletions(-) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index f1c41c4b50..c191f61e60 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osuTK; using osuTK.Graphics; @@ -13,6 +14,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -58,6 +60,8 @@ namespace osu.Game.Overlays private readonly bool showSidebar; + private LoadingLayer loading; + protected SettingsPanel(bool showSidebar) { this.showSidebar = showSidebar; @@ -86,45 +90,69 @@ namespace osu.Game.Overlays Colour = OsuColour.Gray(0.05f), Alpha = 1, }, - SectionsContainer = new SettingsSectionsContainer + loading = new LoadingLayer { - Masking = true, - RelativeSizeAxes = Axes.Both, - ExpandableHeader = CreateHeader(), - FixedHeader = searchTextBox = new SeekLimitedSearchTextBox - { - RelativeSizeAxes = Axes.X, - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Width = 0.95f, - Margin = new MarginPadding - { - Top = 20, - Bottom = 20 - }, - }, - Footer = CreateFooter() - }, + State = { Value = Visibility.Visible } + } } }; + SectionsContainer = new SettingsSectionsContainer + { + Masking = true, + RelativeSizeAxes = Axes.Both, + ExpandableHeader = CreateHeader(), + FixedHeader = searchTextBox = new SeekLimitedSearchTextBox + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Width = 0.95f, + Margin = new MarginPadding + { + Top = 20, + Bottom = 20 + }, + }, + Footer = CreateFooter() + }; + if (showSidebar) { AddInternal(Sidebar = new Sidebar { Width = sidebar_width }); - - SectionsContainer.SelectedSection.ValueChanged += section => - { - selectedSidebarButton.Selected = false; - selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); - selectedSidebarButton.Selected = true; - }; } - searchTextBox.Current.ValueChanged += term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue; - CreateSections()?.ForEach(AddSection); } + private void ensureContentLoaded() + { + if (SectionsContainer.LoadState > LoadState.NotLoaded) + return; + + Debug.Assert(SectionsContainer != null); + + LoadComponentAsync(SectionsContainer, d => + { + ContentContainer.Add(d); + d.FadeInFromZero(500); + loading.Hide(); + + if (Sidebar != null) + { + SectionsContainer.SelectedSection.ValueChanged += section => + { + selectedSidebarButton.Selected = false; + selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); + selectedSidebarButton.Selected = true; + }; + } + + searchTextBox.Current.BindValueChanged(term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue, true); + searchTextBox.TakeFocus(); + }); + } + protected void AddSection(SettingsSection section) { SectionsContainer.Add(section); @@ -136,6 +164,10 @@ namespace osu.Game.Overlays Section = section, Action = () => { + // may not be loaded yet. + if (SectionsContainer == null) + return; + SectionsContainer.ScrollTo(section); Sidebar.State = ExpandedState.Contracted; }, @@ -159,7 +191,8 @@ namespace osu.Game.Overlays { base.PopIn(); - ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); + ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint) + .OnComplete(_ => ensureContentLoaded()); Sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); @@ -187,7 +220,7 @@ namespace osu.Game.Overlays protected override void OnFocus(FocusEvent e) { - searchTextBox.TakeFocus(); + searchTextBox?.TakeFocus(); base.OnFocus(e); } @@ -209,6 +242,8 @@ namespace osu.Game.Overlays { public SearchContainer SearchContainer; + public new ScheduledDelegate Schedule(Action action) => Scheduler.AddDelayed(action, TransformDelay); + protected override FlowContainer CreateScrollContentContainer() => SearchContainer = new SearchContainer { From 230c4eb2475a16c136d001598570d8b4d0c25450 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 19:47:27 +0900 Subject: [PATCH 139/366] Fade in sidebar buttons after the load has completed --- osu.Game/Overlays/Settings/SidebarButton.cs | 3 + osu.Game/Overlays/SettingsPanel.cs | 68 +++++++++++++-------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index 30a53b351d..cf6a313a1f 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -22,6 +22,9 @@ namespace osu.Game.Overlays.Settings private readonly Box selectionIndicator; private readonly Container text; + // always consider as part of flow, even when not visible (for the sake of the initial animation). + public override bool IsPresent => true; + private SettingsSection section; public SettingsSection Section diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index c191f61e60..388c809be8 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -135,54 +135,70 @@ namespace osu.Game.Overlays LoadComponentAsync(SectionsContainer, d => { ContentContainer.Add(d); - d.FadeInFromZero(500); + d.FadeInFromZero(750, Easing.OutQuint); loading.Hide(); - if (Sidebar != null) - { - SectionsContainer.SelectedSection.ValueChanged += section => - { - selectedSidebarButton.Selected = false; - selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); - selectedSidebarButton.Selected = true; - }; - } - searchTextBox.Current.BindValueChanged(term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue, true); searchTextBox.TakeFocus(); + + if (Sidebar == null) + return; + + LoadComponentsAsync(createSidebarButtons(), buttons => + { + float delay = 0; + + foreach (var button in buttons) + { + Sidebar.Add(button); + + button.FadeOut() + .Delay(delay) + .FadeInFromZero(1000, Easing.OutQuint); + + delay += 30; + } + + SectionsContainer.SelectedSection.BindValueChanged(section => + { + if (selectedSidebarButton != null) + selectedSidebarButton.Selected = false; + + selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); + selectedSidebarButton.Selected = true; + }, true); + }); }); } - protected void AddSection(SettingsSection section) + private IEnumerable createSidebarButtons() { - SectionsContainer.Add(section); - - if (Sidebar != null) + foreach (var section in SectionsContainer) { - var button = new SidebarButton + yield return new SidebarButton { Section = section, Action = () => { - // may not be loaded yet. - if (SectionsContainer == null) + if (!SectionsContainer.IsLoaded) return; SectionsContainer.ScrollTo(section); Sidebar.State = ExpandedState.Contracted; }, }; - - Sidebar.Add(button); - - if (selectedSidebarButton == null) - { - selectedSidebarButton = Sidebar.Children.First(); - selectedSidebarButton.Selected = true; - } } } + protected void AddSection(SettingsSection section) + { + if (IsLoaded) + // just to keep things simple. can be accommodated for if we ever need it. + throw new InvalidOperationException("All sections must be added before the panel is loaded."); + + SectionsContainer.Add(section); + } + protected virtual Drawable CreateHeader() => new Container(); protected virtual Drawable CreateFooter() => new Container(); From e485728109869c1e3704056e1c2b9c98708c43d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 19:54:45 +0900 Subject: [PATCH 140/366] Add keywords to make finding audio offset adjustments easier in settings --- osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index 7f2e377c83..eaa557bb37 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; @@ -13,6 +15,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override LocalisableString Header => "Offset Adjustment"; + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "universal", "uo", "timing" }); + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { From de61cb8e6a9a2fb22263098f6ec779360437adce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 19:51:13 +0900 Subject: [PATCH 141/366] Adjust delay slightly --- osu.Game/Overlays/SettingsPanel.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 388c809be8..6593b6cb1e 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using osuTK; using osuTK.Graphics; @@ -130,8 +129,6 @@ namespace osu.Game.Overlays if (SectionsContainer.LoadState > LoadState.NotLoaded) return; - Debug.Assert(SectionsContainer != null); - LoadComponentAsync(SectionsContainer, d => { ContentContainer.Add(d); @@ -207,8 +204,13 @@ namespace osu.Game.Overlays { base.PopIn(); - ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint) - .OnComplete(_ => ensureContentLoaded()); + ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); + + // delay load enough to ensure it doesn't overlap with the initial animation. + // this is done as there is still a brief stutter during load completion which is more visible if the transition is in progress. + // the eventual goal would be to remove the need for this by splitting up load into smaller work pieces, or fixing the remaining + // load complete overheads. + Scheduler.AddDelayed(ensureContentLoaded, TRANSITION_LENGTH / 3); Sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); From 1f942d15f825f6b5db0378e092fdc00c508f86b3 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 16 Aug 2021 13:38:57 +0200 Subject: [PATCH 142/366] Localise scoreboard --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 7 +++--- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 23 ++++++++++--------- .../Scores/TopScoreStatisticsSection.cs | 22 ++++++++++-------- .../BeatmapSet/Scores/TopScoreUserSection.cs | 3 ++- .../Leaderboards/BeatmapLeaderboardScope.cs | 8 ++++--- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index 391ba93a4b..82ca3e030f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Screens.Select.Leaderboards; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -30,15 +31,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores switch (scope) { default: - text.Text = @"No scores have been set yet. Maybe you can be the first!"; + text.Text = BeatmapsetsStrings.ShowScoreboardNoScoresGlobal; break; case BeatmapLeaderboardScope.Friend: - text.Text = @"None of your friends have set a score on this map yet."; + text.Text = BeatmapsetsStrings.ShowScoreboardNoScoresFriend; break; case BeatmapLeaderboardScope.Country: - text.Text = @"No one from your country has set a score on this map yet."; + text.Text = BeatmapsetsStrings.ShowScoreboardNoScoresCountry; break; } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index fee0e62315..a154016824 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -20,6 +20,7 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Localisation; using osu.Framework.Extensions.LocalisationExtensions; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -93,13 +94,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { var columns = new List { - new TableColumn("rank", Anchor.CentreRight, new Dimension(GridSizeMode.AutoSize)), + new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersRank, Anchor.CentreRight, new Dimension(GridSizeMode.AutoSize)), new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), // grade - new TableColumn("score", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("accuracy", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, minSize: 60, maxSize: 70)), + new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersScore, Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), + new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersAccuracy, Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, minSize: 60, maxSize: 70)), new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 25)), // flag - new TableColumn("player", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 125)), - new TableColumn("max combo", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 120)) + new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersPlayer, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 125)), + new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersCombo, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 120)) }; // All statistics across all scores, unordered. @@ -124,9 +125,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } if (showPerformancePoints) - columns.Add(new TableColumn("pp", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 30))); + columns.Add(new TableColumn(BeatmapsetsStrings.ShowScoreboardHeaderspp, Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 30))); - columns.Add(new TableColumn("mods", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize))); + columns.Add(new TableColumn(BeatmapsetsStrings.ShowScoreboardHeadersMods, Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize))); return columns.ToArray(); } @@ -140,7 +141,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { new OsuSpriteText { - Text = $"#{index + 1}", + Text = (index + 1).ToLocalisableString(@"\##"), Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, new UpdateableRank(score.Rank) @@ -168,7 +169,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores username, new OsuSpriteText { - Text = $@"{score.MaxCombo:N0}x", + Text = score.MaxCombo.ToLocalisableString(@"0\x"), Font = OsuFont.GetFont(size: text_size), Colour = score.MaxCombo == score.Beatmap?.MaxCombo ? highAccuracyColour : Color4.White } @@ -183,7 +184,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores content.Add(new OsuSpriteText { - Text = stat.MaxCount == null ? $"{stat.Count}" : $"{stat.Count}/{stat.MaxCount}", + Text = stat.MaxCount == null ? stat.Count.ToLocalisableString(@"N0") : (LocalisableString)$"{stat.Count}/{stat.MaxCount}", Font = OsuFont.GetFont(size: text_size), Colour = stat.Count == 0 ? Color4.Gray : Color4.White }); @@ -193,7 +194,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { content.Add(new OsuSpriteText { - Text = $@"{score.PP:N0}", + Text = score.PP.ToLocalisableString(@"N0"), Font = OsuFont.GetFont(size: text_size) }); } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 3d5f3f595c..582528b675 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -13,6 +14,7 @@ using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Scoring; @@ -61,9 +63,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(margin, 0), Children = new Drawable[] { - totalScoreColumn = new TextColumn("total score", largeFont, top_columns_min_width), - accuracyColumn = new TextColumn("accuracy", largeFont, top_columns_min_width), - maxComboColumn = new TextColumn("max combo", largeFont, top_columns_min_width) + totalScoreColumn = new TextColumn(BeatmapsetsStrings.ShowScoreboardHeadersScoreTotal, largeFont, top_columns_min_width), + accuracyColumn = new TextColumn(BeatmapsetsStrings.ShowScoreboardHeadersAccuracy, largeFont, top_columns_min_width), + maxComboColumn = new TextColumn(BeatmapsetsStrings.ShowScoreboardHeadersCombo, largeFont, top_columns_min_width) } }, new FillFlowContainer @@ -81,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Direction = FillDirection.Horizontal, Spacing = new Vector2(margin, 0), }, - ppColumn = new TextColumn("pp", smallFont, bottom_columns_min_width), + ppColumn = new TextColumn(BeatmapsetsStrings.ShowScoreboardHeaderspp, smallFont, bottom_columns_min_width), modsColumn = new ModsInfoColumn(), } }, @@ -111,10 +113,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores score = value; accuracyColumn.Text = value.DisplayAccuracy; - maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; + maxComboColumn.Text = value.MaxCombo.ToLocalisableString(@"0\x"); ppColumn.Alpha = value.Beatmap?.Status.GrantsPerformancePoints() == true ? 1 : 0; - ppColumn.Text = $@"{value.PP:N0}"; + ppColumn.Text = value.PP.ToLocalisableString(@"N0"); statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn); modsColumn.Mods = value.Mods; @@ -126,7 +128,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private TextColumn createStatisticsColumn(HitResultDisplayStatistic stat) => new TextColumn(stat.DisplayName, smallFont, bottom_columns_min_width) { - Text = stat.MaxCount == null ? $"{stat.Count}" : $"{stat.Count}/{stat.MaxCount}" + Text = stat.MaxCount == null ? stat.Count.ToLocalisableString(@"N0") : (LocalisableString)$"{stat.Count}/{stat.MaxCount}" }; private class InfoColumn : CompositeDrawable @@ -134,7 +136,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box separator; private readonly OsuSpriteText text; - public InfoColumn(string title, Drawable content, float? minWidth = null) + public InfoColumn(LocalisableString title, Drawable content, float? minWidth = null) { AutoSizeAxes = Axes.Both; Margin = new MarginPadding { Vertical = 5 }; @@ -194,12 +196,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private readonly SpriteText text; - public TextColumn(string title, FontUsage font, float? minWidth = null) + public TextColumn(LocalisableString title, FontUsage font, float? minWidth = null) : this(title, new OsuSpriteText { Font = font }, minWidth) { } - private TextColumn(string title, SpriteText text, float? minWidth = null) + private TextColumn(LocalisableString title, SpriteText text, float? minWidth = null) : base(title, text, minWidth) { this.text = text; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 736366fb5c..c934020059 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -126,7 +127,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public int? ScorePosition { - set => rankText.Text = value == null ? "-" : $"#{value}"; + set => rankText.Text = value == null ? (LocalisableString)"-" : value.ToLocalisableString(@"\##"); } /// diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs index dc4c2ba4e2..5bcb4c27a7 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Screens.Select.Leaderboards { @@ -10,13 +12,13 @@ namespace osu.Game.Screens.Select.Leaderboards [Description("Local Ranking")] Local, - [Description("Country Ranking")] + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowScoreboardCountry))] Country, - [Description("Global Ranking")] + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowScoreboardGlobal))] Global, - [Description("Friend Ranking")] + [LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowScoreboardFriend))] Friend, } } From 3325b0cc95d314e700a3e4d928fac9cf6b61c229 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 16 Aug 2021 14:50:08 +0200 Subject: [PATCH 143/366] Fix merge conflicts. --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index dfba93cdbd..80dc185bb5 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.BeatmapSet set => this.value.Text = value; } - public Statistic(BeatmapStatisticsIconType icon, string name) + public Statistic(BeatmapStatisticsIconType icon, LocalisableString name) { TooltipText = name; RelativeSizeAxes = Axes.X; From 568d027013a67ddcc3ff58525001301cf353da8a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 22:07:41 +0900 Subject: [PATCH 144/366] Simplify weird conditionals --- .../Settings/Sections/Input/TabletSettings.cs | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 8303fee3ef..b8b86d9069 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -266,24 +266,16 @@ namespace osu.Game.Overlays.Settings.Sections.Input private void updateVisibility() { - if (!tabletHandler.Enabled.Value) - { - mainSettings.Hide(); - noTabletMessage.Hide(); - return; - } - - bool tabletFound = tablet.Value != null; - - if (!tabletFound) - { - mainSettings.Hide(); - noTabletMessage.Show(); - return; - } - - mainSettings.Show(); + mainSettings.Hide(); noTabletMessage.Hide(); + + if (!tabletHandler.Enabled.Value) + return; + + if (tablet.Value != null) + mainSettings.Show(); + else + noTabletMessage.Show(); } private void applyAspectRatio(BindableNumber sizeChanged) From 677f5aff9e39a0a2de16a0c25071f787db4a70e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 23:30:50 +0900 Subject: [PATCH 145/366] Fix test failures --- osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs index fa2c9ecdea..8632bfe681 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs @@ -32,6 +32,7 @@ namespace osu.Game.Tests.Visual.Settings [SetUpSteps] public void SetUpSteps() { + AddUntilStep("wait for load", () => panel.ChildrenOfType().Any()); AddStep("Scroll to top", () => panel.ChildrenOfType().First().ScrollToTop()); AddWaitStep("wait for scroll", 5); } From c3a86769323e11c637cd738393928be1e1499b47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Aug 2021 23:38:13 +0900 Subject: [PATCH 146/366] Simplify size specifications --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index c51f927f9f..508c8399b6 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -144,8 +144,7 @@ namespace osu.Game.Overlays.Changelog { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Width = heart_size, - Height = heart_size, + Size = new Vector2(heart_size), Margin = new MarginPadding { Top = 70 }, Masking = true, EdgeEffect = new EdgeEffectParameters @@ -157,8 +156,7 @@ namespace osu.Game.Overlays.Changelog }, Child = new Sprite { - Width = heart_size, - Height = heart_size, + Size = new Vector2(heart_size), Texture = textures.Get(@"Online/supporter-heart"), }, }, From df6e4664e0aaa47788c1064be78126fe57fa1d75 Mon Sep 17 00:00:00 2001 From: emu1337 Date: Mon, 16 Aug 2021 16:42:07 +0200 Subject: [PATCH 147/366] changed history length in speed --- osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index b1373cd215..5b8ec5103a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -29,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double max_speed_bonus = 45; // ~330BPM private const double speed_balancing_factor = 40; + protected override int HistoryLength => 32; + public Speed(Mod[] mods) : base(mods) { From 4bf22db4ff9ff21123d9a0cc35a6aa2ed099b65d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 00:23:30 +0900 Subject: [PATCH 148/366] Attempt to reduce skin lookup overhead where file access is not required --- osu.Game/Database/MutableDatabaseBackedStore.cs | 5 +++++ osu.Game/Skinning/SkinManager.cs | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/MutableDatabaseBackedStore.cs b/osu.Game/Database/MutableDatabaseBackedStore.cs index c9d0c4bc41..b0feb7bb78 100644 --- a/osu.Game/Database/MutableDatabaseBackedStore.cs +++ b/osu.Game/Database/MutableDatabaseBackedStore.cs @@ -36,6 +36,11 @@ namespace osu.Game.Database /// public IQueryable ConsumableItems => AddIncludesForConsumption(ContextFactory.Get().Set()); + /// + /// Access barebones items with no includes. + /// + public IQueryable Items => ContextFactory.Get().Set(); + /// /// Add a to the database. /// diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index ea55fd28c2..fca1670419 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -105,12 +105,12 @@ namespace osu.Game.Skinning /// Returns a list of all usable s that have been loaded by the user. /// /// A newly allocated list of available . - public List GetAllUserSkins() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + public List GetAllUserSkins() => ModelStore.Items.Where(s => !s.DeletePending).ToList(); public void SelectRandomSkin() { // choose from only user skins, removing the current selection to ensure a new one is chosen. - var randomChoices = GetAllUsableSkins().Where(s => s.ID != CurrentSkinInfo.Value.ID).ToArray(); + var randomChoices = ModelStore.Items.Where(s => !s.DeletePending && s.ID != CurrentSkinInfo.Value.ID).ToArray(); if (randomChoices.Length == 0) { @@ -118,7 +118,8 @@ namespace osu.Game.Skinning return; } - CurrentSkinInfo.Value = randomChoices.ElementAt(RNG.Next(0, randomChoices.Length)); + var chosen = randomChoices.ElementAt(RNG.Next(0, randomChoices.Length)); + CurrentSkinInfo.Value = ModelStore.ConsumableItems.Single(i => i.ID == chosen.ID); } protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name }; From 19cdd5c3234ad368f81d2c3df8f66abf63fb51df Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 15:25:35 +0000 Subject: [PATCH 149/366] recoded and added rhythm complexity calculator (untested) --- .../Difficulty/Skills/Speed.cs | 82 ++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 5b8ec5103a..73704735d0 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double pi_over_4 = Math.PI / 4; private const double pi_over_2 = Math.PI / 2; + private const double rhythmMultiplier = 1.0; protected override double SkillMultiplier => 1400; protected override double StrainDecayBase => 0.3; protected override int ReducedSectionCount => 5; @@ -31,16 +32,91 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected override int HistoryLength => 32; + private const int HistoryTimeMax = 4; // 4 seconds of calculatingRhythmBonus max. + public Speed(Mod[] mods) : base(mods) { } - private double calculateRhythmBonus(double time) + private bool isRatioEqual(double ratio, double a, double b) { - return 1.0; + return a + 15 > ratio * b && a - 15 < ratio * b; } + /// + /// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current . + /// + private double calculateRhythmBonus(double startTime) + { + // {doubles, triplets, quads, quints, 6-tuplets, 7 Tuplets, greater} + int previousIslandSize = -1; + double[] islandTimes = {0, 0, 0, 0, 0, 0, 0}; + int islandSize = 0; + + bool firstDeltaSwitch = false; + + for (int i = Previous.Count - 1; i < 0; i--) + { + double currDelta = ((OsuDifficultyHitObject)Previous[i - 1]).StrainTime; + double prevDelta = ((OsuDifficultyHitObject)Previous[i]).StrainTime; + double effectiveRatio = Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta); + + double currHistoricalDecay = Math.Max(0, (HistoryTimeMax - (startTime - Previous[i - 1].StartTime))) / HistoryTimeMax; + + // if (historyTime > HistoryTimeMax) + // break; // not sure if this even does what I want.. + + if (firstDeltaSwitch) + { + if (isRatioEqual(1.0, prevDelta, currDelta)) + { + islandSize++; // island is still progressing, count size. + } + + else + { + if (islandSize > 6) + islandSize = 6; + + if (Previous[i - 1].BaseObject is Slider) // bpm change is into slider, this is easy acc window + effectiveRatio *= 0.5; + + if (Previous[i].BaseObject is Slider) // bpm change was from a slider, this is easier typically than circle -> circle + effectiveRatio *= 0.75; + + if (previousIslandSize == islandSize) // repeated island size (ex: triplet -> triplet) + effectiveRatio *= 0.5; + + islandTimes[islandSize] = islandTimes[islandSize] + effectiveRatio * currHistoricalDecay; + + previousIslandSize = islandSize; // log the last island size. + + if (prevDelta * 1.25 < currDelta) // we're slowing down, stop counting + firstDeltaSwitch = false; // if we're speeding up, this stays true and we keep counting island size. + + islandSize = 0; + } + } + else if (prevDelta > 1.25 * currDelta) // we want to be speeding up. + { + // Begin counting island until we change speed again. + firstDeltaSwitch = true; + islandSize = 0; + } + } + + double rhythmComplexitySum = 0.0; + + for (int i = 0; i < islandTimes.Length; i++) + { + rhythmComplexitySum += islandTimes[i]; // sum the total amount of rhythm variance + } + +Console.WriteLine(Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); + + return Math.Min(1.5, Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); + } protected override double StrainValueOf(DifficultyHitObject current) { @@ -81,7 +157,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected override double GetPeakStrain(double time) { - return base.GetPeakStrain(time) * calculateRhythmBonus(time); + return base.GetPeakStrain(time);// * calculateRhythmBonus(current.StartTime); } } } From 7d46b3f9c5fe9062afa5528d025908173c5ca812 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 16:06:50 +0000 Subject: [PATCH 150/366] initial testing and debugging --- .../Difficulty/Skills/Speed.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 73704735d0..433150a025 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -20,7 +20,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double pi_over_4 = Math.PI / 4; private const double pi_over_2 = Math.PI / 2; - private const double rhythmMultiplier = 1.0; + private const double rhythmMultiplier = 1.5; + protected override double SkillMultiplier => 1400; protected override double StrainDecayBase => 0.3; protected override int ReducedSectionCount => 5; @@ -32,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected override int HistoryLength => 32; - private const int HistoryTimeMax = 4; // 4 seconds of calculatingRhythmBonus max. + private const int HistoryTimeMax = 3000; // 4 seconds of calculatingRhythmBonus max. public Speed(Mod[] mods) : base(mods) @@ -56,16 +57,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills bool firstDeltaSwitch = false; - for (int i = Previous.Count - 1; i < 0; i--) + for (int i = Previous.Count - 1; i > 0; i--) { double currDelta = ((OsuDifficultyHitObject)Previous[i - 1]).StrainTime; double prevDelta = ((OsuDifficultyHitObject)Previous[i]).StrainTime; double effectiveRatio = Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta); - double currHistoricalDecay = Math.Max(0, (HistoryTimeMax - (startTime - Previous[i - 1].StartTime))) / HistoryTimeMax; + if (effectiveRatio > 0.5) + effectiveRatio = 0.5 + (effectiveRatio - 0.5) * 5; // extra buff for 1/3 -> 1/4 etc transitions. - // if (historyTime > HistoryTimeMax) - // break; // not sure if this even does what I want.. + double currHistoricalDecay = Math.Max(0, (HistoryTimeMax - (startTime - Previous[i - 1].StartTime))) / HistoryTimeMax; if (firstDeltaSwitch) { @@ -113,9 +114,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills rhythmComplexitySum += islandTimes[i]; // sum the total amount of rhythm variance } -Console.WriteLine(Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); +// Console.WriteLine(Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); - return Math.Min(1.5, Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); + return Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2; } protected override double StrainValueOf(DifficultyHitObject current) From 78f9f4a23081ce994c702215ff94e6d805151b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Sch=C3=BCrz?= Date: Mon, 16 Aug 2021 20:36:46 +0200 Subject: [PATCH 151/366] Move time clamp to `Seek`/`transformSeekTo` methods --- osu.Game/Screens/Edit/EditorClock.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 52c95088f3..ba83261731 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -118,7 +118,6 @@ namespace osu.Game.Screens.Edit if (!snapped || ControlPointInfo.TimingPoints.Count == 0) { - seekTime = Math.Clamp(seekTime, 0, TrackLength); SeekSmoothlyTo(seekTime); return; } @@ -151,8 +150,6 @@ namespace osu.Game.Screens.Edit if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First()) seekTime = timingPoint.Time; - // Ensure the sought point is within the boundaries - seekTime = Math.Clamp(seekTime, 0, TrackLength); SeekSmoothlyTo(seekTime); } @@ -191,6 +188,9 @@ namespace osu.Game.Screens.Edit seekingOrStopped.Value = IsSeeking = true; ClearTransforms(); + + // Ensure the sought point is within the boundaries + position = Math.Clamp(position, 0, TrackLength); return underlyingClock.Seek(position); } @@ -289,7 +289,7 @@ namespace osu.Game.Screens.Edit } private void transformSeekTo(double seek, double duration = 0, Easing easing = Easing.None) - => this.TransformTo(this.PopulateTransform(new TransformSeek(), seek, duration, easing)); + => this.TransformTo(this.PopulateTransform(new TransformSeek(), Math.Clamp(seek, 0, TrackLength), duration, easing)); private double currentTime { From 314c342841e23954c8fc3c80aa4a6930143a5fb6 Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Mon, 16 Aug 2021 22:13:01 +0300 Subject: [PATCH 152/366] Avoid drawing segments of cursor trail near current cursor position --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 7a95111c91..43e0a57f7c 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -172,7 +172,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor float interval = partSize.X / 2.5f * IntervalMultiplier; - for (float d = interval; d < distance; d += interval) + for (float d = interval; d < distance - interval; d += interval) { lastPosition = pos1 + direction * d; addPart(lastPosition.Value); From ef367c6547f7dc27ad7fc9c2470f1403438a1cde Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Mon, 16 Aug 2021 22:52:19 +0300 Subject: [PATCH 153/366] Move implementation to be legacy only --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs | 1 + osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs index 587ff4b573..75d847d54d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs @@ -62,6 +62,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy protected override bool InterpolateMovements => !disjointTrail; protected override float IntervalMultiplier => 1 / Math.Max(cursorSize.Value, 1); + protected override bool AvoidDrawingNearCursor => !disjointTrail; protected override void Update() { diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 43e0a57f7c..62cab4d6d7 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -138,6 +138,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected virtual bool InterpolateMovements => true; protected virtual float IntervalMultiplier => 1.0f; + protected virtual bool AvoidDrawingNearCursor => false; private Vector2? lastPosition; private readonly InputResampler resampler = new InputResampler(); @@ -171,8 +172,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Vector2 direction = diff / distance; float interval = partSize.X / 2.5f * IntervalMultiplier; + float stopAt = distance - (AvoidDrawingNearCursor ? interval : 0); - for (float d = interval; d < distance - interval; d += interval) + for (float d = interval; d < stopAt; d += interval) { lastPosition = pos1 + direction * d; addPart(lastPosition.Value); From 176b3e75335476273ceb305a60c2b4a0fc9fa3f4 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 22:14:29 +0000 Subject: [PATCH 154/366] changed decay system to allow for customizing the currentStrain --- .../Difficulty/Skills/Movement.cs | 2 +- .../Difficulty/Skills/Strain.cs | 4 +- .../Difficulty/Skills/Aim.cs | 2 +- .../Difficulty/Skills/OsuStrainSkill.cs | 4 +- .../Difficulty/Skills/Speed.cs | 11 +--- .../Difficulty/Skills/Colour.cs | 2 +- .../Difficulty/Skills/Rhythm.cs | 2 +- .../Difficulty/Skills/Stamina.cs | 2 +- .../Difficulty/Skills/StrainDecaySkill.cs | 64 +++++++++++++++++++ .../Rulesets/Difficulty/Skills/StrainSkill.cs | 44 +++---------- 10 files changed, 83 insertions(+), 54 deletions(-) create mode 100644 osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index 4372ed938c..cfb3fe40be 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { - public class Movement : StrainSkill + public class Movement : StrainDecaySkill { private const float absolute_player_positioning_error = 16f; private const float normalized_hitobject_radius = 41.0f; diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs index 2ba2ee6b4a..01d930d585 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Difficulty.Skills { - public class Strain : StrainSkill + public class Strain : StrainDecaySkill { private const double individual_decay_base = 0.125; private const double overall_decay_base = 0.30; @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills return individualStrain + overallStrain - CurrentStrain; } - protected override double GetPeakStrain(double offset) + protected override double CalculateInitialStrain(double offset) => applyDecay(individualStrain, offset - Previous[0].StartTime, individual_decay_base) + applyDecay(overallStrain, offset - Previous[0].StartTime, overall_decay_base); diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index 16a18cbcb9..f08c19af76 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances. /// - public class Aim : OsuStrainSkill + public class Aim : OsuStrainDecaySkill { private const double angle_bonus_begin = Math.PI / 3; private const double timing_threshold = 107; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index e47edc37cc..c1bee9b202 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs @@ -10,7 +10,7 @@ using osu.Framework.Utils; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { - public abstract class OsuStrainSkill : StrainSkill + public abstract class OsuStrainDecaySkill : StrainDecaySkill { /// /// The number of sections with the highest strains, which the peak strain reductions will apply to. @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// protected virtual double DifficultyMultiplier => 1.06; - protected OsuStrainSkill(Mod[] mods) + protected OsuStrainDecaySkill(Mod[] mods) : base(mods) { } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 433150a025..bb40ff657a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Represents the skill required to press keys with regards to keeping up with the speed at which objects need to be hit. /// - public class Speed : OsuStrainSkill + public class Speed : OsuStrainDecaySkill { private const double single_spacing_threshold = 125; @@ -151,14 +151,5 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / osuCurrent.StrainTime; } - protected override double GetTotalCurrentStrain(DifficultyHitObject current) - { - return base.GetTotalCurrentStrain(current) * calculateRhythmBonus(current.StartTime); - } - - protected override double GetPeakStrain(double time) - { - return base.GetPeakStrain(time);// * calculateRhythmBonus(current.StartTime); - } } } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs index 769d021362..0c17ca66b9 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills /// /// Calculates the colour coefficient of taiko difficulty. /// - public class Colour : StrainSkill + public class Colour : StrainDecaySkill { protected override double SkillMultiplier => 1; protected override double StrainDecayBase => 0.4; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs index a32f6ebe0d..973e55f4b4 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills /// /// Calculates the rhythm coefficient of taiko difficulty. /// - public class Rhythm : StrainSkill + public class Rhythm : StrainDecaySkill { protected override double SkillMultiplier => 10; protected override double StrainDecayBase => 0; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs index 4cceadb23f..54cf233d69 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills /// /// The reference play style chosen uses two hands, with full alternating (the hand changes after every hit). /// - public class Stamina : StrainSkill + public class Stamina : StrainDecaySkill { protected override double SkillMultiplier => 1; protected override double StrainDecayBase => 0.4; diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs new file mode 100644 index 0000000000..dab1081abb --- /dev/null +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs @@ -0,0 +1,64 @@ +// 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.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Difficulty.Skills +{ + /// + /// Used to processes strain values of s, keep track of strain levels caused by the processed objects + /// and to calculate a final difficulty value representing the difficulty of hitting all the processed objects. + /// + public abstract class StrainDecaySkill : StrainSkill + { + /// + /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other. + /// + protected abstract double SkillMultiplier { get; } + + /// + /// Determines how quickly strain decays for the given skill. + /// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second. + /// + protected abstract double StrainDecayBase { get; } + + /// + /// The current strain level. + /// + protected double CurrentStrain { get; private set; } = 1; + + protected StrainDecaySkill(Mod[] mods) + : base(mods) + { + } + + /// + /// Retrieves the peak strain at a point in time. + /// + /// The time to retrieve the peak strain at. + /// The peak strain. + protected override double CalculateInitialStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime); + + /// + /// Returns the strain value of . This value is calculated with or without respect to previous objects. + /// + protected override double StrainValueAt(DifficultyHitObject current) + { + CurrentStrain *= strainDecay(current.DeltaTime); + CurrentStrain += StrainValueOf(current) * SkillMultiplier; + + return CurrentStrain; + } + + /// + /// Calculates the strain value of a . This value is affected by previously processed objects. + /// + protected abstract double StrainValueOf(DifficultyHitObject current); + + private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000); + } +} diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index 95b0fe43fc..e8ae452506 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -15,27 +15,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// public abstract class StrainSkill : Skill { - /// - /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other. - /// - protected abstract double SkillMultiplier { get; } - - /// - /// Determines how quickly strain decays for the given skill. - /// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second. - /// - protected abstract double StrainDecayBase { get; } - /// /// The weight by which each strain value decays. /// protected virtual double DecayWeight => 0.9; - /// - /// The current strain level. - /// - protected double CurrentStrain { get; private set; } = 1; - /// /// The length of each strain section. /// @@ -52,6 +36,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills { } + /// + /// Returns the strain value of . This value is calculated with or without respect to previous objects. + /// + protected abstract double StrainValueAt(DifficultyHitObject current); + /// /// Process a and update current strain values accordingly. /// @@ -68,15 +57,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills currentSectionEnd += SectionLength; } - CurrentStrain *= strainDecay(current.DeltaTime); - CurrentStrain += StrainValueOf(current) * SkillMultiplier; - - currentSectionPeak = Math.Max(GetTotalCurrentStrain(current), currentSectionPeak); - } - - protected virtual double GetTotalCurrentStrain(DifficultyHitObject current) - { - return CurrentStrain; + currentSectionPeak = Math.Max(StrainValueAt(current), currentSectionPeak); } /// @@ -93,9 +74,9 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// The beginning of the new section in milliseconds. private void startNewSectionFrom(double time) { - // The maximum strain of the new section is not zero by default, strain decays as usual regardless of section boundaries. + // The maximum strain of the new section is not zero by default // This means we need to capture the strain level at the beginning of the new section, and use that as the initial peak level. - currentSectionPeak = GetPeakStrain(time); + currentSectionPeak = CalculateInitialStrain(time); } /// @@ -103,7 +84,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// /// The time to retrieve the peak strain at. /// The peak strain. - protected virtual double GetPeakStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime); + protected abstract double CalculateInitialStrain(double time); /// /// Returns a live enumerable of the peak strains for each section of the beatmap, @@ -129,12 +110,5 @@ namespace osu.Game.Rulesets.Difficulty.Skills return difficulty; } - - /// - /// Calculates the strain value of a . This value is affected by previously processed objects. - /// - protected abstract double StrainValueOf(DifficultyHitObject current); - - private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000); } } From 5561e4852e838c226257d09088e3f51e42d6f2d2 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 22:23:40 +0000 Subject: [PATCH 155/366] removed stuff --- .../Difficulty/Skills/Speed.cs | 85 ------------------- 1 file changed, 85 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index bb40ff657a..78d1438923 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -20,8 +20,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double pi_over_4 = Math.PI / 4; private const double pi_over_2 = Math.PI / 2; - private const double rhythmMultiplier = 1.5; - protected override double SkillMultiplier => 1400; protected override double StrainDecayBase => 0.3; protected override int ReducedSectionCount => 5; @@ -31,94 +29,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double max_speed_bonus = 45; // ~330BPM private const double speed_balancing_factor = 40; - protected override int HistoryLength => 32; - - private const int HistoryTimeMax = 3000; // 4 seconds of calculatingRhythmBonus max. - public Speed(Mod[] mods) : base(mods) { } - private bool isRatioEqual(double ratio, double a, double b) - { - return a + 15 > ratio * b && a - 15 < ratio * b; - } - - /// - /// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current . - /// - private double calculateRhythmBonus(double startTime) - { - // {doubles, triplets, quads, quints, 6-tuplets, 7 Tuplets, greater} - int previousIslandSize = -1; - double[] islandTimes = {0, 0, 0, 0, 0, 0, 0}; - int islandSize = 0; - - bool firstDeltaSwitch = false; - - for (int i = Previous.Count - 1; i > 0; i--) - { - double currDelta = ((OsuDifficultyHitObject)Previous[i - 1]).StrainTime; - double prevDelta = ((OsuDifficultyHitObject)Previous[i]).StrainTime; - double effectiveRatio = Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta); - - if (effectiveRatio > 0.5) - effectiveRatio = 0.5 + (effectiveRatio - 0.5) * 5; // extra buff for 1/3 -> 1/4 etc transitions. - - double currHistoricalDecay = Math.Max(0, (HistoryTimeMax - (startTime - Previous[i - 1].StartTime))) / HistoryTimeMax; - - if (firstDeltaSwitch) - { - if (isRatioEqual(1.0, prevDelta, currDelta)) - { - islandSize++; // island is still progressing, count size. - } - - else - { - if (islandSize > 6) - islandSize = 6; - - if (Previous[i - 1].BaseObject is Slider) // bpm change is into slider, this is easy acc window - effectiveRatio *= 0.5; - - if (Previous[i].BaseObject is Slider) // bpm change was from a slider, this is easier typically than circle -> circle - effectiveRatio *= 0.75; - - if (previousIslandSize == islandSize) // repeated island size (ex: triplet -> triplet) - effectiveRatio *= 0.5; - - islandTimes[islandSize] = islandTimes[islandSize] + effectiveRatio * currHistoricalDecay; - - previousIslandSize = islandSize; // log the last island size. - - if (prevDelta * 1.25 < currDelta) // we're slowing down, stop counting - firstDeltaSwitch = false; // if we're speeding up, this stays true and we keep counting island size. - - islandSize = 0; - } - } - else if (prevDelta > 1.25 * currDelta) // we want to be speeding up. - { - // Begin counting island until we change speed again. - firstDeltaSwitch = true; - islandSize = 0; - } - } - - double rhythmComplexitySum = 0.0; - - for (int i = 0; i < islandTimes.Length; i++) - { - rhythmComplexitySum += islandTimes[i]; // sum the total amount of rhythm variance - } - -// Console.WriteLine(Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2); - - return Math.Sqrt(4 + rhythmComplexitySum * rhythmMultiplier) / 2; - } - protected override double StrainValueOf(DifficultyHitObject current) { if (current.BaseObject is Spinner) From 61045bd0876afac630c9611de1398c0c65677141 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 22:36:14 +0000 Subject: [PATCH 156/366] adjusted code comments --- osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs | 8 -------- osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs index dab1081abb..dbac132faf 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs @@ -36,16 +36,8 @@ namespace osu.Game.Rulesets.Difficulty.Skills { } - /// - /// Retrieves the peak strain at a point in time. - /// - /// The time to retrieve the peak strain at. - /// The peak strain. protected override double CalculateInitialStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime); - /// - /// Returns the strain value of . This value is calculated with or without respect to previous objects. - /// protected override double StrainValueAt(DifficultyHitObject current) { CurrentStrain *= strainDecay(current.DeltaTime); diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index e8ae452506..0880f1b08e 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills } /// - /// Returns the strain value of . This value is calculated with or without respect to previous objects. + /// Returns the strain value at . This value is calculated with or without respect to previous objects. /// protected abstract double StrainValueAt(DifficultyHitObject current); From 9b21016eed1aadc232c0023b23624d61775659c3 Mon Sep 17 00:00:00 2001 From: Xexxar Date: Mon, 16 Aug 2021 22:46:56 +0000 Subject: [PATCH 157/366] accidently renamed osuStrainSkill, fixed --- osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs | 2 +- osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs | 4 ++-- osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index f08c19af76..16a18cbcb9 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances. /// - public class Aim : OsuStrainDecaySkill + public class Aim : OsuStrainSkill { private const double angle_bonus_begin = Math.PI / 3; private const double timing_threshold = 107; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index c1bee9b202..7bcd867a9c 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs @@ -10,7 +10,7 @@ using osu.Framework.Utils; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { - public abstract class OsuStrainDecaySkill : StrainDecaySkill + public abstract class OsuStrainSkill : StrainDecaySkill { /// /// The number of sections with the highest strains, which the peak strain reductions will apply to. @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// protected virtual double DifficultyMultiplier => 1.06; - protected OsuStrainDecaySkill(Mod[] mods) + protected OsuStrainSkill(Mod[] mods) : base(mods) { } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 78d1438923..f0eb199e5f 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Represents the skill required to press keys with regards to keeping up with the speed at which objects need to be hit. /// - public class Speed : OsuStrainDecaySkill + public class Speed : OsuStrainSkill { private const double single_spacing_threshold = 125; From 97d5b80834568d76ca423cf876aaf9955681a72f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:18:21 +0900 Subject: [PATCH 158/366] Fix joining with incorrect password --- .../Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index 2d94b2328d..776307e20e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerClient multiplayerClient { get; set; } public override void CreateRoom(Room room, Action onSuccess = null, Action onError = null) - => base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), onError); + => base.CreateRoom(room, r => joinMultiplayerRoom(r, room.Password.Value, onSuccess, onError), onError); public override void JoinRoom(Room room, string password = null, Action onSuccess = null, Action onError = null) { From 352949069a4a3130c8db14ea8412ac11c93d57aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:36:43 +0900 Subject: [PATCH 159/366] Move filter to LoungeSubScreen --- .../TestSceneLoungeRoomsContainer.cs | 10 ++++----- .../Multiplayer/TestSceneMultiplayer.cs | 22 +++++++++++-------- .../Components/ListingPollingComponent.cs | 10 +++++---- .../Lounge/Components/RoomsContainer.cs | 9 ++++---- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 15 ++++++------- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 4 ---- ...stRequestHandlingMultiplayerRoomManager.cs | 5 ----- .../IOnlinePlayTestSceneDependencies.cs | 6 ----- .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 2 -- .../OnlinePlayTestSceneDependencies.cs | 4 ---- 10 files changed, 35 insertions(+), 52 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index f3d961a646..7e822f898e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -115,11 +115,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("4 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 4); - AddStep("filter one room", () => container.Filter(new FilterCriteria { SearchString = "1" })); + AddStep("filter one room", () => container.Filter.Value = new FilterCriteria { SearchString = "1" }); AddUntilStep("1 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 1); - AddStep("remove filter", () => container.Filter(null)); + AddStep("remove filter", () => container.Filter.Value = null); AddUntilStep("4 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 4); } @@ -131,13 +131,13 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add rooms", () => RoomManager.AddRooms(3, new CatchRuleset().RulesetInfo)); // Todo: What even is this case...? - AddStep("set empty filter criteria", () => container.Filter(null)); + AddStep("set empty filter criteria", () => container.Filter.Value = null); AddUntilStep("5 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 5); - AddStep("filter osu! rooms", () => container.Filter(new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo })); + AddStep("filter osu! rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo }); AddUntilStep("2 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 2); - AddStep("filter catch rooms", () => container.Filter(new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo })); + AddStep("filter catch rooms", () => container.Filter.Value = new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo }); AddUntilStep("3 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 3); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 08b3fb98a8..cf2f2f259e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -132,11 +132,9 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestExitMidJoin() { - Room room = null; - AddStep("create room", () => { - room = new Room + multiplayerScreen.RoomManager.AddRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -147,14 +145,16 @@ namespace osu.Game.Tests.Visual.Multiplayer Ruleset = { Value = new OsuRuleset().RulesetInfo }, } } - }; + }); }); - AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria()); + AddStep("refresh rooms", () => this.ChildrenOfType().Single().UpdateFilter()); + AddUntilStep("wait for room", () => this.ChildrenOfType().Any()); + AddStep("select room", () => InputManager.Key(Key.Down)); - AddStep("join room and immediately exit", () => + AddStep("join room and immediately exit select", () => { - multiplayerScreen.ChildrenOfType().Single().Open(room); + InputManager.Key(Key.Enter); Schedule(() => Stack.CurrentScreen.Exit()); }); } @@ -178,7 +178,9 @@ namespace osu.Game.Tests.Visual.Multiplayer }); }); - AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria()); + AddStep("refresh rooms", () => this.ChildrenOfType().Single().UpdateFilter()); + AddUntilStep("wait for room", () => this.ChildrenOfType().Any()); + AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("join room", () => InputManager.Key(Key.Enter)); @@ -226,7 +228,9 @@ namespace osu.Game.Tests.Visual.Multiplayer }); }); - AddStep("refresh rooms", () => multiplayerScreen.RoomManager.Filter.Value = new FilterCriteria()); + AddStep("refresh rooms", () => this.ChildrenOfType().Single().UpdateFilter()); + AddUntilStep("wait for room", () => this.ChildrenOfType().Any()); + AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("join room", () => InputManager.Key(Key.Enter)); diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index bc6480d05e..1387b5a671 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -18,8 +18,7 @@ namespace osu.Game.Screens.OnlinePlay.Components public IBindable InitialRoomsReceived => initialRoomsReceived; private readonly Bindable initialRoomsReceived = new Bindable(); - [Resolved] - private Bindable currentFilter { get; set; } + public readonly Bindable Filter = new Bindable(); [Resolved] private Bindable selectedRoom { get; set; } @@ -27,7 +26,7 @@ namespace osu.Game.Screens.OnlinePlay.Components [BackgroundDependencyLoader] private void load() { - currentFilter.BindValueChanged(_ => + Filter.BindValueChanged(_ => { RoomManager.ClearRooms(); initialRoomsReceived.Value = false; @@ -44,10 +43,13 @@ namespace osu.Game.Screens.OnlinePlay.Components if (!API.IsLoggedIn) return base.Poll(); + if (Filter.Value == null) + return base.Poll(); + var tcs = new TaskCompletionSource(); pollReq?.Cancel(); - pollReq = new GetRoomsRequest(currentFilter.Value.Status, currentFilter.Value.Category); + pollReq = new GetRoomsRequest(Filter.Value.Status, Filter.Value.Category); pollReq.Success += result => { diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 46d9850fde..e243477a8c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -30,8 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public IReadOnlyList Rooms => roomFlow.FlowingChildren.Cast().ToArray(); - [Resolved(CanBeNull = true)] - private Bindable filter { get; set; } + public readonly Bindable Filter = new Bindable(); [Resolved] private Bindable selectedRoom { get; set; } @@ -74,7 +73,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components rooms.BindTo(roomManager.Rooms); - filter?.BindValueChanged(criteria => Filter(criteria.NewValue)); + Filter?.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true); selectedRoom.BindValueChanged(selection => { @@ -85,7 +84,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void updateSelection() => roomFlow.Children.ForEach(r => r.State = r.Room == selectedRoom.Value ? SelectionState.Selected : SelectionState.NotSelected); - public void Filter(FilterCriteria criteria) + private void applyFilterCriteria(FilterCriteria criteria) { roomFlow.Children.ForEach(r => { @@ -126,7 +125,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components roomFlow.Add(new DrawableRoom(room)); } - Filter(filter?.Value); + applyFilterCriteria(Filter?.Value); updateSelection(); } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index bd2648791c..3e8d07d002 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -56,9 +56,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [Resolved(CanBeNull = true)] private OngoingOperationTracker ongoingOperationTracker { get; set; } - [Resolved(CanBeNull = true)] - private Bindable filter { get; set; } - [Resolved] private IBindable ruleset { get; set; } @@ -68,6 +65,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [CanBeNull] private LeasedBindable selectionLease; + private readonly Bindable filter = new Bindable(new FilterCriteria()); private readonly IBindable operationInProgress = new Bindable(); private readonly IBindable isIdle = new BindableBool(); private LoadingLayer loadingLayer; @@ -81,13 +79,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); - filter ??= new Bindable(new FilterCriteria()); - OsuScrollContainer scrollContainer; InternalChildren = new Drawable[] { - ListingPollingComponent = CreatePollingComponent(), + ListingPollingComponent = CreatePollingComponent().With(c => c.Filter.BindTarget = filter), loadingLayer = new LoadingLayer(true), new Container { @@ -161,7 +157,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { RelativeSizeAxes = Axes.Both, ScrollbarOverlapsContent = false, - Child = roomsContainer = new RoomsContainer() + Child = roomsContainer = new RoomsContainer + { + Filter = { BindTarget = filter } + } }, } }, @@ -202,7 +201,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge #region Filtering - protected void UpdateFilter() => Scheduler.AddOnce(updateFilter); + public void UpdateFilter() => Scheduler.AddOnce(updateFilter); private ScheduledDelegate scheduledFilterUpdate; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 183b7e51f9..e5962db608 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -20,7 +20,6 @@ using osu.Game.Overlays; using osu.Game.Screens.Menu; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -49,9 +48,6 @@ namespace osu.Game.Screens.OnlinePlay [Cached] private readonly Bindable selectedRoom = new Bindable(); - [Cached] - private readonly Bindable currentFilter = new Bindable(new FilterCriteria()); - [Cached] private readonly OngoingOperationTracker ongoingOperationTracker = new OngoingOperationTracker(); diff --git a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs index 2e56c8a094..31b59be61e 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs @@ -5,14 +5,12 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Components; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; namespace osu.Game.Tests.Visual.Multiplayer @@ -32,9 +30,6 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private OsuGameBase game { get; set; } - [Cached] - public readonly Bindable Filter = new Bindable(new FilterCriteria()); - public new readonly List Rooms = new List(); private int currentRoomId; diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs index 6e1e831d9b..71acefb158 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs @@ -4,7 +4,6 @@ using osu.Framework.Bindables; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { @@ -23,11 +22,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// IRoomManager RoomManager { get; } - /// - /// The cached . - /// - Bindable Filter { get; } - /// /// The cached . /// diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 997c910dd4..8716646074 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { @@ -20,7 +19,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay { public Bindable SelectedRoom => OnlinePlayDependencies?.SelectedRoom; public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager; - public Bindable Filter => OnlinePlayDependencies?.Filter; public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies?.OngoingOperationTracker; public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies?.AvailabilityTracker; diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index 05ba509a73..e39711b7ce 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { @@ -20,7 +19,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay { public Bindable SelectedRoom { get; } public IRoomManager RoomManager { get; } - public Bindable Filter { get; } public OngoingOperationTracker OngoingOperationTracker { get; } public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; } @@ -36,7 +34,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay { SelectedRoom = new Bindable(); RoomManager = CreateRoomManager(); - Filter = new Bindable(new FilterCriteria()); OngoingOperationTracker = new OngoingOperationTracker(); AvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker(); @@ -44,7 +41,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay CacheAs(SelectedRoom); CacheAs(RoomManager); - CacheAs(Filter); CacheAs(OngoingOperationTracker); CacheAs(AvailabilityTracker); CacheAs(new OverlayColourProvider(OverlayColourScheme.Plum)); From c4a42c4db007af794104c65c8c768506eb4f5b12 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:36:59 +0900 Subject: [PATCH 160/366] Fix BasicTestRoomManager overriding rooms --- .../Tests/Visual/OnlinePlay/BasicTestRoomManager.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index d7c5a0a0e4..55fbb9f1a6 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -28,6 +28,8 @@ namespace osu.Game.Tests.Visual.OnlinePlay IBindableList IRoomManager.Rooms => Rooms; + private int currentRoomId; + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1; @@ -76,9 +78,9 @@ namespace osu.Game.Tests.Visual.OnlinePlay { var room = new Room { - RoomID = { Value = i }, - Position = { Value = i }, - Name = { Value = $"Room {i}" }, + RoomID = { Value = currentRoomId }, + Position = { Value = currentRoomId }, + Name = { Value = $"Room {currentRoomId}" }, Host = { Value = new User { Username = "Host" } }, EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal }, @@ -101,6 +103,8 @@ namespace osu.Game.Tests.Visual.OnlinePlay } CreateRoom(room); + + currentRoomId++; } } } From 1e282432c90397d976164da3f9e03b99876199da Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:40:25 +0900 Subject: [PATCH 161/366] Fix password in a better way --- osu.Game/Screens/OnlinePlay/Components/RoomManager.cs | 3 ++- .../Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index 43bf3a2ce5..3b6c1c8be0 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -60,7 +60,8 @@ namespace osu.Game.Screens.OnlinePlay.Components AddOrUpdateRoom(result); room.CopyFrom(result); // Also copy back to the source model, since this is likely to have been stored elsewhere. - onSuccess?.Invoke(result); + // The server may not contain all properties (such as password), so invoke success with the given room. + onSuccess?.Invoke(room); }; req.Failure += exception => diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index 776307e20e..2d94b2328d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerClient multiplayerClient { get; set; } public override void CreateRoom(Room room, Action onSuccess = null, Action onError = null) - => base.CreateRoom(room, r => joinMultiplayerRoom(r, room.Password.Value, onSuccess, onError), onError); + => base.CreateRoom(room, r => joinMultiplayerRoom(r, r.Password.Value, onSuccess, onError), onError); public override void JoinRoom(Room room, string password = null, Action onSuccess = null, Action onError = null) { From b672d4b9366d0a695b8085b649c91c037b59878f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:42:17 +0900 Subject: [PATCH 162/366] Refactor RequestHandlingMultiplayerRoomManager to avoid confusion --- .../Multiplayer/TestSceneMultiplayer.cs | 6 +++--- .../Multiplayer/TestMultiplayerClient.cs | 4 ++-- ...stRequestHandlingMultiplayerRoomManager.cs | 20 +++++++------------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index cf2f2f259e..8b96f5dc80 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddRoom(new Room + multiplayerScreen.RoomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -164,7 +164,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddRoom(new Room + multiplayerScreen.RoomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -213,7 +213,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddRoom(new Room + multiplayerScreen.RoomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Password = { Value = "password" }, diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index f2da66d666..2c0ca0b872 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -127,7 +127,7 @@ namespace osu.Game.Tests.Visual.Multiplayer protected override Task JoinRoom(long roomId, string? password = null) { - var apiRoom = roomManager.Rooms.Single(r => r.RoomID.Value == roomId); + var apiRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == roomId); if (password != apiRoom.Password.Value) throw new InvalidOperationException("Invalid password."); @@ -260,7 +260,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { Debug.Assert(Room != null); - var apiRoom = roomManager.Rooms.Single(r => r.RoomID.Value == Room.RoomID); + var apiRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == Room.RoomID); var set = apiRoom.Playlist.FirstOrDefault(p => p.BeatmapID == beatmapId)?.Beatmap.Value.BeatmapSet ?? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId)?.BeatmapSet; diff --git a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs index 31b59be61e..41102ae7b5 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private OsuGameBase game { get; set; } - public new readonly List Rooms = new List(); + public readonly List ServerSideRooms = new List(); private int currentRoomId; private int currentPlaylistItemId; @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Multiplayer apiRoom.HasPassword.Value = !string.IsNullOrEmpty(createRoomRequest.Room.Password.Value); apiRoom.Password.Value = createRoomRequest.Room.Password.Value; - AddRoom(apiRoom); + AddServerSideRoom(apiRoom); var responseRoom = new APICreatedRoom(); responseRoom.CopyFrom(createResponseRoom(apiRoom, false)); @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual.Multiplayer case JoinRoomRequest joinRoomRequest: { - var room = Rooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value); + var room = ServerSideRooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value); if (joinRoomRequest.Password != room.Password.Value) { @@ -84,14 +84,14 @@ namespace osu.Game.Tests.Visual.Multiplayer case GetRoomsRequest getRoomsRequest: var roomsWithoutParticipants = new List(); - foreach (var r in Rooms) + foreach (var r in ServerSideRooms) roomsWithoutParticipants.Add(createResponseRoom(r, false)); getRoomsRequest.TriggerSuccess(roomsWithoutParticipants); return true; case GetRoomRequest getRoomRequest: - getRoomRequest.TriggerSuccess(createResponseRoom(Rooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true)); + getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true)); return true; case GetBeatmapSetRequest getBeatmapSetRequest: @@ -127,17 +127,15 @@ namespace osu.Game.Tests.Visual.Multiplayer }; } - public void AddRoom(Room room) + public void AddServerSideRoom(Room room) { room.RoomID.Value ??= currentRoomId++; for (int i = 0; i < room.Playlist.Count; i++) room.Playlist[i].ID = currentPlaylistItemId++; - Rooms.Add(room); + ServerSideRooms.Add(room); } - public new void RemoveRoom(Room room) => base.RemoveRoom(room); - private Room createResponseRoom(Room room, bool withParticipants) { var responseRoom = new Room(); @@ -147,9 +145,5 @@ namespace osu.Game.Tests.Visual.Multiplayer responseRoom.RecentParticipants.Clear(); return responseRoom; } - - public new void ClearRooms() => base.ClearRooms(); - - public new void Schedule(Action action) => base.Schedule(action); } } From 5214731dc1be8fdfe638143386319377ad839f54 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:45:10 +0900 Subject: [PATCH 163/366] Refactor test a bit --- .../Visual/Multiplayer/TestSceneMultiplayer.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 8b96f5dc80..e618b28f40 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -44,6 +44,8 @@ namespace osu.Game.Tests.Visual.Multiplayer private TestMultiplayer multiplayerScreen; private TestMultiplayerClient client; + private TestRequestHandlingMultiplayerRoomManager roomManager => multiplayerScreen.RoomManager; + [Cached(typeof(UserLookupCache))] private UserLookupCache lookupCache = new TestUserLookupCache(); @@ -68,7 +70,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("load dependencies", () => { - client = new TestMultiplayerClient(multiplayerScreen.RoomManager); + client = new TestMultiplayerClient(roomManager); // The screen gets suspended so it stops receiving updates. Child = client; @@ -134,7 +136,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddServerSideRoom(new Room + roomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -164,7 +166,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddServerSideRoom(new Room + roomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Playlist = @@ -213,7 +215,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room", () => { - multiplayerScreen.RoomManager.AddServerSideRoom(new Room + roomManager.AddServerSideRoom(new Room { Name = { Value = "Test Room" }, Password = { Value = "password" }, From f2340c6dac64d6c7dda95e84699586e35d81b964 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 09:48:33 +0900 Subject: [PATCH 164/366] Privatise mutable list --- .../Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs index 41102ae7b5..c3a944f93c 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs @@ -30,7 +30,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private OsuGameBase game { get; set; } - public readonly List ServerSideRooms = new List(); + public IReadOnlyList ServerSideRooms => serverSideRooms; + private readonly List serverSideRooms = new List(); private int currentRoomId; private int currentPlaylistItemId; @@ -133,7 +134,7 @@ namespace osu.Game.Tests.Visual.Multiplayer for (int i = 0; i < room.Playlist.Count; i++) room.Playlist[i].ID = currentPlaylistItemId++; - ServerSideRooms.Add(room); + serverSideRooms.Add(room); } private Room createResponseRoom(Room room, bool withParticipants) From 060ba0692d27a42507bfcc1fedae13e89f0c8408 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 17 Aug 2021 04:27:04 +0300 Subject: [PATCH 165/366] Add hash code support for `Mod` --- osu.Game/Rulesets/Mods/Mod.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index f2fd02c652..a99ddc6924 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -197,6 +197,18 @@ namespace osu.Game.Rulesets.Mods ModUtils.GetSettingUnderlyingValue(pair.Item2.GetValue(other)))); } + public override int GetHashCode() + { + var hashCode = new HashCode(); + + hashCode.Add(GetType()); + + foreach (var (_, prop) in this.GetSettingsSourceProperties()) + hashCode.Add(ModUtils.GetSettingUnderlyingValue(prop.GetValue(this))); + + return hashCode.ToHashCode(); + } + /// /// Reset all custom settings for this mod back to their defaults. /// From 0291cd5ae2eb269cf10512ce588ac5c762379ebd Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 17 Aug 2021 04:27:43 +0300 Subject: [PATCH 166/366] Consider mod equality in difficulty cache lookup rather than acronym --- osu.Game/Beatmaps/BeatmapDifficultyCache.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index 6ed623d0c0..8bc043a2e9 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -297,7 +297,7 @@ namespace osu.Game.Beatmaps public bool Equals(DifficultyCacheLookup other) => Beatmap.ID == other.Beatmap.ID && Ruleset.ID == other.Ruleset.ID - && OrderedMods.Select(m => m.Acronym).SequenceEqual(other.OrderedMods.Select(m => m.Acronym)); + && OrderedMods.SequenceEqual(other.OrderedMods); public override int GetHashCode() { @@ -307,7 +307,7 @@ namespace osu.Game.Beatmaps hashCode.Add(Ruleset.ID); foreach (var mod in OrderedMods) - hashCode.Add(mod.Acronym); + hashCode.Add(mod); return hashCode.ToHashCode(); } From 32ba5255558f6057831f87123135aa64955baab8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 17 Aug 2021 04:28:34 +0300 Subject: [PATCH 167/366] Track changes to mod settings in beatmap difficulty cache with 100ms debouncing --- osu.Game/Beatmaps/BeatmapDifficultyCache.cs | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index 8bc043a2e9..5025e4ad4b 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -14,6 +14,7 @@ using osu.Framework.Lists; using osu.Framework.Logging; using osu.Framework.Threading; using osu.Framework.Utils; +using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -56,12 +57,28 @@ namespace osu.Game.Beatmaps [Resolved] private Bindable> currentMods { get; set; } + private ModSettingChangeTracker modSettingChangeTracker; + private ScheduledDelegate debouncedModSettingsChange; + protected override void LoadComplete() { base.LoadComplete(); currentRuleset.BindValueChanged(_ => updateTrackedBindables()); - currentMods.BindValueChanged(_ => updateTrackedBindables(), true); + + currentMods.BindValueChanged(mods => + { + modSettingChangeTracker?.Dispose(); + + updateTrackedBindables(); + + modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue); + modSettingChangeTracker.SettingChanged += _ => + { + debouncedModSettingsChange?.Cancel(); + debouncedModSettingsChange = Scheduler.AddDelayed(updateTrackedBindables, 100); + }; + }, true); } /// @@ -84,7 +101,7 @@ namespace osu.Game.Beatmaps /// Retrieves a bindable containing the star difficulty of a with a given and combination. /// /// - /// The bindable will not update to follow the currently-selected ruleset and mods. + /// The bindable will not update to follow the currently-selected ruleset and mods or its settings. /// /// The to get the difficulty of. /// The to get the difficulty with. If null, the 's ruleset is used. @@ -275,6 +292,8 @@ namespace osu.Game.Beatmaps { base.Dispose(isDisposing); + modSettingChangeTracker?.Dispose(); + cancelTrackedBindableUpdate(); updateScheduler?.Dispose(); } From b419ea716b307eb54fca5892024e5066b81920f0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 17 Aug 2021 04:29:15 +0300 Subject: [PATCH 168/366] Refactor beatmap info wedge to not fully refresh on star difficulty change Makes it look awkward when changing difficulty via mod settings for example. Now the changes should instead only affect the displayed components which consume it directly. --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 104 ++++++++++---------- 1 file changed, 54 insertions(+), 50 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 5b4e077100..678e7d5d73 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -21,6 +21,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Configuration; @@ -38,6 +39,8 @@ namespace osu.Game.Screens.Select public const float BORDER_THICKNESS = 2.5f; private const float shear_width = 36.75f; + private const float transition_duration = 250; + private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / SongSelect.WEDGE_HEIGHT, 0); [Resolved] @@ -46,11 +49,6 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable> mods { get; set; } - [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } - - private IBindable beatmapDifficulty; - protected Container DisplayedContent { get; private set; } protected WedgeInfoText Info { get; private set; } @@ -81,20 +79,18 @@ namespace osu.Game.Screens.Select { this.MoveToX(0, 800, Easing.OutQuint); this.RotateTo(0, 800, Easing.OutQuint); - this.FadeIn(250); + this.FadeIn(transition_duration); } protected override void PopOut() { this.MoveToX(-100, 800, Easing.In); this.RotateTo(10, 800, Easing.In); - this.FadeOut(500, Easing.In); + this.FadeOut(transition_duration * 2, Easing.In); } private WorkingBeatmap beatmap; - private CancellationTokenSource cancellationSource; - public WorkingBeatmap Beatmap { get => beatmap; @@ -103,12 +99,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); - beatmapDifficulty.BindValueChanged(_ => updateDisplay()); updateDisplay(); } @@ -128,7 +118,7 @@ namespace osu.Game.Screens.Select { State.Value = beatmap == null ? Visibility.Hidden : Visibility.Visible; - DisplayedContent?.FadeOut(250); + DisplayedContent?.FadeOut(transition_duration); DisplayedContent?.Expire(); DisplayedContent = null; } @@ -147,7 +137,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { new BeatmapInfoWedgeBackground(beatmap), - Info = new WedgeInfoText(beatmap, ruleset.Value, mods.Value, beatmapDifficulty.Value ?? new StarDifficulty()), + Info = new WedgeInfoText(beatmap, ruleset.Value, mods.Value), } }, loaded => { @@ -160,12 +150,6 @@ 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; } @@ -174,6 +158,9 @@ namespace osu.Game.Screens.Select public BeatmapSetOnlineStatusPill StatusPill { get; private set; } public FillFlowContainer MapperContainer { get; private set; } + private DifficultyColourBar difficultyColourBar; + private StarRatingDisplay starRatingDisplay; + private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; private FillFlowContainer infoLabelContainer; @@ -182,20 +169,21 @@ namespace osu.Game.Screens.Select 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, IReadOnlyList mods, StarDifficulty difficulty) + public WedgeInfoText(WorkingBeatmap beatmap, RulesetInfo userRuleset, IReadOnlyList mods) { this.beatmap = beatmap; ruleset = userRuleset ?? beatmap.BeatmapInfo.Ruleset; this.mods = mods; - starDifficulty = difficulty; } + private CancellationTokenSource cancellationSource; + private IBindable starDifficulty; + [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(); @@ -207,7 +195,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { - new DifficultyColourBar(starDifficulty) + difficultyColourBar = new DifficultyColourBar { RelativeSizeAxes = Axes.Y, Width = 20, @@ -241,14 +229,15 @@ 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[] { - createStarRatingDisplay(starDifficulty).With(display => + starRatingDisplay = new StarRatingDisplay(default) { - display.Anchor = Anchor.TopRight; - display.Origin = Anchor.TopRight; - display.Shear = -wedged_container_shear; - }), + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -wedged_container_shear, + Alpha = 0f, + }, StatusPill = new BeatmapSetOnlineStatusPill { Anchor = Anchor.TopRight, @@ -304,6 +293,15 @@ namespace osu.Game.Screens.Select titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); + starDifficulty = difficultyCache.GetBindableDifficulty(beatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); + starDifficulty.BindValueChanged(s => + { + difficultyColourBar.Current.Value = s.NewValue ?? default; + + starRatingDisplay.FadeIn(transition_duration); + starRatingDisplay.Current.Value = s.NewValue ?? default; + }); + // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) StatusPill.Hide(); @@ -311,13 +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; @@ -429,6 +420,7 @@ namespace osu.Game.Screens.Select { base.Dispose(isDisposing); settingChangeTracker?.Dispose(); + cancellationSource?.Cancel(); } public class InfoLabel : Container, IHasTooltip @@ -490,41 +482,53 @@ namespace osu.Game.Screens.Select } } - private class DifficultyColourBar : Container + public class DifficultyColourBar : Container, IHasCurrentValue { - private readonly StarDifficulty difficulty; + private readonly BindableWithCurrent current = new BindableWithCurrent(); - public DifficultyColourBar(StarDifficulty difficulty) + public Bindable Current { - this.difficulty = difficulty; + get => current.Current; + set => current.Current = value; } + [Resolved] + private OsuColour colours { get; set; } + [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { const float full_opacity_ratio = 0.7f; - var difficultyColour = colours.ForStarDifficulty(difficulty.Stars); - 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, } }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(c => + { + this.FadeColour(colours.ForStarDifficulty(c.NewValue.Stars), transition_duration, Easing.OutQuint); + }, true); + + FinishTransforms(true); + } } } } From a329216ff350d2f84e66d48e8a4fdbf03e4d9dd0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 17 Aug 2021 04:28:07 +0300 Subject: [PATCH 169/366] Convert beatmap difficulty test into test scene and extend coverage --- .../Beatmaps/BeatmapDifficultyCacheTest.cs | 56 ------- .../TestSceneBeatmapDifficultyCache.cs | 158 ++++++++++++++++++ 2 files changed, 158 insertions(+), 56 deletions(-) delete mode 100644 osu.Game.Tests/Beatmaps/BeatmapDifficultyCacheTest.cs create mode 100644 osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs diff --git a/osu.Game.Tests/Beatmaps/BeatmapDifficultyCacheTest.cs b/osu.Game.Tests/Beatmaps/BeatmapDifficultyCacheTest.cs deleted file mode 100644 index d407c0663f..0000000000 --- a/osu.Game.Tests/Beatmaps/BeatmapDifficultyCacheTest.cs +++ /dev/null @@ -1,56 +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 NUnit.Framework; -using osu.Game.Beatmaps; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Mods; - -namespace osu.Game.Tests.Beatmaps -{ - [TestFixture] - public class BeatmapDifficultyCacheTest - { - [Test] - public void TestKeyEqualsWithDifferentModInstances() - { - var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); - var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); - - Assert.That(key1, Is.EqualTo(key2)); - } - - [Test] - public void TestKeyEqualsWithDifferentModOrder() - { - var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); - var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHidden(), new OsuModHardRock() }); - - Assert.That(key1, Is.EqualTo(key2)); - } - - [TestCase(1.3, DifficultyRating.Easy)] - [TestCase(1.993, DifficultyRating.Easy)] - [TestCase(1.998, DifficultyRating.Normal)] - [TestCase(2.4, DifficultyRating.Normal)] - [TestCase(2.693, DifficultyRating.Normal)] - [TestCase(2.698, DifficultyRating.Hard)] - [TestCase(3.5, DifficultyRating.Hard)] - [TestCase(3.993, DifficultyRating.Hard)] - [TestCase(3.997, DifficultyRating.Insane)] - [TestCase(5.0, DifficultyRating.Insane)] - [TestCase(5.292, DifficultyRating.Insane)] - [TestCase(5.297, DifficultyRating.Expert)] - [TestCase(6.2, DifficultyRating.Expert)] - [TestCase(6.493, DifficultyRating.Expert)] - [TestCase(6.498, DifficultyRating.ExpertPlus)] - [TestCase(8.3, DifficultyRating.ExpertPlus)] - public void TestDifficultyRatingMapping(double starRating, DifficultyRating expectedBracket) - { - var actualBracket = BeatmapDifficultyCache.GetDifficultyRating(starRating); - - Assert.AreEqual(expectedBracket, actualBracket); - } - } -} diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs new file mode 100644 index 0000000000..b6ba5b748a --- /dev/null +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -0,0 +1,158 @@ +// 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 System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Tests.Beatmaps.IO; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Beatmaps +{ + [HeadlessTest] + public class TestSceneBeatmapDifficultyCache : OsuTestScene + { + public const double BASE_STARS = 5.55; + + private BeatmapSetInfo importedSet; + + [Resolved] + private BeatmapManager beatmaps { get; set; } + + private TestBeatmapDifficultyCache difficultyCache; + + private IBindable starDifficultyBindable; + private Queue> starDifficultyChangesQueue; + + [BackgroundDependencyLoader] + private void load(OsuGameBase osu) + { + importedSet = ImportBeatmapTest.LoadQuickOszIntoOsu(osu).Result; + } + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("setup difficulty cache", () => + { + SelectedMods.Value = Array.Empty(); + + Child = difficultyCache = new TestBeatmapDifficultyCache(); + + starDifficultyChangesQueue = new Queue>(); + starDifficultyBindable = difficultyCache.GetBindableDifficulty(importedSet.Beatmaps.First()); + starDifficultyBindable.BindValueChanged(starDifficultyChangesQueue.Enqueue); + }); + + AddAssert($"star difficulty -> {BASE_STARS}", () => + starDifficultyChangesQueue.Dequeue().NewValue?.Stars == BASE_STARS && + starDifficultyChangesQueue.Count == 0); + } + + [Test] + public void TestStarDifficultyChangesOnModSettings() + { + OsuModDoubleTime dt = null; + + AddStep("change selected mod to DT", () => SelectedMods.Value = new[] { dt = new OsuModDoubleTime { SpeedChange = { Value = 1.5 } } }); + AddAssert($"star difficulty -> {BASE_STARS + 1.5}", () => + starDifficultyChangesQueue.Dequeue().NewValue?.Stars == BASE_STARS + 1.5 && + starDifficultyChangesQueue.Count == 0); + + AddStep("change DT speed to 1.25", () => dt.SpeedChange.Value = 1.25); + AddAssert($"star difficulty -> {BASE_STARS + 1.25}", () => + starDifficultyChangesQueue.Dequeue().NewValue?.Stars == BASE_STARS + 1.25 && + starDifficultyChangesQueue.Count == 0); + + AddStep("change selected mod to NC", () => SelectedMods.Value = new[] { new OsuModNightcore { SpeedChange = { Value = 1.75 } } }); + AddAssert($"star difficulty -> {BASE_STARS + 1.75}", () => + starDifficultyChangesQueue.Dequeue().NewValue?.Stars == BASE_STARS + 1.75 && + starDifficultyChangesQueue.Count == 0); + } + + [Test] + public void TestKeyEqualsWithDifferentModInstances() + { + var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); + var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); + + Assert.That(key1, Is.EqualTo(key2)); + Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode())); + } + + [Test] + public void TestKeyEqualsWithDifferentModOrder() + { + var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() }); + var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHidden(), new OsuModHardRock() }); + + Assert.That(key1, Is.EqualTo(key2)); + Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode())); + } + + [Test] + public void TestKeyDoesntEqualWithDifferentModSettings() + { + var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.1 } } }); + var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.9 } } }); + + Assert.That(key1, Is.Not.EqualTo(key2)); + Assert.That(key1.GetHashCode(), Is.Not.EqualTo(key2.GetHashCode())); + } + + [Test] + public void TestKeyEqualWithMatchingModSettings() + { + var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } }); + var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } }); + + Assert.That(key1, Is.EqualTo(key2)); + Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode())); + } + + [TestCase(1.3, DifficultyRating.Easy)] + [TestCase(1.993, DifficultyRating.Easy)] + [TestCase(1.998, DifficultyRating.Normal)] + [TestCase(2.4, DifficultyRating.Normal)] + [TestCase(2.693, DifficultyRating.Normal)] + [TestCase(2.698, DifficultyRating.Hard)] + [TestCase(3.5, DifficultyRating.Hard)] + [TestCase(3.993, DifficultyRating.Hard)] + [TestCase(3.997, DifficultyRating.Insane)] + [TestCase(5.0, DifficultyRating.Insane)] + [TestCase(5.292, DifficultyRating.Insane)] + [TestCase(5.297, DifficultyRating.Expert)] + [TestCase(6.2, DifficultyRating.Expert)] + [TestCase(6.493, DifficultyRating.Expert)] + [TestCase(6.498, DifficultyRating.ExpertPlus)] + [TestCase(8.3, DifficultyRating.ExpertPlus)] + public void TestDifficultyRatingMapping(double starRating, DifficultyRating expectedBracket) + { + var actualBracket = BeatmapDifficultyCache.GetDifficultyRating(starRating); + + Assert.AreEqual(expectedBracket, actualBracket); + } + + private class TestBeatmapDifficultyCache : BeatmapDifficultyCache + { + protected override Task ComputeValueAsync(DifficultyCacheLookup lookup, CancellationToken token = default) + { + var rateAdjust = lookup.OrderedMods.OfType().SingleOrDefault(); + if (rateAdjust != null) + return Task.FromResult(new StarDifficulty(BASE_STARS + rateAdjust.SpeedChange.Value, 0)); + + return Task.FromResult(new StarDifficulty(BASE_STARS, 0)); + } + } + } +} From eb6c6830bcd977430a710efaf21e65f38fa2c5f9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 17 Aug 2021 05:45:03 +0300 Subject: [PATCH 170/366] Add visual test slider for changing star difficulty in beatmap wedge --- .../Visual/SongSelect/TestSceneBeatmapInfoWedge.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index a416fd4daf..2b38c4f936 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; @@ -65,6 +66,12 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("show", () => { infoWedge.Show(); }); + AddSliderStep("change star difficulty", 0, 11.9, 5.55, v => + { + foreach (var hasCurrentValue in infoWedge.Info.ChildrenOfType>()) + hasCurrentValue.Current.Value = new StarDifficulty(v, 0); + }); + foreach (var rulesetInfo in rulesets.AvailableRulesets) { var instance = rulesetInfo.CreateInstance(); From adb4fd5a2bcdf08ebc6bfe47bc45ba7c41e2c8c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 12:31:33 +0900 Subject: [PATCH 171/366] Load only sections content asynchronously, showing the header initially --- osu.Game/Overlays/SettingsPanel.cs | 150 ++++++++++++++++------------- 1 file changed, 82 insertions(+), 68 deletions(-) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 6593b6cb1e..fea797287e 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -61,6 +62,10 @@ namespace osu.Game.Overlays private LoadingLayer loading; + private readonly List loadableSections = new List(); + + private Task sectionsLoadingTask; + protected SettingsPanel(bool showSidebar) { this.showSidebar = showSidebar; @@ -96,7 +101,7 @@ namespace osu.Game.Overlays } }; - SectionsContainer = new SettingsSectionsContainer + Add(SectionsContainer = new SettingsSectionsContainer { Masking = true, RelativeSizeAxes = Axes.Both, @@ -113,8 +118,8 @@ namespace osu.Game.Overlays Bottom = 20 }, }, - Footer = CreateFooter() - }; + Footer = CreateFooter().With(f => f.Alpha = 0) + }); if (showSidebar) { @@ -124,76 +129,13 @@ namespace osu.Game.Overlays CreateSections()?.ForEach(AddSection); } - private void ensureContentLoaded() - { - if (SectionsContainer.LoadState > LoadState.NotLoaded) - return; - - LoadComponentAsync(SectionsContainer, d => - { - ContentContainer.Add(d); - d.FadeInFromZero(750, Easing.OutQuint); - loading.Hide(); - - searchTextBox.Current.BindValueChanged(term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue, true); - searchTextBox.TakeFocus(); - - if (Sidebar == null) - return; - - LoadComponentsAsync(createSidebarButtons(), buttons => - { - float delay = 0; - - foreach (var button in buttons) - { - Sidebar.Add(button); - - button.FadeOut() - .Delay(delay) - .FadeInFromZero(1000, Easing.OutQuint); - - delay += 30; - } - - SectionsContainer.SelectedSection.BindValueChanged(section => - { - if (selectedSidebarButton != null) - selectedSidebarButton.Selected = false; - - selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); - selectedSidebarButton.Selected = true; - }, true); - }); - }); - } - - private IEnumerable createSidebarButtons() - { - foreach (var section in SectionsContainer) - { - yield return new SidebarButton - { - Section = section, - Action = () => - { - if (!SectionsContainer.IsLoaded) - return; - - SectionsContainer.ScrollTo(section); - Sidebar.State = ExpandedState.Contracted; - }, - }; - } - } - protected void AddSection(SettingsSection section) { if (IsLoaded) // just to keep things simple. can be accommodated for if we ever need it. throw new InvalidOperationException("All sections must be added before the panel is loaded."); - SectionsContainer.Add(section); + loadableSections.Add(section); } protected virtual Drawable CreateHeader() => new Container(); @@ -210,7 +152,7 @@ namespace osu.Game.Overlays // this is done as there is still a brief stutter during load completion which is more visible if the transition is in progress. // the eventual goal would be to remove the need for this by splitting up load into smaller work pieces, or fixing the remaining // load complete overheads. - Scheduler.AddDelayed(ensureContentLoaded, TRANSITION_LENGTH / 3); + Scheduler.AddDelayed(loadSections, TRANSITION_LENGTH / 3); Sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); @@ -250,6 +192,78 @@ namespace osu.Game.Overlays Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; } + private const double fade_in_duration = 1000; + + private void loadSections() + { + if (sectionsLoadingTask != null) + return; + + sectionsLoadingTask = LoadComponentsAsync(loadableSections, sections => + { + SectionsContainer.AddRange(sections); + SectionsContainer.Footer.FadeInFromZero(fade_in_duration, Easing.OutQuint); + SectionsContainer.SearchContainer.FadeInFromZero(fade_in_duration, Easing.OutQuint); + + loading.Hide(); + + searchTextBox.Current.BindValueChanged(term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue, true); + searchTextBox.TakeFocus(); + + loadSidebarButtons(); + }); + } + + private void loadSidebarButtons() + { + if (Sidebar == null) + return; + + LoadComponentsAsync(createSidebarButtons(), buttons => + { + float delay = 0; + + foreach (var button in buttons) + { + Sidebar.Add(button); + + button.FadeOut() + .Delay(delay) + .FadeInFromZero(fade_in_duration, Easing.OutQuint); + + delay += 40; + } + + SectionsContainer.SelectedSection.BindValueChanged(section => + { + if (selectedSidebarButton != null) + selectedSidebarButton.Selected = false; + + selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); + selectedSidebarButton.Selected = true; + }, true); + }); + } + + private IEnumerable createSidebarButtons() + { + foreach (var section in SectionsContainer) + { + yield return new SidebarButton + { + Section = section, + Action = () => + { + if (!SectionsContainer.IsLoaded) + return; + + SectionsContainer.ScrollTo(section); + Sidebar.State = ExpandedState.Contracted; + }, + }; + } + } + private class NonMaskedContent : Container { // masking breaks the pan-out transform with nested sub-settings panels. From 212842c5373bda3b369e1ea9d9d7535637634684 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 12:38:44 +0900 Subject: [PATCH 172/366] Fix initial `LayoutSettings` animation in a more reliable way --- .../Sections/Graphics/LayoutSettings.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 277e344d84..d29f5fef39 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -175,16 +175,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingMode.BindValueChanged(mode => { scalingSettings.ClearTransforms(); - scalingSettings.AutoSizeDuration = transition_duration; scalingSettings.AutoSizeEasing = Easing.OutQuint; - scalingSettings.AutoSizeAxes = mode.NewValue != ScalingMode.Off ? Axes.Y : Axes.None; - if (mode.NewValue == ScalingMode.Off) - scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); + updateScalingModeVisibility(); + }); - scalingSettings.ForEach(s => s.TransferValueOnCommit = mode.NewValue == ScalingMode.Everything); - }, true); + // initial update bypasses transforms + updateScalingModeVisibility(); void updateResolutionDropdown() { @@ -193,6 +191,15 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics else resolutionDropdown.Hide(); } + + void updateScalingModeVisibility() + { + if (scalingMode.Value == ScalingMode.Off) + scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); + + scalingSettings.AutoSizeAxes = scalingMode.Value != ScalingMode.Off ? Axes.Y : Axes.None; + scalingSettings.ForEach(s => s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything); + } } private void bindPreviewEvent(Bindable bindable) From bc86bafc0898b2d6d288ef81b2f3a10f4eb1331d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 12:48:30 +0900 Subject: [PATCH 173/366] Fix `RestoreDefaultValueButton`'s colour weirdness --- osu.Game/Graphics/UserInterface/OsuButton.cs | 1 + osu.Game/Overlays/RestoreDefaultValueButton.cs | 11 ++++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index cd9ca9f87f..82a3e73b84 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -36,6 +36,7 @@ namespace osu.Game.Graphics.UserInterface public Color4 BackgroundColour { + get => backgroundColour ?? Color4.White; set { backgroundColour = value; diff --git a/osu.Game/Overlays/RestoreDefaultValueButton.cs b/osu.Game/Overlays/RestoreDefaultValueButton.cs index 62f5222012..87a294cc10 100644 --- a/osu.Game/Overlays/RestoreDefaultValueButton.cs +++ b/osu.Game/Overlays/RestoreDefaultValueButton.cs @@ -45,8 +45,6 @@ namespace osu.Game.Overlays } } - private Color4 buttonColour; - private bool hovering; public RestoreDefaultValueButton() @@ -61,12 +59,11 @@ namespace osu.Game.Overlays private void load(OsuColour colour) { BackgroundColour = colour.Yellow; - buttonColour = colour.Yellow; Content.Width = 0.33f; Content.CornerRadius = 3; Content.EdgeEffect = new EdgeEffectParameters { - Colour = buttonColour.Opacity(0.1f), + Colour = BackgroundColour.Opacity(0.1f), Type = EdgeEffectType.Glow, Radius = 2, }; @@ -87,7 +84,7 @@ namespace osu.Game.Overlays // avoid unnecessary transforms on first display. Alpha = currentAlpha; - Colour = currentColour; + Background.Colour = currentColour; } public LocalisableString TooltipText => "revert to default"; @@ -108,7 +105,7 @@ namespace osu.Game.Overlays public void UpdateState() => Scheduler.AddOnce(updateState); private float currentAlpha => current.IsDefault ? 0f : hovering && !current.Disabled ? 1f : 0.65f; - private ColourInfo currentColour => current.Disabled ? Color4.Gray : buttonColour; + private ColourInfo currentColour => current.Disabled ? Color4.Gray : BackgroundColour; private void updateState() { @@ -116,7 +113,7 @@ namespace osu.Game.Overlays return; this.FadeTo(currentAlpha, 200, Easing.OutQuint); - this.FadeColour(currentColour, 200, Easing.OutQuint); + Background.FadeColour(currentColour, 200, Easing.OutQuint); } } } From 1e2c0031d7473302f2f39bee34f4e4d2d4088048 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 13:34:44 +0900 Subject: [PATCH 174/366] Remove unused usings --- osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs index dbac132faf..73bab31e82 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; -using System.Linq; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; From 081524b6c862af923b6f1084e3182f0abd85f59f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 13:44:21 +0900 Subject: [PATCH 175/366] Privatise setters --- osu.Game/Screens/Play/PlayerLoader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index a6592e4d24..969527a758 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -46,14 +46,14 @@ namespace osu.Game.Screens.Play protected override bool PlayResumeSound => false; - protected BeatmapMetadataDisplay MetadataInfo; + protected BeatmapMetadataDisplay MetadataInfo { get; private set; } /// /// A fill flow containing the player settings groups, exposed for the ability to hide it from inheritors of the player loader. /// - protected FillFlowContainer PlayerSettings; + protected FillFlowContainer PlayerSettings { get; private set; } - protected VisualSettings VisualSettings; + protected VisualSettings VisualSettings { get; private set; } protected Task LoadTask { get; private set; } From 3a7b9bf096d1b3c259c8db8c7c44f9c99dc44ff5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 17 Aug 2021 08:56:49 +0300 Subject: [PATCH 176/366] Fix `MatchSettingsOverlay` not resetting focus on hide properly --- .../Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs index 2676453a7e..62a968b508 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs @@ -41,11 +41,13 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected override void PopIn() { + base.PopIn(); Settings.MoveToY(0, TRANSITION_DURATION, Easing.OutQuint); } protected override void PopOut() { + base.PopOut(); Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine); } From 82eddeffefe1a33035cd44a7a7435c650c316d00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 16:13:45 +0900 Subject: [PATCH 177/366] Add `LocalUserPlayInfo` interface to convey common information about player status --- osu.Desktop/Windows/GameplayWinKeyBlocker.cs | 8 ++++---- osu.Game/Input/ConfineMouseTracker.cs | 5 +++-- osu.Game/OsuGame.cs | 4 +++- osu.Game/Performance/HighPerformanceSession.cs | 5 +++-- osu.Game/Screens/Play/ILocalUserPlayInfo.cs | 17 +++++++++++++++++ osu.Game/Screens/Play/Player.cs | 4 +++- 6 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 osu.Game/Screens/Play/ILocalUserPlayInfo.cs diff --git a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs index efc3f21149..dbfd170ea1 100644 --- a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs +++ b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs @@ -5,23 +5,23 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Platform; -using osu.Game; using osu.Game.Configuration; +using osu.Game.Screens.Play; namespace osu.Desktop.Windows { public class GameplayWinKeyBlocker : Component { private Bindable disableWinKey; - private Bindable localUserPlaying; + private IBindable localUserPlaying; [Resolved] private GameHost host { get; set; } [BackgroundDependencyLoader] - private void load(OsuGame game, OsuConfigManager config) + private void load(ILocalUserPlayInfo localUserInfo, OsuConfigManager config) { - localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); + localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy(); localUserPlaying.BindValueChanged(_ => updateBlocking()); disableWinKey = config.GetBindable(OsuSetting.GameplayDisableWinKey); diff --git a/osu.Game/Input/ConfineMouseTracker.cs b/osu.Game/Input/ConfineMouseTracker.cs index 75d9c8debb..d2bf953dbc 100644 --- a/osu.Game/Input/ConfineMouseTracker.cs +++ b/osu.Game/Input/ConfineMouseTracker.cs @@ -7,6 +7,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Game.Configuration; +using osu.Game.Screens.Play; namespace osu.Game.Input { @@ -24,14 +25,14 @@ namespace osu.Game.Input private IBindable localUserPlaying; [BackgroundDependencyLoader] - private void load(OsuGame game, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager) + private void load(ILocalUserPlayInfo localUserInfo, FrameworkConfigManager frameworkConfigManager, OsuConfigManager osuConfigManager) { frameworkConfineMode = frameworkConfigManager.GetBindable(FrameworkSetting.ConfineMouseMode); frameworkWindowMode = frameworkConfigManager.GetBindable(FrameworkSetting.WindowMode); frameworkWindowMode.BindValueChanged(_ => updateConfineMode()); osuConfineMode = osuConfigManager.GetBindable(OsuSetting.ConfineMouseMode); - localUserPlaying = game.LocalUserPlaying.GetBoundCopy(); + localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy(); osuConfineMode.ValueChanged += _ => updateConfineMode(); localUserPlaying.BindValueChanged(_ => updateConfineMode(), true); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fb682e0909..0db63df69b 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -62,7 +62,7 @@ namespace osu.Game /// The full osu! experience. Builds on top of to add menus and binding logic /// for initial components that are generally retrieved via DI. /// - public class OsuGame : OsuGameBase, IKeyBindingHandler + public class OsuGame : OsuGameBase, IKeyBindingHandler, ILocalUserPlayInfo { /// /// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications). @@ -1085,5 +1085,7 @@ namespace osu.Game if (newScreen == null) Exit(); } + + IBindable ILocalUserPlayInfo.IsPlaying => LocalUserPlaying; } } diff --git a/osu.Game/Performance/HighPerformanceSession.cs b/osu.Game/Performance/HighPerformanceSession.cs index 661c1046f1..3ef0e0bf93 100644 --- a/osu.Game/Performance/HighPerformanceSession.cs +++ b/osu.Game/Performance/HighPerformanceSession.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Screens.Play; namespace osu.Game.Performance { @@ -12,9 +13,9 @@ namespace osu.Game.Performance private readonly IBindable localUserPlaying = new Bindable(); [BackgroundDependencyLoader] - private void load(OsuGame game) + private void load(ILocalUserPlayInfo localUserInfo) { - localUserPlaying.BindTo(game.LocalUserPlaying); + localUserPlaying.BindTo(localUserInfo.IsPlaying); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs new file mode 100644 index 0000000000..64c3f97305 --- /dev/null +++ b/osu.Game/Screens/Play/ILocalUserPlayInfo.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 osu.Framework.Bindables; + +namespace osu.Game.Screens.Play +{ + [Cached] + public interface ILocalUserPlayInfo + { + /// + /// Whether the local user is currently playing. + /// + public IBindable IsPlaying { get; } + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 09eaf1c543..5461c6ac6c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play { [Cached] [Cached(typeof(ISamplePlaybackDisabler))] - public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler + public abstract class Player : ScreenWithBeatmapBackground, ISamplePlaybackDisabler, ILocalUserPlayInfo { /// /// The delay upon completion of the beatmap before displaying the results screen. @@ -1052,5 +1052,7 @@ namespace osu.Game.Screens.Play #endregion IBindable ISamplePlaybackDisabler.SamplePlaybackDisabled => samplePlaybackDisabled; + + IBindable ILocalUserPlayInfo.IsPlaying => LocalUserPlaying; } } From e3b29df29930e4e5f79072b4b762fad0f27fd31c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 14:39:08 +0900 Subject: [PATCH 178/366] Add test scene for `MultiplayerPlayer` --- .../Multiplayer/TestSceneMultiplayerPlayer.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs new file mode 100644 index 0000000000..80da7a7e5e --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs @@ -0,0 +1,38 @@ +// 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.Testing; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens.OnlinePlay.Multiplayer; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMultiplayerPlayer : MultiplayerTestScene + { + private MultiplayerPlayer player; + + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("set beatmap", () => + { + Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + }); + + AddStep("initialise gameplay", () => + { + Stack.Push(player = new MultiplayerPlayer(Client.CurrentMatchPlayingItem.Value, Client.Room?.Users.ToArray())); + }); + } + + [Test] + public void TestGameplay() + { + AddUntilStep("wait for gameplay start", () => player.LocalUserPlaying.Value); + } + } +} From 0d283aa6a348bef4702a7d1d3bf8010195c70098 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 14:39:22 +0900 Subject: [PATCH 179/366] Expose `LocalUserPlaying` from `Player` --- .../Visual/Gameplay/TestSceneOverlayActivation.cs | 2 -- osu.Game/Screens/Play/Player.cs | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs index 4fa4c00981..b308f3d7d8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs @@ -3,7 +3,6 @@ using System.Linq; using NUnit.Framework; -using osu.Framework.Bindables; using osu.Game.Overlays; using osu.Game.Rulesets; @@ -66,7 +65,6 @@ namespace osu.Game.Tests.Visual.Gameplay protected class OverlayTestPlayer : TestPlayer { public new OverlayActivation OverlayActivationMode => base.OverlayActivationMode.Value; - public new Bindable LocalUserPlaying => base.LocalUserPlaying; } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5461c6ac6c..59c7abb299 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -75,7 +75,9 @@ namespace osu.Game.Screens.Play private readonly Bindable storyboardReplacesBackground = new Bindable(); - protected readonly Bindable LocalUserPlaying = new Bindable(); + public IBindable LocalUserPlaying => localUserPlaying; + + private readonly Bindable localUserPlaying = new Bindable(); public int RestartCount; @@ -442,7 +444,7 @@ namespace osu.Game.Screens.Play { bool inGameplay = !DrawableRuleset.HasReplayLoaded.Value && !DrawableRuleset.IsPaused.Value && !breakTracker.IsBreakTime.Value; OverlayActivationMode.Value = inGameplay ? OverlayActivation.Disabled : OverlayActivation.UserTriggered; - LocalUserPlaying.Value = inGameplay; + localUserPlaying.Value = inGameplay; } private void updateSampleDisabledState() From 35b9f84c00efa0aacc6c01b0ecc00c129ac27a1d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 14:39:51 +0900 Subject: [PATCH 180/366] Expose `StandAloneChatDisplay.Textbox` --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 8b0caddbc6..160c620214 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -22,7 +22,7 @@ namespace osu.Game.Online.Chat { public readonly Bindable Channel = new Bindable(); - private readonly FocusedTextBox textbox; + protected readonly FocusedTextBox Textbox; protected ChannelManager ChannelManager; @@ -54,7 +54,7 @@ namespace osu.Game.Online.Chat if (postingTextbox) { - AddInternal(textbox = new FocusedTextBox + AddInternal(Textbox = new FocusedTextBox { RelativeSizeAxes = Axes.X, Height = textbox_height, @@ -65,7 +65,7 @@ namespace osu.Game.Online.Chat Origin = Anchor.BottomLeft, }); - textbox.OnCommit += postMessage; + Textbox.OnCommit += postMessage; } Channel.BindValueChanged(channelChanged); @@ -82,7 +82,7 @@ namespace osu.Game.Online.Chat private void postMessage(TextBox sender, bool newtext) { - var text = textbox.Text.Trim(); + var text = Textbox.Text.Trim(); if (string.IsNullOrWhiteSpace(text)) return; @@ -92,7 +92,7 @@ namespace osu.Game.Online.Chat else ChannelManager?.PostMessage(text, target: Channel.Value); - textbox.Text = string.Empty; + Textbox.Text = string.Empty; } protected virtual ChatLine CreateMessage(Message message) => new StandAloneMessage(message); From b82f92d7b8913d039cae235a94488047e293aec4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 14:57:38 +0900 Subject: [PATCH 181/366] Adjust background colours of textbox in chat display --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 160c620214..9d23a089df 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -30,6 +30,8 @@ namespace osu.Game.Online.Chat private readonly bool postingTextbox; + protected readonly Box Background; + private const float textbox_height = 30; /// @@ -44,7 +46,7 @@ namespace osu.Game.Online.Chat InternalChildren = new Drawable[] { - new Box + Background = new Box { Colour = Color4.Black, Alpha = 0.8f, @@ -54,7 +56,7 @@ namespace osu.Game.Online.Chat if (postingTextbox) { - AddInternal(Textbox = new FocusedTextBox + AddInternal(Textbox = new ChatTextBox { RelativeSizeAxes = Axes.X, Height = textbox_height, @@ -110,6 +112,17 @@ namespace osu.Game.Online.Chat AddInternal(drawableChannel); } + public class ChatTextBox : FocusedTextBox + { + protected override void LoadComplete() + { + base.LoadComplete(); + + BackgroundUnfocused = new Color4(10, 10, 10, 10); + BackgroundFocused = new Color4(10, 10, 10, 255); + } + } + public class StandAloneDrawableChannel : DrawableChannel { public Func CreateChatLineAction; From 30eee363dcac3226fa679853f4ed40d060643334 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 14:57:48 +0900 Subject: [PATCH 182/366] Add chat display during multiplayer gameplay --- .../Multiplayer/GameplayChatDisplay.cs | 62 +++++++++++++++++++ .../Multiplayer/MultiplayerPlayer.cs | 10 ++- 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs new file mode 100644 index 0000000000..5b33fa1844 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -0,0 +1,62 @@ +// 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.Game.Screens.OnlinePlay.Match.Components; +using osu.Game.Screens.Play; + +namespace osu.Game.Screens.OnlinePlay.Multiplayer +{ + public class GameplayChatDisplay : MatchChatDisplay + { + [Resolved] + private ILocalUserPlayInfo localUserInfo { get; set; } + + private IBindable localUserPlaying = new Bindable(); + + public Bindable Expanded = new Bindable(); + + private const float height = 100; + + public GameplayChatDisplay() + { + RelativeSizeAxes = Axes.X; + + Background.Alpha = 0.2f; + } + + private void expandedChanged(ValueChangedEvent expanded) + { + if (expanded.NewValue) + { + this.FadeIn(300, Easing.OutQuint); + this.ResizeHeightTo(height, 500, Easing.OutQuint); + } + else + { + this.FadeOut(300, Easing.OutQuint); + this.ResizeHeightTo(0, 500, Easing.OutQuint); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy(); + localUserPlaying.BindValueChanged(playing => + { + // for now let's never hold focus. this avoid misdirected gameplay keys entering chat. + // note that this is done within this callback as it triggers an un-focus as well. + Textbox.HoldFocus = false; + + // only hold focus (after sending a message) during breaks + Textbox.ReleaseFocusOnCommit = playing.NewValue; + }, true); + + Expanded.BindValueChanged(expandedChanged, true); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index ca1a3710ab..24657943d7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -68,6 +68,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, + Spacing = new Vector2(5) }); // todo: this should be implemented via a custom HUD implementation, and correctly masked to the main content area. @@ -78,7 +79,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer ((IBindable)leaderboard.Expanded).BindTo(HUDOverlay.ShowHud); - leaderboardFlow.Add(l); + leaderboardFlow.Insert(0, l); if (leaderboard.TeamScores.Count >= 2) { @@ -87,10 +88,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Team1Score = { BindTarget = leaderboard.TeamScores.First().Value }, Team2Score = { BindTarget = leaderboard.TeamScores.Last().Value }, Expanded = { BindTarget = HUDOverlay.ShowHud }, - }, leaderboardFlow.Add); + }, scoreDisplay => leaderboardFlow.Insert(1, scoreDisplay)); } }); + LoadComponentAsync(new GameplayChatDisplay + { + Expanded = { BindTarget = HUDOverlay.ShowHud }, + }, chat => leaderboardFlow.Insert(2, chat)); + HUDOverlay.Add(loadingDisplay = new LoadingLayer(true) { Depth = float.MaxValue }); } From 124f149cb5f861de220d98c5da7f0a2a19b7a9d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 15:05:36 +0900 Subject: [PATCH 183/366] Add key binding to focus chat input --- .../Input/Bindings/GlobalActionContainer.cs | 4 ++++ .../Multiplayer/GameplayChatDisplay.cs | 20 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index d3cc90ef99..66edb25d64 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -90,6 +90,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Left, GlobalAction.SeekReplayBackward), new KeyBinding(InputKey.Right, GlobalAction.SeekReplayForward), new KeyBinding(InputKey.Control, GlobalAction.HoldForHUD), + new KeyBinding(InputKey.Tab, GlobalAction.FocusChatInput), }; public IEnumerable SongSelectKeyBindings => new[] @@ -280,5 +281,8 @@ namespace osu.Game.Input.Bindings [Description("Seek replay backward")] SeekReplayBackward, + + [Description("Focus chat")] + FocusChatInput } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index 5b33fa1844..40da8d0a84 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -4,12 +4,14 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.Play; namespace osu.Game.Screens.OnlinePlay.Multiplayer { - public class GameplayChatDisplay : MatchChatDisplay + public class GameplayChatDisplay : MatchChatDisplay, IKeyBindingHandler { [Resolved] private ILocalUserPlayInfo localUserInfo { get; set; } @@ -58,5 +60,21 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Expanded.BindValueChanged(expandedChanged, true); } + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.FocusChatInput: + Textbox.TakeFocus(); + return true; + } + + return false; + } + + public void OnReleased(GlobalAction action) + { + } } } From 6a2d82c81aa6cd9ff1f6dae57b561ff1132c5367 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 15:11:45 +0900 Subject: [PATCH 184/366] Add test coverage --- .../TestSceneGameplayChatDisplay.cs | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs new file mode 100644 index 0000000000..795963a1ba --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs @@ -0,0 +1,85 @@ +// 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 Moq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Testing; +using osu.Game.Screens.OnlinePlay.Multiplayer; +using osu.Game.Screens.Play; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneGameplayChatDisplay : MultiplayerTestScene + { + private GameplayChatDisplay chatDisplay; + + [Cached(typeof(ILocalUserPlayInfo))] + private ILocalUserPlayInfo localUserInfo; + + private readonly Bindable localUserPlaying = new Bindable(); + + private TextBox textBox => chatDisplay.ChildrenOfType().First(); + + public TestSceneGameplayChatDisplay() + { + var mockLocalUserInfo = new Mock(); + mockLocalUserInfo.SetupGet(i => i.IsPlaying).Returns(localUserPlaying); + + localUserInfo = mockLocalUserInfo.Object; + } + + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("load chat display", () => Child = chatDisplay = new GameplayChatDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 0.5f, + }); + + AddStep("expand", () => chatDisplay.Expanded.Value = true); + } + + [Test] + public void TestFocusDroppedWhenPlaying() + { + assertChatFocused(false); + + AddStep("focus chat", () => + { + InputManager.MoveMouseTo(textBox); + InputManager.Click(MouseButton.Left); + }); + + setLocalUserPlaying(true); + assertChatFocused(false); + + // should still stay non-focused even after entering a new break section. + setLocalUserPlaying(false); + assertChatFocused(false); + } + + [Test] + public void TestFocusOnTabKey() + { + assertChatFocused(false); + AddStep("press tab", () => InputManager.Key(Key.Tab)); + assertChatFocused(true); + } + + private void assertChatFocused(bool isFocused) => + AddAssert($"chat {(isFocused ? "focused" : "not focused")}", () => textBox.HasFocus == isFocused); + + private void setLocalUserPlaying(bool playing) => + AddStep($"local user {(playing ? "playing" : "not playing")}", () => localUserPlaying.Value = playing); + } +} From 6ee6a468941525b3b6d98369c4f3fdcdd30c58d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 16:22:12 +0900 Subject: [PATCH 185/366] Remove unnecessary `public` prefix in interface specification --- osu.Game/Screens/Play/ILocalUserPlayInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs index 64c3f97305..9a2259b12f 100644 --- a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs +++ b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs @@ -12,6 +12,6 @@ namespace osu.Game.Screens.Play /// /// Whether the local user is currently playing. /// - public IBindable IsPlaying { get; } + IBindable IsPlaying { get; } } } From 72dd18732d44efb3c24e732fa59be8cae0f52e9f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 16:37:18 +0900 Subject: [PATCH 186/366] Fix regressed tests --- osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs index 8632bfe681..57ba051214 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Settings [SetUpSteps] public void SetUpSteps() { - AddUntilStep("wait for load", () => panel.ChildrenOfType().Any()); + AddUntilStep("wait for load", () => panel.ChildrenOfType().Any()); AddStep("Scroll to top", () => panel.ChildrenOfType().First().ScrollToTop()); AddWaitStep("wait for scroll", 5); } From 8a1651e8308f1ee865d22cc81f9bc87192e962a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 17:04:32 +0900 Subject: [PATCH 187/366] Reorganise methods in `PollingComponent` --- osu.Game/Online/PollingComponent.cs | 73 ++++++++++++++--------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index 806c0047e7..243be8da44 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -47,39 +47,13 @@ namespace osu.Game.Online pollIfNecessary(); } - private bool pollIfNecessary() + /// + /// Immediately performs a . + /// + public void PollImmediately() { - // we must be loaded so we have access to clock. - if (!IsLoaded) return false; - - // there's already a poll process running. - if (pollingActive) return false; - - // don't try polling if the time between polls hasn't been set. - if (TimeBetweenPolls.Value == 0) return false; - - if (!lastTimePolled.HasValue) - { - doPoll(); - return true; - } - - if (Time.Current - lastTimePolled.Value > TimeBetweenPolls.Value) - { - doPoll(); - return true; - } - - // not enough time has passed since the last poll. we do want to schedule a poll to happen, though. + lastTimePolled = Time.Current - TimeBetweenPolls.Value; scheduleNextPoll(); - return false; - } - - private void doPoll() - { - scheduledPoll = null; - pollingActive = true; - Poll().ContinueWith(_ => pollComplete()); } /// @@ -90,13 +64,11 @@ namespace osu.Game.Online return Task.CompletedTask; } - /// - /// Immediately performs a . - /// - public void PollImmediately() + private void doPoll() { - lastTimePolled = Time.Current - TimeBetweenPolls.Value; - scheduleNextPoll(); + scheduledPoll = null; + pollingActive = true; + Poll().ContinueWith(_ => pollComplete()); } /// @@ -111,6 +83,33 @@ namespace osu.Game.Online pollIfNecessary(); } + private void pollIfNecessary() + { + // we must be loaded so we have access to clock. + if (!IsLoaded) return; + + // there's already a poll process running. + if (pollingActive) return; + + // don't try polling if the time between polls hasn't been set. + if (TimeBetweenPolls.Value == 0) return; + + if (!lastTimePolled.HasValue) + { + doPoll(); + return; + } + + if (Time.Current - lastTimePolled.Value > TimeBetweenPolls.Value) + { + doPoll(); + return; + } + + // not enough time has passed since the last poll. we do want to schedule a poll to happen, though. + scheduleNextPoll(); + } + private void scheduleNextPoll() { scheduledPoll?.Cancel(); From 4b198d14eb4dd473cf042c940d0955bbdc69411a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 17:05:20 +0900 Subject: [PATCH 188/366] Initial refactor of RoomSubScreen --- .../Multiplayer/TestSceneMultiplayer.cs | 13 + .../TestSceneMultiplayerMatchSubScreen.cs | 34 +- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 126 +++++-- .../Multiplayer/MultiplayerMatchSubScreen.cs | 349 +++++++++--------- .../Playlists/PlaylistsRoomSubScreen.cs | 8 + 5 files changed, 302 insertions(+), 228 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index e618b28f40..035bdbea1c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -83,6 +83,19 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("load multiplayer", () => LoadScreen(multiplayerScreen)); AddUntilStep("wait for multiplayer to load", () => multiplayerScreen.IsLoaded); AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); + + createRoom(() => new Room + { + Name = { Value = "Test Room" }, + Playlist = + { + new PlaylistItem + { + Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, + } + } + }); } [Test] diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index ea10fc1b8b..21364fe154 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -59,23 +59,6 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for load", () => screen.IsCurrentScreen()); } - [Test] - public void TestSettingValidity() - { - AddAssert("create button not enabled", () => !this.ChildrenOfType().Single().Enabled.Value); - - AddStep("set playlist", () => - { - SelectedRoom.Value.Playlist.Add(new PlaylistItem - { - Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, - Ruleset = { Value = new OsuRuleset().RulesetInfo }, - }); - }); - - AddAssert("create button enabled", () => this.ChildrenOfType().Single().Enabled.Value); - } - [Test] public void TestCreatedRoom() { @@ -97,6 +80,23 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for join", () => Client.Room != null); } + [Test] + public void TestSettingValidity() + { + AddAssert("create button not enabled", () => !this.ChildrenOfType().Single().Enabled.Value); + + AddStep("set playlist", () => + { + SelectedRoom.Value.Playlist.Add(new PlaylistItem + { + Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, + }); + }); + + AddAssert("create button enabled", () => this.ChildrenOfType().Single().Enabled.Value); + } + [Test] public void TestStartMatchWhileSpectating() { diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 243d2abf74..8de8e5e897 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -19,6 +19,7 @@ using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Match @@ -31,8 +32,6 @@ namespace osu.Game.Screens.OnlinePlay.Match public override bool DisallowExternalBeatmapRulesetChanges => true; - private readonly ModSelectOverlay userModsSelectOverlay; - /// /// A container that provides controls for selection of user mods. /// This will be shown/hidden automatically when applicable. @@ -58,49 +57,106 @@ namespace osu.Game.Screens.OnlinePlay.Match private IBindable> managerUpdated; [Cached] - protected OnlinePlayBeatmapAvailabilityTracker BeatmapAvailabilityTracker { get; } + protected OnlinePlayBeatmapAvailabilityTracker BeatmapAvailabilityTracker { get; private set; } protected IBindable BeatmapAvailability => BeatmapAvailabilityTracker.Availability; - protected RoomSubScreen() + private readonly Room room; + + private ModSelectOverlay userModsSelectOverlay; + + protected RoomSubScreen(Room room) { + this.room = room; + Padding = new MarginPadding { Top = Header.HEIGHT }; - AddRangeInternal(new Drawable[] + BeatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"3e3a44") // This is super temporary. - }, - BeatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker - { - SelectedItem = { BindTarget = SelectedItem } - }, - new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Depth = float.MinValue, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING }, - Child = userModsSelectOverlay = new UserModSelectOverlay - { - SelectedMods = { BindTarget = UserMods }, - IsValidMod = _ => false - } - }, - }); + SelectedItem = { BindTarget = SelectedItem } + }; } - protected override void ClearInternal(bool disposeChildren = true) => - throw new InvalidOperationException($"{nameof(RoomSubScreen)}'s children should not be cleared as it will remove required components"); - [BackgroundDependencyLoader] private void load(AudioManager audio) { sampleStart = audio.Samples.Get(@"SongSelect/confirm-selection"); + + InternalChildren = new Drawable[] + { + BeatmapAvailabilityTracker, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + // Padded main content (drawable room + main content) + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 60 }, + // Main content + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] + { + CreateDrawableRoom(room), + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 10, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"3e3a44") // This is super temporary. + }, + }, + CreateMainContent(), + new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = userModsSelectOverlay = new UserModSelectOverlay + { + SelectedMods = { BindTarget = UserMods }, + IsValidMod = _ => false + } + }, + } + } + } + } + } + } + }, + // Footer + new[] + { + CreateFooter() + } + } + } + }; } protected override void LoadComplete() @@ -257,6 +313,12 @@ namespace osu.Game.Screens.OnlinePlay.Match track.Looping = false; } + protected abstract DrawableRoom CreateDrawableRoom(Room room); + + protected abstract Drawable CreateMainContent(); + + protected abstract Drawable CreateFooter(); + private class UserModSelectOverlay : LocalPlayerModSelectOverlay { } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 6277afa8bb..da766c9e25 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -22,6 +22,7 @@ using osu.Game.Overlays.Dialog; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; @@ -58,10 +59,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [CanBeNull] private IDisposable readyClickOperation; - private GridContainer mainContent; + // private GridContainer mainContent; private MultiplayerMatchSettingsOverlay settingsOverlay; public MultiplayerMatchSubScreen(Room room) + : base(room) { Room = room; @@ -72,191 +74,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [BackgroundDependencyLoader] private void load() { - AddRangeInternal(new Drawable[] - { - mainContent = new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Horizontal = HORIZONTAL_OVERFLOW_PADDING + 55, - Vertical = 20 - }, - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - }, - Content = new[] - { - new Drawable[] - { - new MultiplayerMatchHeader - { - OpenSettings = () => settingsOverlay.Show() - } - }, - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 5, Vertical = 10 }, - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 400), - new Dimension(), - new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 600), - }, - Content = new[] - { - new Drawable[] - { - // Main left column - new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] { new ParticipantsListHeader() }, - new Drawable[] - { - new ParticipantsList - { - RelativeSizeAxes = Axes.Both - }, - } - } - }, - // Spacer - null, - // Main right column - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new[] - { - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - new OverlinedHeader("Beatmap"), - new BeatmapSelectionControl { RelativeSizeAxes = Axes.X } - } - }, - UserModsSection = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 10 }, - Children = new Drawable[] - { - new OverlinedHeader("Extra mods"), - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new UserModSelectButton - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Width = 90, - Text = "Select", - Action = ShowUserModSelect, - }, - new ModDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Current = UserMods, - Scale = new Vector2(0.8f), - }, - } - } - } - } - } - } - } - } - } - } - }, - new Drawable[] - { - new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] { new OverlinedHeader("Chat") }, - new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } - } - } - } - }, - } - } - }, - new Drawable[] - { - new MultiplayerMatchFooter - { - OnReadyClick = onReadyClick, - OnSpectateClick = onSpectateClick - } - } - }, - RowDimensions = new[] - { - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - } - }, - settingsOverlay = new MultiplayerMatchSettingsOverlay - { - RelativeSizeAxes = Axes.Both, - State = { Value = client.Room == null ? Visibility.Visible : Visibility.Hidden } - } - }); - if (client.Room == null) { // A new room is being created. // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. - mainContent.Hide(); + // mainContent.Hide(); settingsOverlay.State.BindValueChanged(visibility => { - if (visibility.NewValue == Visibility.Hidden) - mainContent.Show(); + // if (visibility.NewValue == Visibility.Hidden) + // mainContent.Show(); }, true); } } @@ -303,6 +130,170 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList(); } + protected override DrawableRoom CreateDrawableRoom(Room room) => new DrawableRoom(room); + + protected override Drawable CreateMainContent() => new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Horizontal = HORIZONTAL_OVERFLOW_PADDING + 55, + Vertical = 20 + }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + }, + Content = new[] + { + new Drawable[] + { + new MultiplayerMatchHeader + { + OpenSettings = () => settingsOverlay.Show() + } + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 5, Vertical = 10 }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 400), + new Dimension(), + new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 600), + }, + Content = new[] + { + new Drawable[] + { + // Main left column + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] { new ParticipantsListHeader() }, + new Drawable[] + { + new ParticipantsList + { + RelativeSizeAxes = Axes.Both + }, + } + } + }, + // Spacer + null, + // Main right column + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new OverlinedHeader("Beatmap"), + new BeatmapSelectionControl { RelativeSizeAxes = Axes.X } + } + }, + UserModsSection = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 10 }, + Children = new Drawable[] + { + new OverlinedHeader("Extra mods"), + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new UserModSelectButton + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 90, + Text = "Select", + Action = ShowUserModSelect, + }, + new ModDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = UserMods, + Scale = new Vector2(0.8f), + }, + } + } + } + } + } + } + } + } + } + } + }, + new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] { new OverlinedHeader("Chat") }, + new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } + } + } + } + }, + } + }, + settingsOverlay = new MultiplayerMatchSettingsOverlay + { + RelativeSizeAxes = Axes.Both, + // State = { Value = client.Room == null ? Visibility.Visible : Visibility.Hidden } + } + } + }; + + protected override Drawable CreateFooter() => new MultiplayerMatchFooter + { + OnReadyClick = onReadyClick, + OnSpectateClick = onSpectateClick + }; + [Resolved(canBeNull: true)] private DialogOverlay dialogOverlay { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 682b055766..8ca592ee2c 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -14,6 +14,7 @@ using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.Play; @@ -45,6 +46,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private SelectionPollingComponent selectionPollingComponent; public PlaylistsRoomSubScreen(Room room) + : base(room) { Title = room.RoomID.Value == null ? "New playlist" : room.Name.Value; Activity.Value = new UserActivity.InLobby(room); @@ -295,5 +297,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { Exited = () => leaderboard.RefreshScores() }); + + protected override DrawableRoom CreateDrawableRoom(Room room) => new DrawableRoom(room); + + protected override Drawable CreateMainContent() => Empty(); + + protected override Drawable CreateFooter() => Empty(); } } From 6416e64e06a1695d03e3b524a1094de772bae2b3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 17:13:25 +0900 Subject: [PATCH 189/366] Adjust sizings and paddings --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 11 ++++++++++- .../Multiplayer/MultiplayerMatchSubScreen.cs | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 8de8e5e897..7513ffa0f3 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -88,6 +88,11 @@ namespace osu.Game.Screens.OnlinePlay.Match new GridContainer { RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize) + }, Content = new[] { // Padded main content (drawable room + main content) @@ -96,7 +101,11 @@ namespace osu.Game.Screens.OnlinePlay.Match new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 60 }, + Padding = new MarginPadding + { + Horizontal = WaveOverlayContainer.WIDTH_PADDING, + Bottom = 30 + }, // Main content Child = new GridContainer { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index da766c9e25..0a7ddb1254 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -142,8 +142,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { - Horizontal = HORIZONTAL_OVERFLOW_PADDING + 55, - Vertical = 20 + Horizontal = 10, + Vertical = 10 }, Child = new GridContainer { From 5d72c5911af23537b27addcd5b64e66022d0da40 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 17:14:21 +0900 Subject: [PATCH 190/366] Rename MatchSettingsOverlay and related classes Because "match" is a multiplayer-only concept. --- .../Playlists/TestScenePlaylistsMatchSettingsOverlay.cs | 2 +- .../Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs | 4 ++-- .../{MatchSettingsOverlay.cs => RoomSettingsOverlay.cs} | 2 +- .../Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs | 2 +- ...atchSettingsOverlay.cs => PlaylistsRoomSettingsOverlay.cs} | 2 +- .../Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game/Screens/OnlinePlay/Match/Components/{MatchSettingsOverlay.cs => RoomSettingsOverlay.cs} (97%) rename osu.Game/Screens/OnlinePlay/Playlists/{PlaylistsMatchSettingsOverlay.cs => PlaylistsRoomSettingsOverlay.cs} (99%) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 98882b659c..04b44efd32 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -110,7 +110,7 @@ namespace osu.Game.Tests.Visual.Playlists AddUntilStep("error not displayed", () => !settings.ErrorText.IsPresent); } - private class TestRoomSettings : PlaylistsMatchSettingsOverlay + private class TestRoomSettings : PlaylistsRoomSettingsOverlay { public TriangleButton ApplyButton => ((MatchSettings)Settings).ApplyButton; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs index 9fc29049ef..ee93e728ac 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs @@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("move mouse to create button", () => { - InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); }); AddStep("click", () => InputManager.Click(MouseButton.Left)); @@ -147,7 +147,7 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("create room", () => { - InputManager.MoveMouseTo(match.ChildrenOfType().Single()); + InputManager.MoveMouseTo(match.ChildrenOfType().Single()); InputManager.Click(MouseButton.Left); }); diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs similarity index 97% rename from osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs rename to osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index 2676453a7e..bcefd5a333 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -14,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Match.Components { - public abstract class MatchSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler + public abstract class RoomSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler { protected const float TRANSITION_DURATION = 350; protected const float FIELD_PADDING = 45; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 5f3921d742..3a95ac00a6 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -26,7 +26,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { - public class MultiplayerMatchSettingsOverlay : MatchSettingsOverlay + public class MultiplayerMatchSettingsOverlay : RoomSettingsOverlay { private MatchSettings settings; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs similarity index 99% rename from osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs rename to osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs index 2640f99ea5..d28f886be4 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Screens.OnlinePlay.Playlists { - public class PlaylistsMatchSettingsOverlay : MatchSettingsOverlay + public class PlaylistsRoomSettingsOverlay : RoomSettingsOverlay { public Action EditPlaylist; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 8ca592ee2c..c2f92d7e00 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private readonly IBindable isIdle = new BindableBool(); - private MatchSettingsOverlay settingsOverlay; + private RoomSettingsOverlay settingsOverlay; private MatchLeaderboard leaderboard; private OverlinedHeader participantsHeader; private GridContainer mainContent; @@ -237,7 +237,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists new Dimension(GridSizeMode.AutoSize), } }, - settingsOverlay = new PlaylistsMatchSettingsOverlay + settingsOverlay = new PlaylistsRoomSettingsOverlay { RelativeSizeAxes = Axes.Both, EditPlaylist = () => From 9eb16fa61de76cd0432cb199503ef9a4f31f6d2c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 17:16:21 +0900 Subject: [PATCH 191/366] Move poll allowance logic based on signalr connection inside polling component --- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 47 +++++++------------ 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index 97fed2040d..d152fc3913 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -25,19 +25,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } - private MultiplayerListingPollingComponent multiplayerListingPollingComponent => (MultiplayerListingPollingComponent)ListingPollingComponent; - - private readonly IBindable isConnected = new Bindable(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - isConnected.BindTo(client.IsConnected); - isConnected.BindValueChanged(c => Scheduler.AddOnce(() => multiplayerListingPollingComponent.AllowPolling = c.NewValue)); - multiplayerListingPollingComponent.AllowPolling = isConnected.Value; - } - public override void OnResuming(IScreen last) { base.OnResuming(last); @@ -47,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (last is MultiplayerMatchSubScreen match) { RoomManager.RemoveRoom(match.Room); - multiplayerListingPollingComponent.PollImmediately(); + ListingPollingComponent.PollImmediately(); } } @@ -84,27 +71,29 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private class MultiplayerListingPollingComponent : ListingPollingComponent { - private bool allowPolling; + [Resolved] + private MultiplayerClient client { get; set; } - public bool AllowPolling + private readonly IBindable isConnected = new Bindable(); + + [BackgroundDependencyLoader] + private void load() { - get => allowPolling; - set + isConnected.BindTo(client.IsConnected); + isConnected.BindValueChanged(c => Scheduler.AddOnce(() => { - if (allowPolling == value) - return; - - allowPolling = value; - - if (!allowPolling) - return; - - if (IsLoaded) + if (isConnected.Value && IsLoaded) PollImmediately(); - } + }), true); } - protected override Task Poll() => AllowPolling ? base.Poll() : Task.CompletedTask; + protected override Task Poll() + { + if (!isConnected.Value) + return Task.CompletedTask; + + return base.Poll(); + } } } } From 3b5fc6d10ff17fb06f43cdd107036a6e7da0164a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 17:18:23 +0900 Subject: [PATCH 192/366] Ensure `updateLoadingLayer` is run at least once --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 3e8d07d002..8bed3d6049 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -186,16 +186,16 @@ namespace osu.Game.Screens.OnlinePlay.Lounge searchTextBox.Current.BindValueChanged(_ => updateFilterDebounced()); ruleset.BindValueChanged(_ => UpdateFilter()); - ListingPollingComponent.InitialRoomsReceived.BindValueChanged(_ => updateLoadingLayer()); - isIdle.BindValueChanged(_ => updatePollingRate(this.IsCurrentScreen()), true); if (ongoingOperationTracker != null) { operationInProgress.BindTo(ongoingOperationTracker.InProgress); - operationInProgress.BindValueChanged(_ => updateLoadingLayer(), true); + operationInProgress.BindValueChanged(_ => updateLoadingLayer()); } + ListingPollingComponent.InitialRoomsReceived.BindValueChanged(_ => updateLoadingLayer(), true); + updateFilter(); } From c0b388cd74e864f6654d161e4bd631ca36408b0c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 17:50:30 +0900 Subject: [PATCH 193/366] Fix regression in `ModSettingsChangeTracker` --- osu.Game/Overlays/Settings/SettingsItem.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index c35690151c..6621caef4e 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -119,19 +119,19 @@ namespace osu.Game.Overlays.Settings }, }, }; - } - [BackgroundDependencyLoader] - private void load() - { - // all bindable logic is in constructor intentionally to support "CreateSettingsControls" being used in a context it is + // IMPORTANT: all bindable logic is in constructor intentionally to support "CreateSettingsControls" being used in a context it is // never loaded, but requires bindable storage. if (controlWithCurrent == null) throw new ArgumentException(@$"Control created via {nameof(CreateControl)} must implement {nameof(IHasCurrentValue)}"); controlWithCurrent.Current.ValueChanged += _ => SettingChanged?.Invoke(); controlWithCurrent.Current.DisabledChanged += _ => updateDisabled(); + } + [BackgroundDependencyLoader] + private void load() + { // intentionally done before LoadComplete to avoid overhead. if (ShowsDefaultIndicator) { From 6840ec671684501b2ca47675d17e4405fdd7a55e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 17:58:24 +0900 Subject: [PATCH 194/366] Actually show the room in the sub screen --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 7513ffa0f3..afd7112b22 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -113,13 +113,15 @@ namespace osu.Game.Screens.OnlinePlay.Match RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, 10) }, Content = new[] { new Drawable[] { - CreateDrawableRoom(room), + CreateDrawableRoom(room).With(d => d.MatchingFilter = true), }, + null, new Drawable[] { new Container From f16468b7063ea85c7b610f0d761151ad181f02f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 18:17:55 +0900 Subject: [PATCH 195/366] Improve visibility of repeat ticks / drag areas on timeline --- .../Timeline/TimelineHitObjectBlueprint.cs | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 6e57b8e88c..911c9fea51 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -166,14 +166,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } if (IsSelected) - { border.Show(); - colour = colour.Lighten(0.3f); - } else - { border.Hide(); - } if (Item is IHasDuration duration && duration.Duration > 0) circle.Colour = ColourInfo.GradientHorizontal(colour, colour.Lighten(0.4f)); @@ -212,14 +207,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline for (int i = 0; i < repeats.RepeatCount; i++) { - repeatsContainer.Add(new Circle + repeatsContainer.Add(new Tick { - Size = new Vector2(circle_size / 3), - Alpha = 0.2f, - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.X, - X = (float)(i + 1) / (repeats.RepeatCount + 1), + X = (float)(i + 1) / (repeats.RepeatCount + 1) }); } } @@ -233,6 +223,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public override Vector2 ScreenSpaceSelectionPoint => ScreenSpaceDrawQuad.TopLeft; + private class Tick : Circle + { + public Tick() + { + Size = new Vector2(circle_size / 4); + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + RelativePositionAxes = Axes.X; + } + } + public class DragArea : Circle { private readonly HitObject hitObject; @@ -304,20 +305,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void updateState() { - if (hasMouseDown) - { - this.ScaleTo(0.7f, 200, Easing.OutQuint); - } - else if (IsHovered) - { - this.ScaleTo(0.8f, 200, Easing.OutQuint); - } - else - { - this.ScaleTo(0.6f, 200, Easing.OutQuint); - } + float scale = 0.5f; - this.FadeTo(IsHovered || hasMouseDown ? 0.8f : 0.2f, 200, Easing.OutQuint); + if (hasMouseDown) + scale = 0.6f; + else if (IsHovered) + scale = 0.7f; + + this.ScaleTo(scale, 200, Easing.OutQuint); + this.FadeTo(IsHovered || hasMouseDown ? 1f : 0.9f, 200, Easing.OutQuint); } [Resolved] From 590d814881e71dcb4ad353f40e7a5164df8adb41 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 18:24:04 +0900 Subject: [PATCH 196/366] Move RoomSettingsOverlay to RoomSubScreen --- .../Match/Components/RoomSettingsOverlay.cs | 8 +- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 109 ++++++++++++------ .../Multiplayer/MultiplayerMatchSubScreen.cs | 44 +------ .../Playlists/PlaylistsRoomSubScreen.cs | 2 + 4 files changed, 82 insertions(+), 81 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index bcefd5a333..5f0ce0feed 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -27,11 +27,15 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected abstract bool IsLoading { get; } + protected RoomSettingsOverlay() + { + RelativeSizeAxes = Axes.Both; + Masking = true; + } + [BackgroundDependencyLoader] private void load() { - Masking = true; - Add(Settings = CreateSettings()); } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index afd7112b22..a79f9421a7 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -64,6 +64,7 @@ namespace osu.Game.Screens.OnlinePlay.Match private readonly Room room; private ModSelectOverlay userModsSelectOverlay; + private RoomSettingsOverlay settingsOverlay; protected RoomSubScreen(Room room) { @@ -82,6 +83,8 @@ namespace osu.Game.Screens.OnlinePlay.Match { sampleStart = audio.Samples.Get(@"SongSelect/confirm-selection"); + Drawable mainContent; + InternalChildren = new Drawable[] { BeatmapAvailabilityTracker, @@ -106,59 +109,62 @@ namespace osu.Game.Screens.OnlinePlay.Match Horizontal = WaveOverlayContainer.WIDTH_PADDING, Bottom = 30 }, - // Main content - Child = new GridContainer + Children = new[] { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + mainContent = new GridContainer { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Absolute, 10) - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - CreateDrawableRoom(room).With(d => d.MatchingFilter = true), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, 10) }, - null, - new Drawable[] + Content = new[] { - new Container + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new[] + CreateDrawableRoom(room).With(d => d.MatchingFilter = true), + }, + null, + new Drawable[] + { + new Container { - new Container + RelativeSizeAxes = Axes.Both, + Children = new[] { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 10, - Child = new Box + new Container { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"3e3a44") // This is super temporary. + Masking = true, + CornerRadius = 10, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"3e3a44") // This is super temporary. + }, }, - }, - CreateMainContent(), - new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = userModsSelectOverlay = new UserModSelectOverlay + CreateMainContent(), + new Container { - SelectedMods = { BindTarget = UserMods }, - IsValidMod = _ => false - } - }, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = userModsSelectOverlay = new UserModSelectOverlay + { + SelectedMods = { BindTarget = UserMods }, + IsValidMod = _ => false + } + }, + } } } } - } - } - } + }, + settingsOverlay = CreateRoomSettingsOverlay() + }, + }, }, // Footer new[] @@ -168,6 +174,19 @@ namespace osu.Game.Screens.OnlinePlay.Match } } }; + + if (room.RoomID.Value == null) + { + // A new room is being created. + // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. + mainContent.Hide(); + + settingsOverlay.State.BindValueChanged(visibility => + { + if (visibility.NewValue == Visibility.Hidden) + mainContent.Show(); + }, true); + } } protected override void LoadComplete() @@ -184,12 +203,24 @@ namespace osu.Game.Screens.OnlinePlay.Match public override bool OnBackButton() { + if (room.RoomID.Value == null) + { + // room has not been created yet; exit immediately. + return base.OnBackButton(); + } + if (userModsSelectOverlay.State.Value == Visibility.Visible) { userModsSelectOverlay.Hide(); return true; } + if (settingsOverlay.State.Value == Visibility.Visible) + { + settingsOverlay.Hide(); + return true; + } + return base.OnBackButton(); } @@ -330,6 +361,8 @@ namespace osu.Game.Screens.OnlinePlay.Match protected abstract Drawable CreateFooter(); + protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(); + private class UserModSelectOverlay : LocalPlayerModSelectOverlay { } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 0a7ddb1254..1b9c2092dd 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -60,7 +60,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private IDisposable readyClickOperation; // private GridContainer mainContent; - private MultiplayerMatchSettingsOverlay settingsOverlay; public MultiplayerMatchSubScreen(Room room) : base(room) @@ -71,23 +70,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Activity.Value = new UserActivity.InLobby(room); } - [BackgroundDependencyLoader] - private void load() - { - if (client.Room == null) - { - // A new room is being created. - // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. - // mainContent.Hide(); - - settingsOverlay.State.BindValueChanged(visibility => - { - // if (visibility.NewValue == Visibility.Hidden) - // mainContent.Show(); - }, true); - } - } - protected override void LoadComplete() { base.LoadComplete(); @@ -159,7 +141,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { new MultiplayerMatchHeader { - OpenSettings = () => settingsOverlay.Show() + // OpenSettings = () => settingsOverlay.Show() } }, new Drawable[] @@ -280,11 +262,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer }, } }, - settingsOverlay = new MultiplayerMatchSettingsOverlay - { - RelativeSizeAxes = Axes.Both, - // State = { Value = client.Room == null ? Visibility.Visible : Visibility.Hidden } - } } }; @@ -294,28 +271,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer OnSpectateClick = onSpectateClick }; + protected override RoomSettingsOverlay CreateRoomSettingsOverlay() => new MultiplayerMatchSettingsOverlay(); + [Resolved(canBeNull: true)] private DialogOverlay dialogOverlay { get; set; } private bool exitConfirmed; - public override bool OnBackButton() - { - if (client.Room == null) - { - // room has not been created yet; exit immediately. - return base.OnBackButton(); - } - - if (settingsOverlay.State.Value == Visibility.Visible) - { - settingsOverlay.Hide(); - return true; - } - - return base.OnBackButton(); - } - public override bool OnExiting(IScreen next) { // the room may not be left immediately after a disconnection due to async flow, diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index c2f92d7e00..7af74e7e64 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -303,5 +303,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override Drawable CreateMainContent() => Empty(); protected override Drawable CreateFooter() => Empty(); + + protected override RoomSettingsOverlay CreateRoomSettingsOverlay() => new PlaylistsRoomSettingsOverlay(); } } From d66f7cb6b597ce62acd5460771958bfc59c1c97f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Aug 2021 19:21:22 +0900 Subject: [PATCH 197/366] Fix tests by allowing retrieval with files where required --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 16 ++++++++-------- osu.Game/Skinning/SkinManager.cs | 10 ++++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 8124bd4199..bab8dfc983 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -50,10 +50,10 @@ namespace osu.Game.Tests.Skins.IO var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin", "skinner"), "skin2.osk")); Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Count, Is.EqualTo(1)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(1)); // the first should be overwritten by the second import. - Assert.That(osu.Dependencies.Get().GetAllUserSkins().First().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); } finally { @@ -76,10 +76,10 @@ namespace osu.Game.Tests.Skins.IO var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk(string.Empty, string.Empty), "download.osk")); Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Count, Is.EqualTo(2)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(2)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); } finally { @@ -101,10 +101,10 @@ namespace osu.Game.Tests.Skins.IO var imported2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOsk("test skin v2.1", "skinner"), "skin2.osk")); Assert.That(imported2.ID, Is.Not.EqualTo(imported.ID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Count, Is.EqualTo(2)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Count, Is.EqualTo(2)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); - Assert.That(osu.Dependencies.Get().GetAllUserSkins().Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).First().Files.First().FileInfoID, Is.EqualTo(imported.Files.First().FileInfoID)); + Assert.That(osu.Dependencies.Get().GetAllUserSkins(true).Last().Files.First().FileInfoID, Is.EqualTo(imported2.Files.First().FileInfoID)); } finally { diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index fca1670419..51aaac1f79 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -95,7 +95,7 @@ namespace osu.Game.Skinning /// A newly allocated list of available . public List GetAllUsableSkins() { - var userSkins = GetAllUserSkins(); + var userSkins = GetAllUserSkins(false); userSkins.Insert(0, DefaultSkin.SkinInfo); userSkins.Insert(1, DefaultLegacySkin.SkinInfo); return userSkins; @@ -105,7 +105,13 @@ namespace osu.Game.Skinning /// Returns a list of all usable s that have been loaded by the user. /// /// A newly allocated list of available . - public List GetAllUserSkins() => ModelStore.Items.Where(s => !s.DeletePending).ToList(); + public List GetAllUserSkins(bool includeFiles = false) + { + if (includeFiles) + return ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + + return ModelStore.Items.Where(s => !s.DeletePending).ToList(); + } public void SelectRandomSkin() { From 47d4a2e97f70de9b1cc307554de19b45eaa3a107 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Aug 2021 20:05:26 +0900 Subject: [PATCH 198/366] Make SettingsOverlay protected --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 10 +++++----- .../Multiplayer/MultiplayerMatchSubScreen.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index a79f9421a7..3addf57048 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -64,7 +64,7 @@ namespace osu.Game.Screens.OnlinePlay.Match private readonly Room room; private ModSelectOverlay userModsSelectOverlay; - private RoomSettingsOverlay settingsOverlay; + protected RoomSettingsOverlay SettingsOverlay { get; private set; } protected RoomSubScreen(Room room) { @@ -162,7 +162,7 @@ namespace osu.Game.Screens.OnlinePlay.Match } } }, - settingsOverlay = CreateRoomSettingsOverlay() + SettingsOverlay = CreateRoomSettingsOverlay() }, }, }, @@ -181,7 +181,7 @@ namespace osu.Game.Screens.OnlinePlay.Match // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. mainContent.Hide(); - settingsOverlay.State.BindValueChanged(visibility => + SettingsOverlay.State.BindValueChanged(visibility => { if (visibility.NewValue == Visibility.Hidden) mainContent.Show(); @@ -215,9 +215,9 @@ namespace osu.Game.Screens.OnlinePlay.Match return true; } - if (settingsOverlay.State.Value == Visibility.Visible) + if (SettingsOverlay.State.Value == Visibility.Visible) { - settingsOverlay.Hide(); + SettingsOverlay.Hide(); return true; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 1b9c2092dd..09c2a22850 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -141,7 +141,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { new MultiplayerMatchHeader { - // OpenSettings = () => settingsOverlay.Show() + OpenSettings = () => SettingsOverlay.Show() } }, new Drawable[] From 2296ee60598cea4d5fb1d276d624d3d54874e312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20Sch=C3=BCrz?= Date: Tue, 17 Aug 2021 16:56:06 +0200 Subject: [PATCH 199/366] Add test coverage --- .../Visual/Editing/TestSceneEditorClock.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs index 0b1617b6a6..0abf0c47f8 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs @@ -78,6 +78,24 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("clock looped to start", () => Clock.IsRunning && Clock.CurrentTime < 500); } + [Test] + public void TestClampWhenSeekOutsideBeatmapBounds() + { + AddStep("stop clock", Clock.Stop); + + AddStep("seek before start time", () => Clock.Seek(-1000)); + AddAssert("time is clamped to 0", () => Clock.CurrentTime == 0); + + AddStep("seek beyond track length", () => Clock.Seek(Clock.TrackLength + 1000)); + AddAssert("time is clamped to track length", () => Clock.CurrentTime == Clock.TrackLength); + + AddStep("seek smoothly before start time", () => Clock.SeekSmoothlyTo(-1000)); + AddAssert("time is clamped to 0", () => Clock.CurrentTime == 0); + + AddStep("seek smoothly beyond track length", () => Clock.SeekSmoothlyTo(Clock.TrackLength + 1000)); + AddAssert("time is clamped to track length", () => Clock.CurrentTime == Clock.TrackLength); + } + protected override void Dispose(bool isDisposing) { Beatmap.Disabled = false; From 58ecee543ad546c7c1e1f91ae6fb1187920f0b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 17 Aug 2021 23:00:10 +0200 Subject: [PATCH 200/366] Trim redundant default argument value --- osu.Game/Skinning/SkinManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 51aaac1f79..0f805990b9 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -95,7 +95,7 @@ namespace osu.Game.Skinning /// A newly allocated list of available . public List GetAllUsableSkins() { - var userSkins = GetAllUserSkins(false); + var userSkins = GetAllUserSkins(); userSkins.Insert(0, DefaultSkin.SkinInfo); userSkins.Insert(1, DefaultLegacySkin.SkinInfo); return userSkins; From 8c5d99ab21c71fe5e1c743835c8b5245c8b17246 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 04:16:57 +0300 Subject: [PATCH 201/366] Override `CreateInstance()` in osu! bindable subclasses Three bindables are left which don't have this overriden due to them already not having a value-only constructor and not supporting `GetBoundCopy()` properly: - `BeatmapDifficultyCache.BindableStarDifficulty`. - `TotalScoreBindable` - `TotalScoreStringBindable` I could add support for them by passing the required data to them, as they seem to be able to have that shared, but I'm hesitant to support something which was already broken and never used, not sure. --- osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs | 2 +- osu.Game/Rulesets/Mods/DifficultyBindable.cs | 2 +- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs index 186514e868..3978378c3a 100644 --- a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs +++ b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mods { // Intercept and extract the internal number bindable from DifficultyBindable. // This will provide bounds and precision specifications for the slider bar. - difficultyBindable = ((DifficultyBindable)value).GetBoundCopy(); + difficultyBindable = (DifficultyBindable)value.GetBoundCopy(); sliderDisplayCurrent.BindTo(difficultyBindable.CurrentNumber); base.Current = difficultyBindable; diff --git a/osu.Game/Rulesets/Mods/DifficultyBindable.cs b/osu.Game/Rulesets/Mods/DifficultyBindable.cs index 664b88eef4..e4304795f2 100644 --- a/osu.Game/Rulesets/Mods/DifficultyBindable.cs +++ b/osu.Game/Rulesets/Mods/DifficultyBindable.cs @@ -128,6 +128,6 @@ namespace osu.Game.Rulesets.Mods ExtendedLimits.UnbindFrom(otherDifficultyBindable.ExtendedLimits); } - public new DifficultyBindable GetBoundCopy() => new DifficultyBindable { BindTarget = this }; + protected override Bindable CreateInstance() => new DifficultyBindable(); } } diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index ff33f0c70d..dfe2992a7c 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -41,6 +41,8 @@ namespace osu.Game.Screens.Edit protected override int DefaultMaxValue => VALID_DIVISORS.Last(); protected override int DefaultPrecision => 1; + protected override Bindable CreateInstance() => new BindableBeatDivisor(); + /// /// Retrieves the appropriate colour for a beat divisor. /// From 5671820d92011d83f3d170df01e0f5f07fcc1837 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 10:35:34 +0900 Subject: [PATCH 202/366] 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 ec223f98c2..24d07b4588 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d4dba9330f..928620b32e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 7e514afe74..77f9052e85 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From f5923508564b8d24f3d9ca475c7144aa466b9332 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 04:59:08 +0300 Subject: [PATCH 203/366] Fix config pollution in HUD overlay test scene --- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 3017428039..4f15032c62 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -19,6 +19,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneHUDOverlay : OsuManualInputManagerTestScene { + private OsuConfigManager localConfig; + private HUDOverlay hudOverlay; [Cached] @@ -31,8 +33,14 @@ namespace osu.Game.Tests.Visual.Gameplay private Drawable hideTarget => hudOverlay.KeyCounter; private FillFlowContainer keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().First(); - [Resolved] - private OsuConfigManager config { get; set; } + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(localConfig = new OsuConfigManager(LocalStorage)); + } + + [SetUpSteps] + public void SetUp() => Schedule(() => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always)); [Test] public void TestComboCounterIncrementing() @@ -85,11 +93,7 @@ namespace osu.Game.Tests.Visual.Gameplay { createNew(); - HUDVisibilityMode originalConfigValue = HUDVisibilityMode.HideDuringGameplay; - - AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); - - AddStep("set hud to never show", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + AddStep("set hud to never show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); AddUntilStep("wait for fade", () => !hideTarget.IsPresent); @@ -98,37 +102,28 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("stop trigering", () => InputManager.ReleaseKey(Key.ControlLeft)); AddUntilStep("wait for fade", () => !hideTarget.IsPresent); - - AddStep("set original config value", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); } [Test] public void TestExternalHideDoesntAffectConfig() { - HUDVisibilityMode originalConfigValue = HUDVisibilityMode.HideDuringGameplay; - createNew(); - AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); - AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false); - AddAssert("config unchanged", () => originalConfigValue == config.Get(OsuSetting.HUDVisibilityMode)); + AddAssert("config unchanged", () => localConfig.GetBindable(OsuSetting.HUDVisibilityMode).IsDefault); AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true); - AddAssert("config unchanged", () => originalConfigValue == config.Get(OsuSetting.HUDVisibilityMode)); + AddAssert("config unchanged", () => localConfig.GetBindable(OsuSetting.HUDVisibilityMode).IsDefault); } [Test] public void TestChangeHUDVisibilityOnHiddenKeyCounter() { - bool keyCounterVisibleValue = false; - createNew(); - AddStep("save keycounter visible value", () => keyCounterVisibleValue = config.Get(OsuSetting.KeyOverlay)); - AddStep("set keycounter visible false", () => + AddStep("hide key overlay", () => { - config.SetValue(OsuSetting.KeyOverlay, false); + localConfig.SetValue(OsuSetting.KeyOverlay, false); hudOverlay.KeyCounter.AlwaysVisible.Value = false; }); @@ -139,24 +134,16 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true); AddUntilStep("hidetarget is visible", () => hideTarget.IsPresent); AddAssert("key counters still hidden", () => !keyCounterFlow.IsPresent); - - AddStep("return value", () => config.SetValue(OsuSetting.KeyOverlay, keyCounterVisibleValue)); } [Test] public void TestHiddenHUDDoesntBlockSkinnableComponentsLoad() { - HUDVisibilityMode originalConfigValue = default; - - AddStep("get original config value", () => originalConfigValue = config.Get(OsuSetting.HUDVisibilityMode)); - - AddStep("set hud to never show", () => config.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + AddStep("set hud to never show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); createNew(); AddUntilStep("wait for hud load", () => hudOverlay.IsLoaded); AddUntilStep("skinnable components loaded", () => hudOverlay.ChildrenOfType().Single().ComponentsLoaded); - - AddStep("set original config value", () => config.SetValue(OsuSetting.HUDVisibilityMode, originalConfigValue)); } private void createNew(Action action = null) @@ -175,5 +162,11 @@ namespace osu.Game.Tests.Visual.Gameplay Child = hudOverlay; }); } + + protected override void Dispose(bool isDisposing) + { + localConfig?.Dispose(); + base.Dispose(isDisposing); + } } } From 1fdaefef99d4b79cba8cbc428fb7d55cd5597cc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 12:45:08 +0900 Subject: [PATCH 204/366] Revert unnecessary changes --- osu.Game/Overlays/SettingsPanel.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index fea797287e..376e36ea4e 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -14,7 +14,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -180,7 +179,7 @@ namespace osu.Game.Overlays protected override void OnFocus(FocusEvent e) { - searchTextBox?.TakeFocus(); + searchTextBox.TakeFocus(); base.OnFocus(e); } @@ -274,8 +273,6 @@ namespace osu.Game.Overlays { public SearchContainer SearchContainer; - public new ScheduledDelegate Schedule(Action action) => Scheduler.AddDelayed(action, TransformDelay); - protected override FlowContainer CreateScrollContentContainer() => SearchContainer = new SearchContainer { From 5441fab6922bc05344b3797898502742d7d89dda Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 12:45:14 +0900 Subject: [PATCH 205/366] Avoid scheduling focus operation when not required --- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 4a42027964..06a40e7245 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -25,7 +25,7 @@ namespace osu.Game.Graphics.UserInterface if (!allowImmediateFocus) return; - Schedule(() => GetContainingInputManager().ChangeFocus(this)); + Scheduler.Add(() => GetContainingInputManager().ChangeFocus(this), false); } public bool HoldFocus From 6ed3e469f7549b0346314d31e606d2ff942e542c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 06:50:01 +0300 Subject: [PATCH 206/366] Fix wrong attribute used for setup method --- 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 4f15032c62..290ba3317b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay Dependencies.Cache(localConfig = new OsuConfigManager(LocalStorage)); } - [SetUpSteps] + [SetUp] public void SetUp() => Schedule(() => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Always)); [Test] From c66abf85f71d4a755262c805f06bccf7782b54d5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 14:04:44 +0900 Subject: [PATCH 207/366] Remove match header --- .../Match/MultiplayerMatchHeader.cs | 106 ------------------ .../Multiplayer/MultiplayerMatchSubScreen.cs | 14 --- 2 files changed, 120 deletions(-) delete mode 100644 osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchHeader.cs diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchHeader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchHeader.cs deleted file mode 100644 index bb351d06d3..0000000000 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchHeader.cs +++ /dev/null @@ -1,106 +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.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Online.API; -using osu.Game.Screens.OnlinePlay.Match.Components; -using osu.Game.Users.Drawables; -using osuTK; -using FontWeight = osu.Game.Graphics.FontWeight; -using OsuColour = osu.Game.Graphics.OsuColour; -using OsuFont = osu.Game.Graphics.OsuFont; - -namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match -{ - public class MultiplayerMatchHeader : OnlinePlayComposite - { - public const float HEIGHT = 50; - - public Action OpenSettings; - - private UpdateableAvatar avatar; - private LinkFlowContainer hostText; - private Button openSettingsButton; - - [Resolved] - private IAPIProvider api { get; set; } - - public MultiplayerMatchHeader() - { - RelativeSizeAxes = Axes.X; - Height = HEIGHT; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - InternalChildren = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - avatar = new UpdateableAvatar - { - Size = new Vector2(50), - Masking = true, - CornerRadius = 10, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30), - Current = { BindTarget = RoomName } - }, - hostText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 20)) - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - } - } - } - } - }, - openSettingsButton = new PurpleTriangleButton - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Size = new Vector2(150, HEIGHT), - Text = "Open settings", - Action = () => OpenSettings?.Invoke(), - Alpha = 0 - } - }; - - Host.BindValueChanged(host => - { - avatar.User = host.NewValue; - - hostText.Clear(); - - if (host.NewValue != null) - { - hostText.AddText("hosted by "); - hostText.AddUserLink(host.NewValue, s => s.Font = s.Font.With(weight: FontWeight.SemiBold)); - } - - openSettingsButton.Alpha = host.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0; - }, true); - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 09c2a22850..93377b221f 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -59,8 +59,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [CanBeNull] private IDisposable readyClickOperation; - // private GridContainer mainContent; - public MultiplayerMatchSubScreen(Room room) : base(room) { @@ -130,20 +128,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Child = new GridContainer { RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - }, Content = new[] { - new Drawable[] - { - new MultiplayerMatchHeader - { - OpenSettings = () => SettingsOverlay.Show() - } - }, new Drawable[] { new Container From 3d88a745cd2f5184e114447c329b89f45ca339ca Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 18 Aug 2021 14:27:05 +0900 Subject: [PATCH 208/366] Fix osu editor transforms not specified in the absolute time --- .../Edit/DrawableOsuEditorRuleset.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs index d4f1602a46..c89527d8bd 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs @@ -64,11 +64,14 @@ namespace osu.Game.Rulesets.Osu.Edit if (hitObject is DrawableHitCircle circle) { - circle.ApproachCircle - .FadeOutFromOne(EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION * 4) - .Expire(); + using (circle.BeginAbsoluteSequence(circle.HitStateUpdateTime)) + { + circle.ApproachCircle + .FadeOutFromOne(EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION * 4) + .Expire(); - circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint); + circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint); + } } if (hitObject is IHasMainCirclePiece mainPieceContainer) From 0853554c2403700be54db9763466788bd19379f8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 15:11:52 +0900 Subject: [PATCH 209/366] Fix settings overlay not being initially visible --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 3addf57048..9e729515d2 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -162,7 +162,10 @@ namespace osu.Game.Screens.OnlinePlay.Match } } }, - SettingsOverlay = CreateRoomSettingsOverlay() + SettingsOverlay = CreateRoomSettingsOverlay().With(s => + { + s.State.Value = room.RoomID.Value == null ? Visibility.Visible : Visibility.Hidden; + }) }, }, }, From 704af94d399517093b084809c7144d165f57965c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 15:12:16 +0900 Subject: [PATCH 210/366] Add edit button to room panel --- .../Lounge/Components/DrawableRoom.cs | 20 ++++--- .../Match/DrawableMultiplayerRoom.cs | 54 +++++++++++++++++++ .../Multiplayer/MultiplayerMatchSubScreen.cs | 5 +- 3 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Multiplayer/Match/DrawableMultiplayerRoom.cs diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index c8ecd65574..4e81739dc4 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -124,17 +124,23 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } + public bool FilteringActive { get; set; } + + protected readonly Container ButtonsContainer = new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X + }; + private readonly Bindable roomCategory = new Bindable(); + private readonly Bindable hasPassword = new Bindable(); private RecentParticipantsList recentParticipantsList; private RoomSpecialCategoryPill specialCategoryPill; - - public bool FilteringActive { get; set; } - private PasswordProtectedIcon passwordIcon; - private readonly Bindable hasPassword = new Bindable(); - public DrawableRoom(Room room) { Room = room; @@ -289,13 +295,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Origin = Anchor.CentreRight, AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, + Spacing = new Vector2(5), Padding = new MarginPadding { Right = 10, - Vertical = 5 + Vertical = 20, }, Children = new Drawable[] { + ButtonsContainer, recentParticipantsList = new RecentParticipantsList { Anchor = Anchor.CentreRight, diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/DrawableMultiplayerRoom.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/DrawableMultiplayerRoom.cs new file mode 100644 index 0000000000..84ae6108f6 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/DrawableMultiplayerRoom.cs @@ -0,0 +1,54 @@ +// 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.Framework.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osu.Game.Screens.OnlinePlay.Match.Components; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match +{ + public class DrawableMultiplayerRoom : DrawableRoom + { + public Action OnEdit; + + [Resolved] + private IAPIProvider api { get; set; } + + private readonly IBindable host = new Bindable(); + + private Drawable editButton; + + public DrawableMultiplayerRoom(Room room) + : base(room) + { + host.BindTo(room.Host); + } + + [BackgroundDependencyLoader] + private void load() + { + ButtonsContainer.Add(editButton = new PurpleTriangleButton + { + RelativeSizeAxes = Axes.Y, + Size = new Vector2(100, 1), + Text = "Edit", + Action = () => OnEdit?.Invoke() + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true); + } + + protected override bool ShouldBeConsideredForInput(Drawable child) => true; + } +} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 93377b221f..3cbc6c36b6 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -110,7 +110,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList(); } - protected override DrawableRoom CreateDrawableRoom(Room room) => new DrawableRoom(room); + protected override DrawableRoom CreateDrawableRoom(Room room) => new DrawableMultiplayerRoom(room) + { + OnEdit = () => SettingsOverlay.Show() + }; protected override Drawable CreateMainContent() => new Container { From 1ae4a1910a135a8c1084d332bbf2650fa13abdf2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 09:17:42 +0300 Subject: [PATCH 211/366] Cache mod settings rather than fetching everytime --- osu.Game/Rulesets/Mods/Mod.cs | 36 +++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index a99ddc6924..8c2a8a8e8b 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; @@ -129,6 +130,17 @@ namespace osu.Game.Rulesets.Mods [JsonIgnore] public virtual Type[] IncompatibleMods => Array.Empty(); + private IReadOnlyList settingsBacking; + + /// + /// A list of the all settings within this mod. + /// + internal IReadOnlyList Settings => + settingsBacking ??= this.GetSettingsSourceProperties() + .Select(p => p.Item2.GetValue(this)) + .Cast() + .ToList(); + /// /// Creates a copy of this initialised to a default state. /// @@ -191,10 +203,7 @@ namespace osu.Game.Rulesets.Mods if (ReferenceEquals(this, other)) return true; return GetType() == other.GetType() && - this.GetSettingsSourceProperties().All(pair => - EqualityComparer.Default.Equals( - ModUtils.GetSettingUnderlyingValue(pair.Item2.GetValue(this)), - ModUtils.GetSettingUnderlyingValue(pair.Item2.GetValue(other)))); + Settings.SequenceEqual(other.Settings, ModSettingsEqualityComparer.Default); } public override int GetHashCode() @@ -203,8 +212,8 @@ namespace osu.Game.Rulesets.Mods hashCode.Add(GetType()); - foreach (var (_, prop) in this.GetSettingsSourceProperties()) - hashCode.Add(ModUtils.GetSettingUnderlyingValue(prop.GetValue(this))); + foreach (var setting in Settings) + hashCode.Add(ModUtils.GetSettingUnderlyingValue(setting)); return hashCode.ToHashCode(); } @@ -213,5 +222,20 @@ namespace osu.Game.Rulesets.Mods /// Reset all custom settings for this mod back to their defaults. /// public virtual void ResetSettingsToDefaults() => CopyFrom((Mod)Activator.CreateInstance(GetType())); + + private class ModSettingsEqualityComparer : IEqualityComparer + { + public static ModSettingsEqualityComparer Default { get; } = new ModSettingsEqualityComparer(); + + public bool Equals(IBindable x, IBindable y) + { + object xValue = x == null ? null : ModUtils.GetSettingUnderlyingValue(x); + object yValue = y == null ? null : ModUtils.GetSettingUnderlyingValue(y); + + return EqualityComparer.Default.Equals(xValue, yValue); + } + + public int GetHashCode(IBindable obj) => ModUtils.GetSettingUnderlyingValue(obj).GetHashCode(); + } } } From 96b6670d1fe2e3018acdfe8ee0dd98a0981b5f6f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 09:18:03 +0300 Subject: [PATCH 212/366] Add mod benchmark --- osu.Game.Benchmarks/BenchmarkMod.cs | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 osu.Game.Benchmarks/BenchmarkMod.cs diff --git a/osu.Game.Benchmarks/BenchmarkMod.cs b/osu.Game.Benchmarks/BenchmarkMod.cs new file mode 100644 index 0000000000..050ddf36d5 --- /dev/null +++ b/osu.Game.Benchmarks/BenchmarkMod.cs @@ -0,0 +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 System; +using BenchmarkDotNet.Attributes; +using osu.Game.Rulesets.Osu.Mods; + +namespace osu.Game.Benchmarks +{ + public class BenchmarkMod : BenchmarkTest + { + private OsuModDoubleTime mod; + + [Params(1, 10, 100)] + public int Times { get; set; } + + [GlobalSetup] + public void GlobalSetup() + { + mod = new OsuModDoubleTime(); + } + + [Benchmark] + public int ModHashCode() + { + var hashCode = new HashCode(); + + for (int i = 0; i < Times; i++) + hashCode.Add(mod); + + return hashCode.ToHashCode(); + } + } +} From c5268c9a99d820d16534fc912e15cd02a1d08894 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 15:16:48 +0900 Subject: [PATCH 213/366] Simplify by reusing same room panel --- .../DrawableMatchRoom.cs} | 6 +++--- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 19 ++++++++++--------- .../Multiplayer/MultiplayerMatchSubScreen.cs | 6 ------ .../Playlists/PlaylistsRoomSubScreen.cs | 3 --- 4 files changed, 13 insertions(+), 21 deletions(-) rename osu.Game/Screens/OnlinePlay/{Multiplayer/Match/DrawableMultiplayerRoom.cs => Match/DrawableMatchRoom.cs} (89%) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/DrawableMultiplayerRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs similarity index 89% rename from osu.Game/Screens/OnlinePlay/Multiplayer/Match/DrawableMultiplayerRoom.cs rename to osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index 84ae6108f6..f7b4dd6920 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/DrawableMultiplayerRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -12,9 +12,9 @@ using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Users; using osuTK; -namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match +namespace osu.Game.Screens.OnlinePlay.Match { - public class DrawableMultiplayerRoom : DrawableRoom + public class DrawableMatchRoom : DrawableRoom { public Action OnEdit; @@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match private Drawable editButton; - public DrawableMultiplayerRoom(Room room) + public DrawableMatchRoom(Room room) : base(room) { host.BindTo(room.Host); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 9e729515d2..8dc5c0cc4a 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -19,7 +19,6 @@ using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match.Components; namespace osu.Game.Screens.OnlinePlay.Match @@ -64,7 +63,7 @@ namespace osu.Game.Screens.OnlinePlay.Match private readonly Room room; private ModSelectOverlay userModsSelectOverlay; - protected RoomSettingsOverlay SettingsOverlay { get; private set; } + private RoomSettingsOverlay settingsOverlay; protected RoomSubScreen(Room room) { @@ -123,7 +122,11 @@ namespace osu.Game.Screens.OnlinePlay.Match { new Drawable[] { - CreateDrawableRoom(room).With(d => d.MatchingFilter = true), + new DrawableMatchRoom(room) + { + MatchingFilter = true, + OnEdit = () => settingsOverlay.Show() + } }, null, new Drawable[] @@ -162,7 +165,7 @@ namespace osu.Game.Screens.OnlinePlay.Match } } }, - SettingsOverlay = CreateRoomSettingsOverlay().With(s => + settingsOverlay = CreateRoomSettingsOverlay().With(s => { s.State.Value = room.RoomID.Value == null ? Visibility.Visible : Visibility.Hidden; }) @@ -184,7 +187,7 @@ namespace osu.Game.Screens.OnlinePlay.Match // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. mainContent.Hide(); - SettingsOverlay.State.BindValueChanged(visibility => + settingsOverlay.State.BindValueChanged(visibility => { if (visibility.NewValue == Visibility.Hidden) mainContent.Show(); @@ -218,9 +221,9 @@ namespace osu.Game.Screens.OnlinePlay.Match return true; } - if (SettingsOverlay.State.Value == Visibility.Visible) + if (settingsOverlay.State.Value == Visibility.Visible) { - SettingsOverlay.Hide(); + settingsOverlay.Hide(); return true; } @@ -358,8 +361,6 @@ namespace osu.Game.Screens.OnlinePlay.Match track.Looping = false; } - protected abstract DrawableRoom CreateDrawableRoom(Room room); - protected abstract Drawable CreateMainContent(); protected abstract Drawable CreateFooter(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 3cbc6c36b6..73c8053c1a 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -22,7 +22,6 @@ using osu.Game.Overlays.Dialog; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.OnlinePlay.Components; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; @@ -110,11 +109,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList(); } - protected override DrawableRoom CreateDrawableRoom(Room room) => new DrawableMultiplayerRoom(room) - { - OnEdit = () => SettingsOverlay.Show() - }; - protected override Drawable CreateMainContent() => new Container { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 7af74e7e64..c655f49820 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -14,7 +14,6 @@ using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.Play; @@ -298,8 +297,6 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Exited = () => leaderboard.RefreshScores() }); - protected override DrawableRoom CreateDrawableRoom(Room room) => new DrawableRoom(room); - protected override Drawable CreateMainContent() => Empty(); protected override Drawable CreateFooter() => Empty(); From 228ad98b39ad6056eb387ed9e478b4de92db02fa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 15:27:23 +0900 Subject: [PATCH 214/366] Remove extra corner radius on DrawableRoom --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 4e81739dc4..b627dfbb8e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -149,7 +149,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Height = height; Masking = true; - CornerRadius = corner_radius + SELECTION_BORDER_WIDTH / 2; + CornerRadius = corner_radius; EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, From 744b6749d18ca282ba3eb6426b950ecd5cb071e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 15:29:01 +0900 Subject: [PATCH 215/366] Resolve room settings layout issues --- .../Match/Components/RoomSettingsOverlay.cs | 3 +++ osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 12 +++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index eec512347b..86687d7da8 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -31,6 +31,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components { RelativeSizeAxes = Axes.Both; Masking = true; + CornerRadius = 10; } [BackgroundDependencyLoader] @@ -47,12 +48,14 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components { base.PopIn(); Settings.MoveToY(0, TRANSITION_DURATION, Easing.OutQuint); + Settings.FadeIn(TRANSITION_DURATION / 2); } protected override void PopOut() { base.PopOut(); Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine); + Settings.Delay(TRANSITION_DURATION / 2).FadeOut(TRANSITION_DURATION / 2); } public bool OnPressed(GlobalAction action) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 8dc5c0cc4a..9c7b255213 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -165,10 +165,16 @@ namespace osu.Game.Screens.OnlinePlay.Match } } }, - settingsOverlay = CreateRoomSettingsOverlay().With(s => + new Container { - s.State.Value = room.RoomID.Value == null ? Visibility.Visible : Visibility.Hidden; - }) + RelativeSizeAxes = Axes.Both, + // Resolves 1px masking errors between the settings overlay and the room panel. + Padding = new MarginPadding(-1), + Child = settingsOverlay = CreateRoomSettingsOverlay().With(s => + { + s.State.Value = room.RoomID.Value == null ? Visibility.Visible : Visibility.Hidden; + }) + } }, }, }, From 90a1be2e6158b2f2cb7bdb6533d0fa22e77056aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 15:54:33 +0900 Subject: [PATCH 216/366] Move paddings up one level --- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 7 +- .../Multiplayer/MultiplayerMatchSubScreen.cs | 216 ++++++++---------- 2 files changed, 106 insertions(+), 117 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 9c7b255213..8e6cfe2acb 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -147,7 +147,12 @@ namespace osu.Game.Screens.OnlinePlay.Match Colour = Color4Extensions.FromHex(@"3e3a44") // This is super temporary. }, }, - CreateMainContent(), + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(10), + Child = CreateMainContent(), + }, new Container { Anchor = Anchor.BottomLeft, diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 73c8053c1a..b9bcb27d60 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -109,115 +109,99 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList(); } - protected override Drawable CreateMainContent() => new Container + protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + Content = new[] { - new Container + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Horizontal = 10, - Vertical = 10 - }, - Child = new GridContainer + new Container { RelativeSizeAxes = Axes.Both, - Content = new[] + Padding = new MarginPadding { Horizontal = 5, Vertical = 10 }, + Child = new GridContainer { - new Drawable[] + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - new Container + new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 400), + new Dimension(), + new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 600), + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 5, Vertical = 10 }, - Child = new GridContainer + // Main left column + new GridContainer { RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + RowDimensions = new[] { - new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 400), - new Dimension(), - new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 600), + new Dimension(GridSizeMode.AutoSize) }, Content = new[] { + new Drawable[] { new ParticipantsListHeader() }, new Drawable[] { - // Main left column - new GridContainer + new ParticipantsList { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] { new ParticipantsListHeader() }, - new Drawable[] - { - new ParticipantsList - { - RelativeSizeAxes = Axes.Both - }, - } - } + RelativeSizeAxes = Axes.Both }, - // Spacer - null, - // Main right column - new FillFlowContainer + } + } + }, + // Spacer + null, + // Main right column + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new[] + new OverlinedHeader("Beatmap"), + new BeatmapSelectionControl { RelativeSizeAxes = Axes.X } + } + }, + UserModsSection = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 10 }, + Children = new Drawable[] + { + new OverlinedHeader("Extra mods"), + new FillFlowContainer { - new FillFlowContainer + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + new UserModSelectButton { - new OverlinedHeader("Beatmap"), - new BeatmapSelectionControl { RelativeSizeAxes = Axes.X } - } - }, - UserModsSection = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 10 }, - Children = new Drawable[] + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 90, + Text = "Select", + Action = ShowUserModSelect, + }, + new ModDisplay { - new OverlinedHeader("Extra mods"), - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new UserModSelectButton - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Width = 90, - Text = "Select", - Action = ShowUserModSelect, - }, - new ModDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Current = UserMods, - Scale = new Vector2(0.8f), - }, - } - } - } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = UserMods, + Scale = new Vector2(0.8f), + }, } } } @@ -225,27 +209,27 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } } - }, - new Drawable[] - { - new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] { new OverlinedHeader("Chat") }, - new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } - } - } } - }, + } } }, - } + new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] { new OverlinedHeader("Chat") }, + new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } + } + } + } + }, }; protected override Drawable CreateFooter() => new MultiplayerMatchFooter @@ -444,19 +428,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (client != null) - { - client.RoomUpdated -= onRoomUpdated; - client.LoadRequested -= onLoadRequested; - } - - modSettingChangeTracker?.Dispose(); - } - public void PresentBeatmap(WorkingBeatmap beatmap, RulesetInfo ruleset) { if (!this.IsCurrentScreen()) @@ -472,5 +443,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer this.Push(new MultiplayerMatchSongSelect(beatmap, ruleset)); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (client != null) + { + client.RoomUpdated -= onRoomUpdated; + client.LoadRequested -= onLoadRequested; + } + + modSettingChangeTracker?.Dispose(); + } } } From dc44cc0eb34783f306437bd90716c914ec7c0174 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 15:32:59 +0900 Subject: [PATCH 217/366] Update scenarios to use new `TestRunHeadlessGameHost` where feasible --- .../Collections/IO/ImportCollectionsTest.cs | 5 +++-- .../NonVisual/CustomDataDirectoryTest.cs | 15 ++++++++++++--- osu.Game/Tests/CleanRunHeadlessGameHost.cs | 4 ++-- osu.Game/Tests/Visual/OsuTestScene.cs | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs index 8f5ebf53bd..d87ac29d75 100644 --- a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs +++ b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs @@ -7,6 +7,7 @@ using System.Text; using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Platform; +using osu.Framework.Testing; using osu.Game.Tests.Resources; namespace osu.Game.Tests.Collections.IO @@ -127,7 +128,7 @@ namespace osu.Game.Tests.Collections.IO [Test] public async Task TestSaveAndReload() { - using (HeadlessGameHost host = new CleanRunHeadlessGameHost()) + using (HeadlessGameHost host = new TestRunHeadlessGameHost("TestSaveAndReload", bypassCleanup: true)) { try { @@ -148,7 +149,7 @@ namespace osu.Game.Tests.Collections.IO } } - using (HeadlessGameHost host = new HeadlessGameHost("TestSaveAndReload")) + using (HeadlessGameHost host = new TestRunHeadlessGameHost("TestSaveAndReload")) { try { diff --git a/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs b/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs index 4c44e2ec72..c9f5774735 100644 --- a/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs +++ b/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs @@ -6,10 +6,10 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; using NUnit.Framework; -using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Platform; +using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.IO; @@ -278,7 +278,7 @@ namespace osu.Game.Tests.NonVisual private static string getDefaultLocationFor(string testTypeName) { - string path = Path.Combine(RuntimeInfo.StartupDirectory, "headless", testTypeName); + string path = Path.Combine(TestRunHeadlessGameHost.TemporaryTestDirectory, testTypeName); if (Directory.Exists(path)) Directory.Delete(path, true); @@ -288,7 +288,7 @@ namespace osu.Game.Tests.NonVisual private string prepareCustomPath(string suffix = "") { - string path = Path.Combine(RuntimeInfo.StartupDirectory, $"custom-path{suffix}"); + string path = Path.Combine(TestRunHeadlessGameHost.TemporaryTestDirectory, $"custom-path{suffix}"); if (Directory.Exists(path)) Directory.Delete(path, true); @@ -308,6 +308,15 @@ namespace osu.Game.Tests.NonVisual InitialStorage = new DesktopStorage(defaultStorageLocation, this); InitialStorage.DeleteDirectory(string.Empty); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + // the storage may have changed from the initial location. + // this handles cleanup of the initial location. + InitialStorage.DeleteDirectory(string.Empty); + } } } } diff --git a/osu.Game/Tests/CleanRunHeadlessGameHost.cs b/osu.Game/Tests/CleanRunHeadlessGameHost.cs index 03ab94d1da..d7ab769ac4 100644 --- a/osu.Game/Tests/CleanRunHeadlessGameHost.cs +++ b/osu.Game/Tests/CleanRunHeadlessGameHost.cs @@ -2,14 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using System.Runtime.CompilerServices; -using osu.Framework.Platform; +using osu.Framework.Testing; namespace osu.Game.Tests { /// /// A headless host which cleans up before running (removing any remnants from a previous execution). /// - public class CleanRunHeadlessGameHost : HeadlessGameHost + public class CleanRunHeadlessGameHost : TestRunHeadlessGameHost { /// /// Create a new instance. diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 57e400a77e..ef1a35ffa5 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -155,7 +155,7 @@ namespace osu.Game.Tests.Visual } localStorage = - new Lazy(() => isolatedHostStorage ?? new NativeStorage(Path.Combine(RuntimeInfo.StartupDirectory, $"{GetType().Name}-{Guid.NewGuid()}"))); + new Lazy(() => isolatedHostStorage ?? new TemporaryNativeStorage($"{GetType().Name}-{Guid.NewGuid()}")); } [Resolved] From 568f1fd345fd7f51660623c90916036aa84dbdce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 16:09:00 +0900 Subject: [PATCH 218/366] Fix initial RoomId state not being handled correctly --- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 49 ++++++++++--------- .../Multiplayer/MultiplayerMatchSubScreen.cs | 4 -- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 8e6cfe2acb..ae92ab92c1 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -44,6 +44,8 @@ namespace osu.Game.Screens.OnlinePlay.Match /// protected readonly Bindable> UserMods = new Bindable>(Array.Empty()); + protected readonly IBindable RoomId = new Bindable(); + [Resolved] private MusicController music { get; set; } @@ -60,14 +62,15 @@ namespace osu.Game.Screens.OnlinePlay.Match protected IBindable BeatmapAvailability => BeatmapAvailabilityTracker.Availability; - private readonly Room room; + public readonly Room Room; private ModSelectOverlay userModsSelectOverlay; private RoomSettingsOverlay settingsOverlay; + private Drawable mainContent; protected RoomSubScreen(Room room) { - this.room = room; + Room = room; Padding = new MarginPadding { Top = Header.HEIGHT }; @@ -75,6 +78,8 @@ namespace osu.Game.Screens.OnlinePlay.Match { SelectedItem = { BindTarget = SelectedItem } }; + + RoomId.BindTo(room.RoomID); } [BackgroundDependencyLoader] @@ -82,8 +87,6 @@ namespace osu.Game.Screens.OnlinePlay.Match { sampleStart = audio.Samples.Get(@"SongSelect/confirm-selection"); - Drawable mainContent; - InternalChildren = new Drawable[] { BeatmapAvailabilityTracker, @@ -122,7 +125,7 @@ namespace osu.Game.Screens.OnlinePlay.Match { new Drawable[] { - new DrawableMatchRoom(room) + new DrawableMatchRoom(Room) { MatchingFilter = true, OnEdit = () => settingsOverlay.Show() @@ -175,10 +178,7 @@ namespace osu.Game.Screens.OnlinePlay.Match RelativeSizeAxes = Axes.Both, // Resolves 1px masking errors between the settings overlay and the room panel. Padding = new MarginPadding(-1), - Child = settingsOverlay = CreateRoomSettingsOverlay().With(s => - { - s.State.Value = room.RoomID.Value == null ? Visibility.Visible : Visibility.Hidden; - }) + Child = settingsOverlay = CreateRoomSettingsOverlay() } }, }, @@ -191,25 +191,28 @@ namespace osu.Game.Screens.OnlinePlay.Match } } }; - - if (room.RoomID.Value == null) - { - // A new room is being created. - // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. - mainContent.Hide(); - - settingsOverlay.State.BindValueChanged(visibility => - { - if (visibility.NewValue == Visibility.Hidden) - mainContent.Show(); - }, true); - } } protected override void LoadComplete() { base.LoadComplete(); + RoomId.BindValueChanged(id => + { + if (id.NewValue == null) + { + // A new room is being created. + // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. + mainContent.Hide(); + settingsOverlay.Show(); + } + else + { + mainContent.Show(); + settingsOverlay.Hide(); + } + }, true); + SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(selectedItemChanged)); managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy(); @@ -220,7 +223,7 @@ namespace osu.Game.Screens.OnlinePlay.Match public override bool OnBackButton() { - if (room.RoomID.Value == null) + if (Room.RoomID.Value == null) { // room has not been created yet; exit immediately. return base.OnBackButton(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index b9bcb27d60..f8e5d7d901 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -42,8 +42,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override string ShortTitle => "room"; - public readonly Room Room; - [Resolved] private MultiplayerClient client { get; set; } @@ -61,8 +59,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public MultiplayerMatchSubScreen(Room room) : base(room) { - Room = room; - Title = room.RoomID.Value == null ? "New room" : room.Name.Value; Activity.Value = new UserActivity.InLobby(room); } From 66e11fe75eb0424af82fc03c384d372df7304fc2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 16:09:15 +0900 Subject: [PATCH 219/366] Initial integration of playlists with the new structure --- .../Playlists/PlaylistsRoomSubScreen.cs | 390 ++++++++---------- 1 file changed, 166 insertions(+), 224 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index c655f49820..bf0107d3c3 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -30,18 +30,13 @@ namespace osu.Game.Screens.OnlinePlay.Playlists public override string ShortTitle => "playlist"; - [Resolved(typeof(Room), nameof(Room.RoomID))] - private Bindable roomId { get; set; } - - [Resolved(typeof(Room), nameof(Room.Playlist))] - private BindableList playlist { get; set; } + [Resolved] + private IAPIProvider api { get; set; } private readonly IBindable isIdle = new BindableBool(); - private RoomSettingsOverlay settingsOverlay; private MatchLeaderboard leaderboard; private OverlinedHeader participantsHeader; - private GridContainer mainContent; private SelectionPollingComponent selectionPollingComponent; public PlaylistsRoomSubScreen(Room room) @@ -57,231 +52,21 @@ namespace osu.Game.Screens.OnlinePlay.Playlists if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); - AddRangeInternal(new Drawable[] - { - selectionPollingComponent = new SelectionPollingComponent(), - mainContent = new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Horizontal = 105, - Vertical = 20 - }, - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - }, - Content = new[] - { - new Drawable[] { new Match.Components.Header() }, - new Drawable[] - { - participantsHeader = new OverlinedHeader("Participants") - { - ShowLine = false - } - }, - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 5 }, - Child = new ParticipantsDisplay(Direction.Horizontal) - { - Details = { BindTarget = participantsHeader.Details } - } - } - }, - new Drawable[] - { - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 5 }, - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { new OverlinedPlaylistHeader(), }, - new Drawable[] - { - new DrawableRoomPlaylistWithResults - { - RelativeSizeAxes = Axes.Both, - Items = { BindTarget = playlist }, - SelectedItem = { BindTarget = SelectedItem }, - RequestShowResults = item => - { - Debug.Assert(roomId.Value != null); - ParentScreen?.Push(new PlaylistsResultsScreen(null, roomId.Value.Value, item, false)); - } - } - }, - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - } - } - }, - null, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new[] - { - UserModsSection = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Bottom = 10 }, - Children = new Drawable[] - { - new OverlinedHeader("Extra mods"), - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new UserModSelectButton - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Width = 90, - Text = "Select", - Action = ShowUserModSelect, - }, - new ModDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Current = UserMods, - Scale = new Vector2(0.8f), - }, - } - } - } - }, - }, - new Drawable[] - { - new OverlinedHeader("Leaderboard") - }, - new Drawable[] { leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }, }, - new Drawable[] { new OverlinedHeader("Chat"), }, - new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Relative, size: 0.4f, minSize: 120), - } - }, - null - }, - }, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 400), - new Dimension(), - new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 600), - new Dimension(), - } - } - } - }, - } - } - }, - new Drawable[] - { - new Footer { OnStart = StartPlay } - } - }, - RowDimensions = new[] - { - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - } - }, - settingsOverlay = new PlaylistsRoomSettingsOverlay - { - RelativeSizeAxes = Axes.Both, - EditPlaylist = () => - { - if (this.IsCurrentScreen()) - this.Push(new PlaylistsSongSelect()); - }, - State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden } - } - }); - - if (roomId.Value == null) - { - // A new room is being created. - // The main content should be hidden until the settings overlay is hidden, signaling the room is ready to be displayed. - mainContent.Hide(); - - settingsOverlay.State.BindValueChanged(visibility => - { - if (visibility.NewValue == Visibility.Hidden) - mainContent.Show(); - }, true); - } + AddInternal(selectionPollingComponent = new SelectionPollingComponent()); } - [Resolved] - private IAPIProvider api { get; set; } - protected override void LoadComplete() { base.LoadComplete(); isIdle.BindValueChanged(_ => updatePollingRate(), true); - - roomId.BindValueChanged(id => + RoomId.BindValueChanged(id => { - if (id.NewValue == null) - settingsOverlay.Show(); - else + if (id.NewValue != null) { - settingsOverlay.Hide(); - // Set the first playlist item. // This is scheduled since updating the room and playlist may happen in an arbitrary order (via Room.CopyFrom()). - Schedule(() => SelectedItem.Value = playlist.FirstOrDefault()); + Schedule(() => SelectedItem.Value = Room.Playlist.FirstOrDefault()); } }, true); } @@ -297,10 +82,167 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Exited = () => leaderboard.RefreshScores() }); - protected override Drawable CreateMainContent() => Empty(); + protected override Drawable CreateMainContent() => new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + }, + Content = new[] + { + new Drawable[] { new Match.Components.Header() }, + new Drawable[] + { + participantsHeader = new OverlinedHeader("Participants") + { + ShowLine = false + } + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 5 }, + Child = new ParticipantsDisplay(Direction.Horizontal) + { + Details = { BindTarget = participantsHeader.Details } + } + } + }, + new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 5 }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { new OverlinedPlaylistHeader(), }, + new Drawable[] + { + new DrawableRoomPlaylistWithResults + { + RelativeSizeAxes = Axes.Both, + Items = { BindTarget = Room.Playlist }, + SelectedItem = { BindTarget = SelectedItem }, + RequestShowResults = item => + { + Debug.Assert(RoomId.Value != null); + ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item, false)); + } + } + }, + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + } + } + }, + null, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new[] + { + UserModsSection = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Bottom = 10 }, + Children = new Drawable[] + { + new OverlinedHeader("Extra mods"), + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new UserModSelectButton + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 90, + Text = "Select", + Action = ShowUserModSelect, + }, + new ModDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = UserMods, + Scale = new Vector2(0.8f), + }, + } + } + } + }, + }, + new Drawable[] + { + new OverlinedHeader("Leaderboard") + }, + new Drawable[] { leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }, }, + new Drawable[] { new OverlinedHeader("Chat"), }, + new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Relative, size: 0.4f, minSize: 120), + } + }, + null + }, + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 400), + new Dimension(), + new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 600), + new Dimension(), + } + } + } + }, + }; - protected override Drawable CreateFooter() => Empty(); + protected override Drawable CreateFooter() => new Footer + { + OnStart = StartPlay + }; - protected override RoomSettingsOverlay CreateRoomSettingsOverlay() => new PlaylistsRoomSettingsOverlay(); + protected override RoomSettingsOverlay CreateRoomSettingsOverlay() => new PlaylistsRoomSettingsOverlay + { + EditPlaylist = () => + { + if (this.IsCurrentScreen()) + this.Push(new PlaylistsSongSelect()); + }, + }; } } From 87a5922f0eef0eb69becbdf3a1ea1b12d3ceb501 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 16:26:45 +0900 Subject: [PATCH 220/366] Remove participants from playlists screen --- .../Playlists/PlaylistsRoomSubScreen.cs | 193 +++++++----------- 1 file changed, 76 insertions(+), 117 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index bf0107d3c3..d799f09972 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -36,7 +36,6 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private readonly IBindable isIdle = new BindableBool(); private MatchLeaderboard leaderboard; - private OverlinedHeader participantsHeader; private SelectionPollingComponent selectionPollingComponent; public PlaylistsRoomSubScreen(Room room) @@ -85,150 +84,110 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - }, Content = new[] { - new Drawable[] { new Match.Components.Header() }, - new Drawable[] - { - participantsHeader = new OverlinedHeader("Participants") - { - ShowLine = false - } - }, new Drawable[] { new Container { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 5 }, - Child = new ParticipantsDisplay(Direction.Horizontal) + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 5 }, + Child = new GridContainer { - Details = { BindTarget = participantsHeader.Details } + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { new OverlinedPlaylistHeader(), }, + new Drawable[] + { + new DrawableRoomPlaylistWithResults + { + RelativeSizeAxes = Axes.Both, + Items = { BindTarget = Room.Playlist }, + SelectedItem = { BindTarget = SelectedItem }, + RequestShowResults = item => + { + Debug.Assert(RoomId.Value != null); + ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item, false)); + } + } + }, + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + } } - } - }, - new Drawable[] - { + }, + null, new GridContainer { RelativeSizeAxes = Axes.Both, Content = new[] { - new Drawable[] + new[] { - new Container + UserModsSection = new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 5 }, - Child = new GridContainer + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Bottom = 10 }, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Content = new[] + new OverlinedHeader("Extra mods"), + new FillFlowContainer { - new Drawable[] { new OverlinedPlaylistHeader(), }, - new Drawable[] + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] { - new DrawableRoomPlaylistWithResults + new UserModSelectButton { - RelativeSizeAxes = Axes.Both, - Items = { BindTarget = Room.Playlist }, - SelectedItem = { BindTarget = SelectedItem }, - RequestShowResults = item => - { - Debug.Assert(RoomId.Value != null); - ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item, false)); - } - } - }, - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 90, + Text = "Select", + Action = ShowUserModSelect, + }, + new ModDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = UserMods, + Scale = new Vector2(0.8f), + }, + } } } }, - null, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new[] - { - UserModsSection = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Bottom = 10 }, - Children = new Drawable[] - { - new OverlinedHeader("Extra mods"), - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new UserModSelectButton - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Width = 90, - Text = "Select", - Action = ShowUserModSelect, - }, - new ModDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Current = UserMods, - Scale = new Vector2(0.8f), - }, - } - } - } - }, - }, - new Drawable[] - { - new OverlinedHeader("Leaderboard") - }, - new Drawable[] { leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }, }, - new Drawable[] { new OverlinedHeader("Chat"), }, - new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Relative, size: 0.4f, minSize: 120), - } - }, - null }, + new Drawable[] + { + new OverlinedHeader("Leaderboard") + }, + new Drawable[] { leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }, }, + new Drawable[] { new OverlinedHeader("Chat"), }, + new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } }, - ColumnDimensions = new[] + RowDimensions = new[] { - new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 400), - new Dimension(), - new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 600), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), new Dimension(), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Relative, size: 0.4f, minSize: 120), } - } - } + }, + }, }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 400), + new Dimension(), + new Dimension(GridSizeMode.Relative, size: 0.5f, maxSize: 600), + } }; protected override Drawable CreateFooter() => new Footer From 2758a83d5556cbea8e4d7b95977b053b8dcb6702 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 16:23:02 +0900 Subject: [PATCH 221/366] Fix `TestSettingsMigration`'s usage of `RecycleLocalStorage` --- .../Input/ConfineMouseTrackerTest.cs | 2 +- .../Menus/TestSceneMusicActionHandling.cs | 1 - .../Visual/Menus/TestSceneSideOverlays.cs | 1 - .../Visual/Navigation/OsuGameTestScene.cs | 9 +++++- .../Visual/Navigation/TestSceneOsuGame.cs | 32 ++++++++++++------- .../Navigation/TestSettingsMigration.cs | 7 ++-- .../TestSceneBeatmapRecommendations.cs | 1 - osu.Game/Tests/Visual/OsuTestScene.cs | 7 ++-- 8 files changed, 37 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs index 27cece42e8..b612899d79 100644 --- a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs +++ b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs @@ -8,7 +8,7 @@ using osu.Framework.Input; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Input; -using osu.Game.Tests.Visual.Navigation; +using osu.Game.Tests.Visual; namespace osu.Game.Tests.Input { diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index aaf3323432..9037338e23 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -10,7 +10,6 @@ using osu.Game.Database; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osu.Game.Tests.Resources; -using osu.Game.Tests.Visual.Navigation; namespace osu.Game.Tests.Visual.Menus { diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs index e58f85b0b3..5230e026bc 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Framework.Testing; using osu.Game.Overlays; -using osu.Game.Tests.Visual.Navigation; namespace osu.Game.Tests.Visual.Menus { diff --git a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs index c9a1471e41..e392301568 100644 --- a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs +++ b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs @@ -62,7 +62,7 @@ namespace osu.Game.Tests.Visual.Navigation Game.Dispose(); } - RecycleLocalStorage(); + RecycleLocalStorage(false); CreateGame(); }); @@ -73,6 +73,13 @@ namespace osu.Game.Tests.Visual.Navigation ConfirmAtMainMenu(); } + [TearDownSteps] + public void TearDownSteps() + { + AddStep("exit game", () => Game.Exit()); + AddUntilStep("wait for game exit", () => Game.Parent == null); + } + protected void CreateGame() { Game = new TestOsuGame(LocalStorage, API); diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index 26641214b1..48e68b03fb 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Framework.Platform; +using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; @@ -88,25 +89,32 @@ namespace osu.Game.Tests.Visual.Navigation [Resolved] private OsuGameBase gameBase { get; set; } - [BackgroundDependencyLoader] - private void load(GameHost host) - { - game = new OsuGame(); - game.SetHost(host); + [Resolved] + private GameHost host { get; set; } - Children = new Drawable[] + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create game", () => { - new Box + game = new OsuGame(); + game.SetHost(host); + + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - game - }; + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + game + }; + }); AddUntilStep("wait for load", () => game.IsLoaded); } + [Test] public void TestNullRulesetHandled() { diff --git a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs index c1c968e862..7e3d8290be 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs @@ -9,9 +9,12 @@ namespace osu.Game.Tests.Visual.Navigation { public class TestSettingsMigration : OsuGameTestScene { - public override void RecycleLocalStorage() + public override void RecycleLocalStorage(bool isDisposing) { - base.RecycleLocalStorage(); + base.RecycleLocalStorage(isDisposing); + + if (isDisposing) + return; using (var config = new OsuConfigManager(LocalStorage)) { diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs index 5e2d5eba5d..53cb628bb3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs @@ -14,7 +14,6 @@ using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; -using osu.Game.Tests.Visual.Navigation; using osu.Game.Users; namespace osu.Game.Tests.Visual.SongSelect diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index ef1a35ffa5..ef9181c8a6 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -7,7 +7,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using JetBrains.Annotations; -using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -100,7 +99,7 @@ namespace osu.Game.Tests.Visual return factory; }); - RecycleLocalStorage(); + RecycleLocalStorage(false); var baseDependencies = base.CreateChildDependencies(parent); @@ -140,7 +139,7 @@ namespace osu.Game.Tests.Visual protected virtual bool UseFreshStoragePerRun => false; - public virtual void RecycleLocalStorage() + public virtual void RecycleLocalStorage(bool isDisposing) { if (localStorage?.IsValueCreated == true) { @@ -199,7 +198,7 @@ namespace osu.Game.Tests.Visual if (contextFactory?.IsValueCreated == true) contextFactory.Value.ResetDatabase(); - RecycleLocalStorage(); + RecycleLocalStorage(true); } protected override ITestSceneTestRunner CreateRunner() => new OsuTestSceneTestRunner(); From 4725b802b017c19ecb31c9526a49e544f33377be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 16:38:54 +0900 Subject: [PATCH 222/366] Share `OsuGameTestScene` with implementations across template projects --- .../TestSceneOsuGame.cs | 23 +----------- .../TestSceneOsuGame.cs | 23 +----------- .../TestSceneOsuGame.cs | 23 +----------- .../TestSceneOsuGame.cs | 23 +----------- .../Visual/Navigation/TestSceneOsuGame.cs | 37 +------------------ .../Tests/Visual}/OsuGameTestScene.cs | 7 +--- 6 files changed, 7 insertions(+), 129 deletions(-) rename {osu.Game.Tests/Visual/Navigation => osu.Game/Tests/Visual}/OsuGameTestScene.cs (93%) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs index 9c512a01ea..fb63f69f72 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs @@ -1,32 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Platform; using osu.Game.Tests.Visual; -using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyFreeform.Tests { - public class TestSceneOsuGame : OsuTestScene + public class TestSceneOsuGame : OsuGameTestScene { - [BackgroundDependencyLoader] - private void load(GameHost host, OsuGameBase gameBase) - { - OsuGame game = new OsuGame(); - game.SetHost(host); - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - game - }; - } } } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs index 270d906b01..a99a400afa 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs @@ -1,32 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Platform; using osu.Game.Tests.Visual; -using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.Tests { - public class TestSceneOsuGame : OsuTestScene + public class TestSceneOsuGame : OsuGameTestScene { - [BackgroundDependencyLoader] - private void load(GameHost host, OsuGameBase gameBase) - { - OsuGame game = new OsuGame(); - game.SetHost(host); - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - game - }; - } } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs index aed6abb6bf..debdc14b57 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs @@ -1,32 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Platform; using osu.Game.Tests.Visual; -using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyScrolling.Tests { - public class TestSceneOsuGame : OsuTestScene + public class TestSceneOsuGame : OsuGameTestScene { - [BackgroundDependencyLoader] - private void load(GameHost host, OsuGameBase gameBase) - { - OsuGame game = new OsuGame(); - game.SetHost(host); - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - game - }; - } } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs index 270d906b01..a99a400afa 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs @@ -1,32 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Platform; using osu.Game.Tests.Visual; -using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.Tests { - public class TestSceneOsuGame : OsuTestScene + public class TestSceneOsuGame : OsuGameTestScene { - [BackgroundDependencyLoader] - private void load(GameHost host, OsuGameBase gameBase) - { - OsuGame game = new OsuGame(); - game.SetHost(host); - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - game - }; - } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index 48e68b03fb..d3f1a852d1 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -6,11 +6,7 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; -using osu.Framework.Platform; -using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; @@ -28,12 +24,11 @@ using osu.Game.Scoring; using osu.Game.Screens.Menu; using osu.Game.Skinning; using osu.Game.Utils; -using osuTK.Graphics; namespace osu.Game.Tests.Visual.Navigation { [TestFixture] - public class TestSceneOsuGame : OsuTestScene + public class TestSceneOsuGame : OsuGameTestScene { private IReadOnlyList requiredGameDependencies => new[] { @@ -84,37 +79,9 @@ namespace osu.Game.Tests.Visual.Navigation typeof(PreviewTrackManager), }; - private OsuGame game; - [Resolved] private OsuGameBase gameBase { get; set; } - [Resolved] - private GameHost host { get; set; } - - [SetUpSteps] - public void SetUpSteps() - { - AddStep("create game", () => - { - game = new OsuGame(); - game.SetHost(host); - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - game - }; - }); - - AddUntilStep("wait for load", () => game.IsLoaded); - } - - [Test] public void TestNullRulesetHandled() { @@ -150,7 +117,7 @@ namespace osu.Game.Tests.Visual.Navigation { foreach (var type in requiredGameDependencies) { - if (game.Dependencies.Get(type) == null) + if (Game.Dependencies.Get(type) == null) throw new InvalidOperationException($"{type} has not been cached"); } diff --git a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs b/osu.Game/Tests/Visual/OsuGameTestScene.cs similarity index 93% rename from osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs rename to osu.Game/Tests/Visual/OsuGameTestScene.cs index e392301568..f38aaa9358 100644 --- a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGameTestScene.cs @@ -22,9 +22,8 @@ using osu.Game.Scoring; using osu.Game.Screens; using osu.Game.Screens.Menu; using osuTK.Graphics; -using IntroSequence = osu.Game.Configuration.IntroSequence; -namespace osu.Game.Tests.Visual.Navigation +namespace osu.Game.Tests.Visual { /// /// A scene which tests full game flow. @@ -85,10 +84,6 @@ namespace osu.Game.Tests.Visual.Navigation Game = new TestOsuGame(LocalStorage, API); Game.SetHost(host); - // todo: this can be removed once we can run audio tracks without a device present - // see https://github.com/ppy/osu/issues/1302 - Game.LocalConfig.SetValue(OsuSetting.IntroSequence, IntroSequence.Circles); - Add(Game); } From 6dc96fdb830b78dc11e539ebeb24b20e7619b615 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 16:35:18 +0900 Subject: [PATCH 223/366] Disable edit button in playlists --- .../TestScenePlaylistsRoomSubScreen.cs | 7 +++-- .../OnlinePlay/Match/DrawableMatchRoom.cs | 26 +++++++++++++------ .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 11 ++++++-- .../Playlists/PlaylistsRoomSubScreen.cs | 2 +- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs index ee93e728ac..b8df90be2b 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs @@ -19,7 +19,6 @@ using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.OnlinePlay; -using osu.Game.Users; using osuTK.Input; namespace osu.Game.Tests.Visual.Playlists @@ -66,7 +65,7 @@ namespace osu.Game.Tests.Visual.Playlists { SelectedRoom.Value.RoomID.Value = 1; SelectedRoom.Value.Name.Value = "my awesome room"; - SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" }; + SelectedRoom.Value.Host.Value = API.LocalUser.Value; SelectedRoom.Value.RecentParticipants.Add(SelectedRoom.Value.Host.Value); SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMinutes(5); SelectedRoom.Value.Playlist.Add(new PlaylistItem @@ -86,7 +85,7 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("set room properties", () => { SelectedRoom.Value.Name.Value = "my awesome room"; - SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" }; + SelectedRoom.Value.Host.Value = API.LocalUser.Value; SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, @@ -137,7 +136,7 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("load room", () => { SelectedRoom.Value.Name.Value = "my awesome room"; - SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" }; + SelectedRoom.Value.Host.Value = API.LocalUser.Value; SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = importedSet.Beatmaps[0] }, diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index f7b4dd6920..ead219bee2 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -22,31 +23,40 @@ namespace osu.Game.Screens.OnlinePlay.Match private IAPIProvider api { get; set; } private readonly IBindable host = new Bindable(); + private readonly bool allowEdit; + [CanBeNull] private Drawable editButton; - public DrawableMatchRoom(Room room) + public DrawableMatchRoom(Room room, bool allowEdit = true) : base(room) { + this.allowEdit = allowEdit; + host.BindTo(room.Host); } [BackgroundDependencyLoader] private void load() { - ButtonsContainer.Add(editButton = new PurpleTriangleButton + if (allowEdit) { - RelativeSizeAxes = Axes.Y, - Size = new Vector2(100, 1), - Text = "Edit", - Action = () => OnEdit?.Invoke() - }); + ButtonsContainer.Add(editButton = new PurpleTriangleButton + { + RelativeSizeAxes = Axes.Y, + Size = new Vector2(100, 1), + Text = "Edit", + Action = () => OnEdit?.Invoke() + }); + } } protected override void LoadComplete() { base.LoadComplete(); - host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true); + + if (editButton != null) + host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true); } protected override bool ShouldBeConsideredForInput(Drawable child) => true; diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index ae92ab92c1..e95b4b221e 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -63,14 +63,21 @@ namespace osu.Game.Screens.OnlinePlay.Match protected IBindable BeatmapAvailability => BeatmapAvailabilityTracker.Availability; public readonly Room Room; + private readonly bool allowEdit; private ModSelectOverlay userModsSelectOverlay; private RoomSettingsOverlay settingsOverlay; private Drawable mainContent; - protected RoomSubScreen(Room room) + /// + /// Creates a new . + /// + /// The . + /// Whether to allow editing room settings post-creation. + protected RoomSubScreen(Room room, bool allowEdit = true) { Room = room; + this.allowEdit = allowEdit; Padding = new MarginPadding { Top = Header.HEIGHT }; @@ -125,7 +132,7 @@ namespace osu.Game.Screens.OnlinePlay.Match { new Drawable[] { - new DrawableMatchRoom(Room) + new DrawableMatchRoom(Room, allowEdit) { MatchingFilter = true, OnEdit = () => settingsOverlay.Show() diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index d799f09972..9855d1cb95 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private SelectionPollingComponent selectionPollingComponent; public PlaylistsRoomSubScreen(Room room) - : base(room) + : base(room, false) // Editing is temporarily not allowed. { Title = room.RoomID.Value == null ? "New playlist" : room.Name.Value; Activity.Value = new UserActivity.InLobby(room); From 5faf2df9b459bd00d669ff13db6d1f93a412a8d4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 16:42:49 +0900 Subject: [PATCH 224/366] Revert unintentional change --- .../Visual/Multiplayer/TestSceneMultiplayer.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 035bdbea1c..e618b28f40 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -83,19 +83,6 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("load multiplayer", () => LoadScreen(multiplayerScreen)); AddUntilStep("wait for multiplayer to load", () => multiplayerScreen.IsLoaded); AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); - - createRoom(() => new Room - { - Name = { Value = "Test Room" }, - Playlist = - { - new PlaylistItem - { - Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo }, - Ruleset = { Value = new OsuRuleset().RulesetInfo }, - } - } - }); } [Test] From 74d6c2652023e2f603c053ded54bac6b768aa551 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 11:03:35 +0300 Subject: [PATCH 225/366] Refactor star rating display layout with flexibility in mind --- .../TestSceneStarRatingDisplay.cs | 11 ++-- .../Beatmaps/Drawables/StarRatingDisplay.cs | 63 ++++++++++++++----- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index a8bc5664f3..7883049df2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -8,17 +8,15 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; -using osu.Game.Graphics.Containers; using osuTK; namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneStarRatingDisplay : OsuTestScene { - [TestCase(52f, 20f)] - [TestCase(52f, 16f)] - [TestCase(50f, 14f)] - public void TestDisplay(float width, float height) + [TestCase(StarRatingDisplaySize.Regular)] + [TestCase(StarRatingDisplaySize.Small)] + public void TestDisplay(StarRatingDisplaySize size) { AddStep("load displays", () => { @@ -36,11 +34,10 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Both, Spacing = new Vector2(2f), Direction = FillDirection.Vertical, - ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i * (i >= 11 ? 25f : 1f) + j * 0.1f, 0)) + ChildrenEnumerable = Enumerable.Range(0, 10).Select(j => new StarRatingDisplay(new StarDifficulty(i * (i >= 11 ? 25f : 1f) + j * 0.1f, 0), size) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(width, height), }), }) }; diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 2c40aebbe1..ed2fee23d5 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -44,40 +44,63 @@ namespace osu.Game.Beatmaps.Drawables /// Creates a new using an already computed . /// /// The already computed to display. - public StarRatingDisplay(StarDifficulty starDifficulty) + /// The size of the star rating display. + public StarRatingDisplay(StarDifficulty starDifficulty, StarRatingDisplaySize size = StarRatingDisplaySize.Regular) { Current.Value = starDifficulty; - Size = new Vector2(52f, 20f); + AutoSizeAxes = Axes.Both; InternalChild = new CircularContainer { Masking = true, - RelativeSizeAxes = Axes.Both, + AutoSizeAxes = Axes.Both, Children = new Drawable[] { background = new Box { RelativeSizeAxes = Axes.Both, }, - starIcon = new SpriteIcon + new GridContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Margin = new MarginPadding { Right = 30f }, - Icon = FontAwesome.Solid.Star, - Size = new Vector2(8f), + AutoSizeAxes = Axes.Both, + Margin = size == StarRatingDisplaySize.Small + ? new MarginPadding { Horizontal = 7f } + : new MarginPadding { Horizontal = 8f, Vertical = 2f }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, 3f), + new Dimension(GridSizeMode.AutoSize, minSize: 25f), + }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + Content = new[] + { + new[] + { + starIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.Solid.Star, + Size = new Vector2(8f), + }, + Empty(), + starsText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Bottom = 1.5f }, + // todo: this should be size: 12f, but to match up with the design, it needs to be 14.4f + // see https://github.com/ppy/osu-framework/issues/3271. + Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold), + Shadow = false, + } + } + } }, - starsText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Left = 10f, Bottom = 2f }, - // todo: this should be size: 12f, but to match up with the design, it needs to be 14.4f - // see https://github.com/ppy/osu-framework/issues/3271. - Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold), - Shadow = false, - } } }; } @@ -97,4 +120,10 @@ namespace osu.Game.Beatmaps.Drawables }, true); } } + + public enum StarRatingDisplaySize + { + Small, + Regular, + } } From 9220d17202fb032110d7804a29ae109e5520692f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 17:28:20 +0900 Subject: [PATCH 226/366] Adjust paddings/spacings --- .../Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs | 2 +- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 +- .../OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index 86687d7da8..80a22880d4 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components public abstract class RoomSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler { protected const float TRANSITION_DURATION = 350; - protected const float FIELD_PADDING = 45; + protected const float FIELD_PADDING = 25; protected OnlinePlayComposite Settings { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index e95b4b221e..e1412c894c 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -160,7 +160,7 @@ namespace osu.Game.Screens.OnlinePlay.Match new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(10), + Padding = new MarginPadding(20), Child = CreateMainContent(), }, new Container diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs index d28f886be4..3eea59006a 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs @@ -193,7 +193,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Child = new GridContainer { RelativeSizeAxes = Axes.X, - Height = 500, + Height = 448, Content = new[] { new Drawable[] From 209929844414101678998d6c3fa63b61dd9acf5e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 17:30:50 +0900 Subject: [PATCH 227/366] Disallow clicking on chat textbox during gameplay --- .../Multiplayer/TestSceneGameplayChatDisplay.cs | 14 ++++++++++++++ .../OnlinePlay/Multiplayer/GameplayChatDisplay.cs | 2 ++ 2 files changed, 16 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs index 795963a1ba..ffbc75ae15 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs @@ -49,6 +49,20 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("expand", () => chatDisplay.Expanded.Value = true); } + [Test] + public void TestCantClickWhenPlaying() + { + setLocalUserPlaying(true); + + AddStep("attempt focus chat", () => + { + InputManager.MoveMouseTo(textBox); + InputManager.Click(MouseButton.Left); + }); + + assertChatFocused(false); + } + [Test] public void TestFocusDroppedWhenPlaying() { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index 40da8d0a84..6a2609480e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -18,6 +18,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private IBindable localUserPlaying = new Bindable(); + public override bool PropagatePositionalInputSubTree => !localUserPlaying.Value; + public Bindable Expanded = new Bindable(); private const float height = 100; From 5e91ec73e3bf888f5aaf305478d5fceb317106ec Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 11:36:27 +0300 Subject: [PATCH 228/366] Handle star rating range display sizing --- .../Beatmaps/Drawables/StarRatingDisplay.cs | 22 ++++++++++++++++--- .../Components/StarRatingRangeDisplay.cs | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index ed2fee23d5..192ebe79d7 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -51,6 +51,23 @@ namespace osu.Game.Beatmaps.Drawables AutoSizeAxes = Axes.Both; + MarginPadding margin = default; + + switch (size) + { + case StarRatingDisplaySize.Small: + margin = new MarginPadding { Horizontal = 7f }; + break; + + case StarRatingDisplaySize.Range: + margin = new MarginPadding { Horizontal = 8f }; + break; + + case StarRatingDisplaySize.Regular: + margin = new MarginPadding { Horizontal = 8f, Vertical = 2f }; + break; + } + InternalChild = new CircularContainer { Masking = true, @@ -66,9 +83,7 @@ namespace osu.Game.Beatmaps.Drawables Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, - Margin = size == StarRatingDisplaySize.Small - ? new MarginPadding { Horizontal = 7f } - : new MarginPadding { Horizontal = 8f, Vertical = 2f }, + Margin = margin, ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize), @@ -124,6 +139,7 @@ namespace osu.Game.Beatmaps.Drawables public enum StarRatingDisplaySize { Small, + Range, Regular, } } diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 8e62153225..7b14acf924 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -64,8 +64,8 @@ namespace osu.Game.Screens.OnlinePlay.Components AutoSizeAxes = Axes.Both, Children = new Drawable[] { - minDisplay = new StarRatingDisplay(default) { Size = new Vector2(52f, 16f) }, - maxDisplay = new StarRatingDisplay(default) { Size = new Vector2(52f, 16f) } + minDisplay = new StarRatingDisplay(default, StarRatingDisplaySize.Range), + maxDisplay = new StarRatingDisplay(default, StarRatingDisplaySize.Range) } } }; From d2df09432f040d29ae08a92b2104c8d4fca5eda2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 11:49:33 +0300 Subject: [PATCH 229/366] Center the star rating display text rather than left --- osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 192ebe79d7..25cde5fb82 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -105,8 +105,8 @@ namespace osu.Game.Beatmaps.Drawables Empty(), starsText = new OsuSpriteText { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Margin = new MarginPadding { Bottom = 1.5f }, // todo: this should be size: 12f, but to match up with the design, it needs to be 14.4f // see https://github.com/ppy/osu-framework/issues/3271. From 365c1bccc67764695e940006176ab1b676eedee0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 18:24:19 +0900 Subject: [PATCH 230/366] Fix multiplayer channel being unintentionally left after gameplay session --- .../OnlinePlay/Match/Components/MatchChatDisplay.cs | 9 +++++++-- .../OnlinePlay/Multiplayer/GameplayChatDisplay.cs | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs index a96d64cb5d..5f960c1b5c 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs @@ -19,9 +19,12 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components [Resolved(CanBeNull = true)] private ChannelManager channelManager { get; set; } - public MatchChatDisplay() + private readonly bool leaveChannelOnDispose; + + public MatchChatDisplay(bool leaveChannelOnDispose = true) : base(true) { + this.leaveChannelOnDispose = leaveChannelOnDispose; } protected override void LoadComplete() @@ -42,7 +45,9 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - channelManager?.LeaveChannel(Channel.Value); + + if (leaveChannelOnDispose) + channelManager?.LeaveChannel(Channel.Value); } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index 6a2609480e..94542fb804 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -25,6 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private const float height = 100; public GameplayChatDisplay() + : base(leaveChannelOnDispose: false) { RelativeSizeAxes = Axes.X; From 1faf789f0e70a9d8b7431f127c3a1e76ebf18942 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 18:25:21 +0900 Subject: [PATCH 231/366] Allow expanding chat using key binding even when it is hidden --- .../TestSceneGameplayChatDisplay.cs | 17 ++++++- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 11 +++- .../Multiplayer/GameplayChatDisplay.cs | 50 +++++++++++++------ 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs index ffbc75ae15..51960680d6 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs @@ -83,13 +83,28 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] - public void TestFocusOnTabKey() + public void TestFocusOnTabKeyWhenExpanded() { assertChatFocused(false); AddStep("press tab", () => InputManager.Key(Key.Tab)); assertChatFocused(true); } + [Test] + public void TestFocusOnTabKeyWhenNotExpanded() + { + AddStep("set not expanded", () => chatDisplay.Expanded.Value = false); + AddUntilStep("is not visible", () => !chatDisplay.IsPresent); + + AddStep("press tab", () => InputManager.Key(Key.Tab)); + assertChatFocused(true); + AddUntilStep("is visible", () => chatDisplay.IsPresent); + + AddStep("press enter", () => InputManager.Key(Key.Enter)); + assertChatFocused(false); + AddUntilStep("is not visible", () => !chatDisplay.IsPresent); + } + private void assertChatFocused(bool isFocused) => AddAssert($"chat {(isFocused ? "focused" : "not focused")}", () => textBox.HasFocus == isFocused); diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 9d23a089df..6ed2055e65 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Chat; @@ -22,7 +23,7 @@ namespace osu.Game.Online.Chat { public readonly Bindable Channel = new Bindable(); - protected readonly FocusedTextBox Textbox; + protected readonly ChatTextBox Textbox; protected ChannelManager ChannelManager; @@ -121,6 +122,14 @@ namespace osu.Game.Online.Chat BackgroundUnfocused = new Color4(10, 10, 10, 10); BackgroundFocused = new Color4(10, 10, 10, 255); } + + protected override void OnFocusLost(FocusLostEvent e) + { + base.OnFocusLost(e); + FocusLost?.Invoke(); + } + + public Action FocusLost; } public class StandAloneDrawableChannel : DrawableChannel diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index 94542fb804..5d494379e6 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -22,28 +22,20 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public Bindable Expanded = new Bindable(); + private readonly Bindable expandedFromTextboxFocus = new Bindable(); + private const float height = 100; + public override bool PropagateNonPositionalInputSubTree => true; + public GameplayChatDisplay() : base(leaveChannelOnDispose: false) { RelativeSizeAxes = Axes.X; Background.Alpha = 0.2f; - } - private void expandedChanged(ValueChangedEvent expanded) - { - if (expanded.NewValue) - { - this.FadeIn(300, Easing.OutQuint); - this.ResizeHeightTo(height, 500, Easing.OutQuint); - } - else - { - this.FadeOut(300, Easing.OutQuint); - this.ResizeHeightTo(0, 500, Easing.OutQuint); - } + Textbox.FocusLost = () => expandedFromTextboxFocus.Value = false; } protected override void LoadComplete() @@ -61,7 +53,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Textbox.ReleaseFocusOnCommit = playing.NewValue; }, true); - Expanded.BindValueChanged(expandedChanged, true); + Expanded.BindValueChanged(_ => updateExpandedState(), true); + expandedFromTextboxFocus.BindValueChanged(focus => + { + if (focus.NewValue) + updateExpandedState(); + else + { + // on finishing typing a message there should be a brief delay before hiding. + using (BeginDelayedSequence(600)) + updateExpandedState(); + } + }, true); } public bool OnPressed(GlobalAction action) @@ -69,7 +72,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer switch (action) { case GlobalAction.FocusChatInput: - Textbox.TakeFocus(); + expandedFromTextboxFocus.Value = true; + + // schedule required to ensure the textbox has become present from above bindable update. + Schedule(() => Textbox.TakeFocus()); return true; } @@ -79,5 +85,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public void OnReleased(GlobalAction action) { } + + private void updateExpandedState() + { + if (Expanded.Value || expandedFromTextboxFocus.Value) + { + this.FadeIn(300, Easing.OutQuint); + this.ResizeHeightTo(height, 500, Easing.OutQuint); + } + else + { + this.FadeOut(300, Easing.OutQuint); + this.ResizeHeightTo(0, 500, Easing.OutQuint); + } + } } } From 28e2b6cec7cff82d007d44a7aa2026ff0679ed73 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Aug 2021 18:34:09 +0900 Subject: [PATCH 232/366] Add transform test for fun --- .../TestSceneStarRatingDisplay.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 7883049df2..052251d5a8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -3,6 +3,7 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; @@ -44,6 +45,31 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + [Test] + public void TestSpectrum() + { + StarRatingDisplay starRating = null; + + BindableDouble starRatingNumeric; + + AddStep("load display", () => + { + Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(3f), + }; + }); + + AddStep("transform over spectrum", () => + { + starRatingNumeric = new BindableDouble(); + starRatingNumeric.BindValueChanged(val => starRating.Current.Value = new StarDifficulty(val.NewValue, 1)); + this.TransformBindableTo(starRatingNumeric, 10, 10000, Easing.OutQuint); + }); + } + [Test] public void TestChangingStarRatingDisplay() { From 8172ffc401a5ff0abe8a779cc7fd2dba8aee3448 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Aug 2021 13:12:58 +0300 Subject: [PATCH 233/366] Fix lounge sub screen loading layer displaying in the background --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 8bed3d6049..24aad8c124 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -84,7 +84,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { ListingPollingComponent = CreatePollingComponent().With(c => c.Filter.BindTarget = filter), - loadingLayer = new LoadingLayer(true), new Container { RelativeSizeAxes = Axes.Both, @@ -162,6 +161,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge Filter = { BindTarget = filter } } }, + loadingLayer = new LoadingLayer(true), } }, } From 63af67f61b5a69918b34ae7f4dc764deffa7b747 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 20:21:29 +0900 Subject: [PATCH 234/366] Cleanup around footers --- .../Multiplayer/TestSceneMatchHeader.cs | 55 ------------- .../OnlinePlay/Match/Components/Footer.cs | 48 ----------- .../OnlinePlay/Match/Components/Header.cs | 79 ------------------- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 29 ++++++- .../Match/MultiplayerMatchFooter.cs | 63 ++++++--------- .../Multiplayer/MultiplayerMatchSubScreen.cs | 22 +++--- .../Playlists/PlaylistsRoomFooter.cs | 32 ++++++++ .../Playlists/PlaylistsRoomSubScreen.cs | 25 +++--- 8 files changed, 103 insertions(+), 250 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Match/Components/Footer.cs delete mode 100644 osu.Game/Screens/OnlinePlay/Match/Components/Header.cs create mode 100644 osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs deleted file mode 100644 index 71ba5db481..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using NUnit.Framework; -using osu.Game.Beatmaps; -using osu.Game.Online.Rooms; -using osu.Game.Rulesets.Osu; -using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Screens.OnlinePlay.Match.Components; -using osu.Game.Tests.Visual.OnlinePlay; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class TestSceneMatchHeader : OnlinePlayTestScene - { - [SetUp] - public new void Setup() => Schedule(() => - { - SelectedRoom.Value = new Room - { - Name = { Value = "A very awesome room" }, - Host = { Value = new User { Id = 2, Username = "peppy" } }, - Playlist = - { - new PlaylistItem - { - Beatmap = - { - Value = new BeatmapInfo - { - Metadata = new BeatmapMetadata - { - Title = "Title", - Artist = "Artist", - AuthorString = "Author", - }, - Version = "Version", - Ruleset = new OsuRuleset().RulesetInfo - } - }, - RequiredMods = - { - new OsuModDoubleTime(), - new OsuModNoFail(), - new OsuModRelax(), - } - } - } - }; - - Child = new Header(); - }); - } -} diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/Footer.cs b/osu.Game/Screens/OnlinePlay/Match/Components/Footer.cs deleted file mode 100644 index e91c46beed..0000000000 --- a/osu.Game/Screens/OnlinePlay/Match/Components/Footer.cs +++ /dev/null @@ -1,48 +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.Allocation; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osu.Game.Screens.OnlinePlay.Playlists; -using osuTK; - -namespace osu.Game.Screens.OnlinePlay.Match.Components -{ - public class Footer : CompositeDrawable - { - public const float HEIGHT = 50; - - public Action OnStart; - - private readonly Drawable background; - - public Footer() - { - RelativeSizeAxes = Axes.X; - Height = HEIGHT; - - InternalChildren = new[] - { - background = new Box { RelativeSizeAxes = Axes.Both }, - new PlaylistsReadyButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(600, 50), - Action = () => OnStart?.Invoke() - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = Color4Extensions.FromHex(@"28242d"); - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/Header.cs b/osu.Game/Screens/OnlinePlay/Match/Components/Header.cs deleted file mode 100644 index a2d11c54c1..0000000000 --- a/osu.Game/Screens/OnlinePlay/Match/Components/Header.cs +++ /dev/null @@ -1,79 +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.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Users.Drawables; -using osuTK; - -namespace osu.Game.Screens.OnlinePlay.Match.Components -{ - public class Header : OnlinePlayComposite - { - public const float HEIGHT = 50; - - private UpdateableAvatar avatar; - private LinkFlowContainer hostText; - - public Header() - { - RelativeSizeAxes = Axes.X; - Height = HEIGHT; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - avatar = new UpdateableAvatar - { - Size = new Vector2(50), - Masking = true, - CornerRadius = 10, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30), - Current = { BindTarget = RoomName } - }, - hostText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 20)) - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - } - } - } - } - }; - - Host.BindValueChanged(host => - { - avatar.User = host.NewValue; - - hostText.Clear(); - - if (host.NewValue != null) - { - hostText.AddText("hosted by "); - hostText.AddUserLink(host.NewValue, s => s.Font = s.Font.With(weight: FontWeight.SemiBold)); - } - }, true); - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index e1412c894c..42d76e5a15 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -103,7 +103,7 @@ namespace osu.Game.Screens.OnlinePlay.Match RowDimensions = new[] { new Dimension(), - new Dimension(GridSizeMode.AutoSize) + new Dimension(GridSizeMode.Absolute, 50) }, Content = new[] { @@ -154,7 +154,7 @@ namespace osu.Game.Screens.OnlinePlay.Match Child = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex(@"3e3a44") // This is super temporary. + Colour = Color4Extensions.FromHex(@"3e3a44") // Temporary. }, }, new Container @@ -191,9 +191,21 @@ namespace osu.Game.Screens.OnlinePlay.Match }, }, // Footer - new[] + new Drawable[] { - CreateFooter() + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex(@"28242d") // Temporary. + }, + CreateFooter() + } + } } } } @@ -382,10 +394,19 @@ namespace osu.Game.Screens.OnlinePlay.Match track.Looping = false; } + /// + /// Creates the main centred content. + /// protected abstract Drawable CreateMainContent(); + /// + /// Creates the footer content. + /// protected abstract Drawable CreateFooter(); + /// + /// Creates the room settings overlay. + /// protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(); private class UserModSelectOverlay : LocalPlayerModSelectOverlay diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs index d4f5428bfb..9e8d51e64e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs @@ -2,18 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { public class MultiplayerMatchFooter : CompositeDrawable { - public const float HEIGHT = 50; private const float ready_button_width = 600; private const float spectate_button_width = 200; @@ -27,54 +22,42 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match set => spectateButton.OnSpectateClick = value; } - private readonly Drawable background; private readonly MultiplayerReadyButton readyButton; private readonly MultiplayerSpectateButton spectateButton; public MultiplayerMatchFooter() { - RelativeSizeAxes = Axes.X; - Height = HEIGHT; + RelativeSizeAxes = Axes.Both; - InternalChildren = new[] + InternalChild = new GridContainer { - background = new Box { RelativeSizeAxes = Axes.Both }, - new GridContainer + RelativeSizeAxes = Axes.Both, + Content = new[] { - RelativeSizeAxes = Axes.Both, - Content = new[] + new Drawable[] { - new Drawable[] + null, + spectateButton = new MultiplayerSpectateButton { - null, - spectateButton = new MultiplayerSpectateButton - { - RelativeSizeAxes = Axes.Both, - }, - null, - readyButton = new MultiplayerReadyButton - { - RelativeSizeAxes = Axes.Both, - }, - null - } - }, - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(maxSize: spectate_button_width), - new Dimension(GridSizeMode.Absolute, 10), - new Dimension(maxSize: ready_button_width), - new Dimension() + RelativeSizeAxes = Axes.Both, + }, + null, + readyButton = new MultiplayerReadyButton + { + RelativeSizeAxes = Axes.Both, + }, + null } + }, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(maxSize: spectate_button_width), + new Dimension(GridSizeMode.Absolute, 10), + new Dimension(maxSize: ready_button_width), + new Dimension() } }; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = Color4Extensions.FromHex(@"28242d"); - } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index f8e5d7d901..3f5837cbbe 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -94,17 +94,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer }, true); } - protected override void UpdateMods() - { - if (SelectedItem.Value == null || client.LocalUser == null) - return; - - // update local mods based on room's reported status for the local user (omitting the base call implementation). - // this makes the server authoritative, and avoids the local user potentially setting mods that the server is not aware of (ie. if the match was started during the selection being changed). - var ruleset = Ruleset.Value.CreateInstance(); - Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList(); - } - protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, @@ -236,6 +225,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override RoomSettingsOverlay CreateRoomSettingsOverlay() => new MultiplayerMatchSettingsOverlay(); + protected override void UpdateMods() + { + if (SelectedItem.Value == null || client.LocalUser == null) + return; + + // update local mods based on room's reported status for the local user (omitting the base call implementation). + // this makes the server authoritative, and avoids the local user potentially setting mods that the server is not aware of (ie. if the match was started during the selection being changed). + var ruleset = Ruleset.Value.CreateInstance(); + Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList(); + } + [Resolved(canBeNull: true)] private DialogOverlay dialogOverlay { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs new file mode 100644 index 0000000000..3eb1cde0a4 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.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.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; + +namespace osu.Game.Screens.OnlinePlay.Playlists +{ + public class PlaylistsRoomFooter : CompositeDrawable + { + public Action OnStart; + + public PlaylistsRoomFooter() + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new[] + { + new PlaylistsReadyButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Size = new Vector2(600, 1), + Action = () => OnStart?.Invoke() + } + }; + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 9855d1cb95..27de781d5f 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -20,7 +20,6 @@ using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; using osu.Game.Users; using osuTK; -using Footer = osu.Game.Screens.OnlinePlay.Match.Components.Footer; namespace osu.Game.Screens.OnlinePlay.Playlists { @@ -70,17 +69,6 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, true); } - private void updatePollingRate() - { - selectionPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 30000 : 5000; - Logger.Log($"Polling adjusted (selection: {selectionPollingComponent.TimeBetweenPolls.Value})"); - } - - protected override Screen CreateGameplayScreen() => new PlayerLoader(() => new PlaylistsPlayer(SelectedItem.Value) - { - Exited = () => leaderboard.RefreshScores() - }); - protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, @@ -190,7 +178,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists } }; - protected override Drawable CreateFooter() => new Footer + protected override Drawable CreateFooter() => new PlaylistsRoomFooter { OnStart = StartPlay }; @@ -203,5 +191,16 @@ namespace osu.Game.Screens.OnlinePlay.Playlists this.Push(new PlaylistsSongSelect()); }, }; + + private void updatePollingRate() + { + selectionPollingComponent.TimeBetweenPolls.Value = isIdle.Value ? 30000 : 5000; + Logger.Log($"Polling adjusted (selection: {selectionPollingComponent.TimeBetweenPolls.Value})"); + } + + protected override Screen CreateGameplayScreen() => new PlayerLoader(() => new PlaylistsPlayer(SelectedItem.Value) + { + Exited = () => leaderboard.RefreshScores() + }); } } From eadf02933a735ea97ce8dbd69fb6a35f2318525d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 20:53:17 +0900 Subject: [PATCH 235/366] Split lounge-specific implementation from DrawableRoom --- .../Multiplayer/TestSceneDrawableRoom.cs | 7 +- .../TestSceneLoungeRoomsContainer.cs | 3 +- .../Multiplayer/TestSceneMultiplayer.cs | 4 +- .../TestSceneMultiplayerLoungeSubScreen.cs | 13 +- .../Lounge/Components/DrawableRoom.cs | 263 ++---------------- .../Lounge/Components/RoomsContainer.cs | 22 +- .../OnlinePlay/Lounge/DrawableLoungeRoom.cs | 225 +++++++++++++++ .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 1 - 8 files changed, 269 insertions(+), 269 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 299bbacf08..489ece3271 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -10,11 +10,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Framework.Utils; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Overlays; using osu.Game.Rulesets.Osu; +using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Beatmaps; using osu.Game.Users; @@ -159,10 +159,7 @@ namespace osu.Game.Tests.Visual.Multiplayer })); } - var drawableRoom = new DrawableRoom(room) { MatchingFilter = true }; - drawableRoom.Action = () => drawableRoom.State = drawableRoom.State == SelectionState.Selected ? SelectionState.NotSelected : SelectionState.Selected; - - return drawableRoom; + return new DrawableLoungeRoom(room) { MatchingFilter = true }; } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 7e822f898e..b23638e514 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Testing; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; +using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Visual.OnlinePlay; using osuTK.Input; @@ -150,6 +151,6 @@ namespace osu.Game.Tests.Visual.Multiplayer private bool checkRoomSelected(Room room) => SelectedRoom.Value == room; private Room getRoomInFlow(int index) => - (container.ChildrenOfType>().First().FlowingChildren.ElementAt(index) as DrawableRoom)?.Room; + (container.ChildrenOfType>().First().FlowingChildren.ElementAt(index) as DrawableRoom)?.Room; } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index e618b28f40..6c1aed71e6 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -236,8 +236,8 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("join room", () => InputManager.Key(Key.Enter)); - DrawableRoom.PasswordEntryPopover passwordEntryPopover = null; - AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); + DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null; + AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType().First().Text = "password"); AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().TriggerClick()); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs index c66d5429d6..4ec02a6ec8 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs @@ -9,7 +9,6 @@ using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Lounge; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Tests.Visual.OnlinePlay; using osuTK.Input; @@ -59,20 +58,20 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("attempt join room", () => InputManager.Key(Key.Enter)); - AddUntilStep("password prompt appeared", () => InputManager.ChildrenOfType().Any()); + AddUntilStep("password prompt appeared", () => InputManager.ChildrenOfType().Any()); AddStep("exit screen", () => Stack.Exit()); - AddUntilStep("password prompt hidden", () => !InputManager.ChildrenOfType().Any()); + AddUntilStep("password prompt hidden", () => !InputManager.ChildrenOfType().Any()); } [Test] public void TestJoinRoomWithPassword() { - DrawableRoom.PasswordEntryPopover passwordEntryPopover = null; + DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null; AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true)); AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("attempt join room", () => InputManager.Key(Key.Enter)); - AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); + AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType().First().Text = "password"); AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().TriggerClick()); @@ -83,12 +82,12 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestJoinRoomWithPasswordViaKeyboardOnly() { - DrawableRoom.PasswordEntryPopover passwordEntryPopover = null; + DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null; AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true)); AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("attempt join room", () => InputManager.Key(Key.Enter)); - AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); + AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType().First().Text = "password"); AddStep("press enter", () => InputManager.Key(Key.Enter)); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index b627dfbb8e..c5b8bffbc6 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -1,32 +1,19 @@ // 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 osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Input.Bindings; using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Screens.OnlinePlay.Components; @@ -35,104 +22,17 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public class DrawableRoom : OsuClickableContainer, IStateful, IFilterable, IHasContextMenu, IHasPopover, IKeyBindingHandler + public class DrawableRoom : CompositeDrawable { - public const float SELECTION_BORDER_WIDTH = 4; - private const float corner_radius = 10; - private const float transition_duration = 60; + protected const float CORNER_RADIUS = 10; private const float height = 100; - public event Action StateChanged; - - protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(); - - private Drawable selectionBox; - - [Resolved(canBeNull: true)] - private LoungeSubScreen loungeScreen { get; set; } + public readonly Room Room; [Resolved] private BeatmapManager beatmaps { get; set; } - [Resolved(canBeNull: true)] - private Bindable selectedRoom { get; set; } - - [Resolved(canBeNull: true)] - private LoungeSubScreen lounge { get; set; } - - public readonly Room Room; - - private SelectionState state; - - private Sample sampleSelect; - private Sample sampleJoin; - - public SelectionState State - { - get => state; - set - { - if (value == state) - return; - - state = value; - - if (selectionBox != null) - { - if (state == SelectionState.Selected) - selectionBox.FadeIn(transition_duration); - else - selectionBox.FadeOut(transition_duration); - } - - StateChanged?.Invoke(State); - } - } - - public IEnumerable FilterTerms => new[] { Room.Name.Value }; - - private bool matchingFilter; - - public bool MatchingFilter - { - get => matchingFilter; - set - { - matchingFilter = value; - - if (!IsLoaded) - return; - - if (matchingFilter) - this.FadeIn(200); - else - Hide(); - } - } - - private int numberOfAvatars = 7; - - public int NumberOfAvatars - { - get => numberOfAvatars; - set - { - numberOfAvatars = value; - - if (recentParticipantsList != null) - recentParticipantsList.NumberOfCircles = value; - } - } - - public bool FilteringActive { get; set; } - - protected readonly Container ButtonsContainer = new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X - }; + protected Container ButtonsContainer { get; private set; } private readonly Bindable roomCategory = new Bindable(); private readonly Bindable hasPassword = new Bindable(); @@ -149,7 +49,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Height = height; Masking = true; - CornerRadius = corner_radius; + CornerRadius = CORNER_RADIUS; EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, @@ -159,9 +59,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colours, AudioManager audio) + private void load(OverlayColourProvider colours) { - Children = new Drawable[] + InternalChildren = new Drawable[] { // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. new Box @@ -183,7 +83,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { RelativeSizeAxes = Axes.Both, Masking = true, - CornerRadius = corner_radius, + CornerRadius = CORNER_RADIUS, Children = new Drawable[] { new GridContainer @@ -303,7 +203,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, Children = new Drawable[] { - ButtonsContainer, + ButtonsContainer = new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X + }, recentParticipantsList = new RecentParticipantsList { Anchor = Anchor.CentreRight, @@ -316,36 +222,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }, }, }, - new StatusColouredContainer(transition_duration) - { - RelativeSizeAxes = Axes.Both, - Child = selectionBox = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = state == SelectionState.Selected ? 1 : 0, - Masking = true, - CornerRadius = corner_radius, - BorderThickness = SELECTION_BORDER_WIDTH, - BorderColour = Color4.White, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - } - }, - }; - - sampleSelect = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select"); - sampleJoin = audio.Samples.Get($@"UI/{HoverSampleSet.Submit.GetDescription()}-select"); - } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - return new CachedModelDependencyContainer(base.CreateChildDependencies(parent)) - { - Model = { Value = Room } }; } @@ -353,11 +229,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { base.LoadComplete(); - if (matchingFilter) - this.FadeInFromZero(transition_duration); - else - Alpha = 0; - roomCategory.BindTo(Room.Category); roomCategory.BindValueChanged(c => { @@ -371,57 +242,26 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components hasPassword.BindValueChanged(v => passwordIcon.Alpha = v.NewValue ? 1 : 0, true); } - public Popover GetPopover() => new PasswordEntryPopover(Room) { JoinRequested = lounge.Join }; - - public MenuItem[] ContextMenuItems => new MenuItem[] + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - new OsuMenuItem("Create copy", MenuItemType.Standard, () => + return new CachedModelDependencyContainer(base.CreateChildDependencies(parent)) { - lounge?.Open(Room.DeepClone()); - }) - }; - - public bool OnPressed(GlobalAction action) - { - if (selectedRoom.Value != Room) - return false; - - switch (action) - { - case GlobalAction.Select: - TriggerClick(); - return true; - } - - return false; + Model = { Value = Room } + }; } - public void OnReleased(GlobalAction action) + private int numberOfAvatars = 7; + + public int NumberOfAvatars { - } - - protected override bool ShouldBeConsideredForInput(Drawable child) => state == SelectionState.Selected || child is HoverSounds; - - protected override bool OnClick(ClickEvent e) - { - if (Room != selectedRoom.Value) + get => numberOfAvatars; + set { - sampleSelect?.Play(); - selectedRoom.Value = Room; - return true; + numberOfAvatars = value; + + if (recentParticipantsList != null) + recentParticipantsList.NumberOfCircles = value; } - - if (Room.HasPassword.Value) - { - sampleJoin?.Play(); - this.ShowPopover(); - return true; - } - - sampleJoin?.Play(); - lounge?.Join(Room, null); - - return base.OnClick(e); } private class RoomNameText : OsuSpriteText @@ -508,52 +348,5 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components }; } } - - public class PasswordEntryPopover : OsuPopover - { - private readonly Room room; - - public Action JoinRequested; - - public PasswordEntryPopover(Room room) - { - this.room = room; - } - - private OsuPasswordTextBox passwordTextbox; - - [BackgroundDependencyLoader] - private void load() - { - Child = new FillFlowContainer - { - Margin = new MarginPadding(10), - Spacing = new Vector2(5), - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - passwordTextbox = new OsuPasswordTextBox - { - Width = 200, - }, - new TriangleButton - { - Width = 80, - Text = "Join Room", - Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text) - } - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextbox)); - passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text); - } - } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index e243477a8c..be5558ed0b 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -15,7 +15,6 @@ using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Game.Extensions; using osu.Game.Graphics.Cursor; -using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Online.Rooms; using osuTK; @@ -26,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { private readonly IBindableList rooms = new BindableList(); - private readonly FillFlowContainer roomFlow; + private readonly FillFlowContainer roomFlow; public IReadOnlyList Rooms => roomFlow.FlowingChildren.Cast().ToArray(); @@ -56,7 +55,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = roomFlow = new FillFlowContainer + Child = roomFlow = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -74,16 +73,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components rooms.BindTo(roomManager.Rooms); Filter?.BindValueChanged(criteria => applyFilterCriteria(criteria.NewValue), true); - - selectedRoom.BindValueChanged(selection => - { - updateSelection(); - }, true); } - private void updateSelection() => - roomFlow.Children.ForEach(r => r.State = r.Room == selectedRoom.Value ? SelectionState.Selected : SelectionState.NotSelected); - private void applyFilterCriteria(FilterCriteria criteria) { roomFlow.Children.ForEach(r => @@ -122,22 +113,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { foreach (var room in rooms) { - roomFlow.Add(new DrawableRoom(room)); + roomFlow.Add(new DrawableLoungeRoom(room)); } applyFilterCriteria(Filter?.Value); - - updateSelection(); } private void removeRooms(IEnumerable rooms) { foreach (var r in rooms) { - var toRemove = roomFlow.Single(d => d.Room == r); - toRemove.Action = null; - - roomFlow.Remove(toRemove); + roomFlow.RemoveAll(d => d.Room == r); // selection may have a lease due to being in a sub screen. if (!selectedRoom.Disabled) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs new file mode 100644 index 0000000000..764d4e9d3a --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -0,0 +1,225 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Input.Bindings; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.OnlinePlay.Lounge +{ + /// + /// A with lounge-specific interactions such as selection and hover sounds. + /// + public class DrawableLoungeRoom : DrawableRoom, IFilterable, IHasContextMenu, IHasPopover, IKeyBindingHandler + { + private const float transition_duration = 60; + private const float selection_border_width = 4; + + [Resolved(canBeNull: true)] + private LoungeSubScreen lounge { get; set; } + + [Resolved(canBeNull: true)] + private Bindable selectedRoom { get; set; } + + private Sample sampleSelect; + private Sample sampleJoin; + private Drawable selectionBox; + + public DrawableLoungeRoom(Room room) + : base(room) + { + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleSelect = audio.Samples.Get($@"UI/{HoverSampleSet.Default.GetDescription()}-select"); + sampleJoin = audio.Samples.Get($@"UI/{HoverSampleSet.Submit.GetDescription()}-select"); + + AddRangeInternal(new Drawable[] + { + new StatusColouredContainer(transition_duration) + { + RelativeSizeAxes = Axes.Both, + Child = selectionBox = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = CORNER_RADIUS, + BorderThickness = selection_border_width, + BorderColour = Color4.White, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + }, + new HoverSounds() + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (matchingFilter) + this.FadeInFromZero(transition_duration); + else + Alpha = 0; + + selectedRoom.BindValueChanged(updateSelectedRoom, true); + } + + private void updateSelectedRoom(ValueChangedEvent selected) + { + if (selected.NewValue == Room) + selectionBox.FadeIn(transition_duration); + else + selectionBox.FadeOut(transition_duration); + } + + public bool FilteringActive { get; set; } + + public IEnumerable FilterTerms => new[] { Room.Name.Value }; + + private bool matchingFilter; + + public bool MatchingFilter + { + get => matchingFilter; + set + { + matchingFilter = value; + + if (!IsLoaded) + return; + + if (matchingFilter) + this.FadeIn(200); + else + Hide(); + } + } + + public Popover GetPopover() => new PasswordEntryPopover(Room) { JoinRequested = lounge.Join }; + + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem("Create copy", MenuItemType.Standard, () => + { + lounge?.Open(Room.DeepClone()); + }) + }; + + public bool OnPressed(GlobalAction action) + { + if (selectedRoom.Value != Room) + return false; + + switch (action) + { + case GlobalAction.Select: + TriggerClick(); + return true; + } + + return false; + } + + public void OnReleased(GlobalAction action) + { + } + + protected override bool ShouldBeConsideredForInput(Drawable child) => selectedRoom.Value == Room || child is HoverSounds; + + protected override bool OnClick(ClickEvent e) + { + if (Room != selectedRoom.Value) + { + sampleSelect?.Play(); + selectedRoom.Value = Room; + return true; + } + + if (Room.HasPassword.Value) + { + sampleJoin?.Play(); + this.ShowPopover(); + return true; + } + + sampleJoin?.Play(); + lounge?.Join(Room, null); + + return base.OnClick(e); + } + + public class PasswordEntryPopover : OsuPopover + { + private readonly Room room; + + public Action JoinRequested; + + public PasswordEntryPopover(Room room) + { + this.room = room; + } + + private OsuPasswordTextBox passwordTextbox; + + [BackgroundDependencyLoader] + private void load() + { + Child = new FillFlowContainer + { + Margin = new MarginPadding(10), + Spacing = new Vector2(5), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + passwordTextbox = new OsuPasswordTextBox + { + Width = 200, + }, + new TriangleButton + { + Width = 80, + Text = "Join Room", + Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text) + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextbox)); + passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text); + } + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 42d76e5a15..81fae558c8 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -134,7 +134,6 @@ namespace osu.Game.Screens.OnlinePlay.Match { new DrawableMatchRoom(Room, allowEdit) { - MatchingFilter = true, OnEdit = () => settingsOverlay.Show() } }, From e9221f012635c9e63a7049d8c7a046681b65b0a6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 21:00:11 +0900 Subject: [PATCH 236/366] Cleanup unnecessary implementation --- osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index ead219bee2..b3e6292f45 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -58,7 +58,5 @@ namespace osu.Game.Screens.OnlinePlay.Match if (editButton != null) host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true); } - - protected override bool ShouldBeConsideredForInput(Drawable child) => true; } } From d40023bcc1ff1e612a48dd78f60b32e31c8e868e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Aug 2021 21:09:34 +0900 Subject: [PATCH 237/366] Hide border by default --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 764d4e9d3a..4e106b844c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -63,6 +63,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge Child = selectionBox = new Container { RelativeSizeAxes = Axes.Both, + Alpha = 0, Masking = true, CornerRadius = CORNER_RADIUS, BorderThickness = selection_border_width, From af0c7ed108387b4e77ee8bf4f902dafbd2f12551 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 01:25:57 +0900 Subject: [PATCH 238/366] Fix searching in settings not correctly invalidating the scroll position --- osu.Game/Graphics/Containers/SectionsContainer.cs | 11 ++++++++++- osu.Game/Overlays/SettingsPanel.cs | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 8ab146efe7..b3dd44f0e1 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -170,13 +170,22 @@ namespace osu.Game.Graphics.Containers if (source == InvalidationSource.Child && (invalidation & Invalidation.DrawSize) != 0) { - lastKnownScroll = null; + InvalidateScrollPosition(); result = true; } return result; } + protected void InvalidateScrollPosition() + { + Schedule(() => + { + lastKnownScroll = null; + lastClickedSection = null; + }); + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 376e36ea4e..83b0d9c7dc 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -273,6 +273,16 @@ namespace osu.Game.Overlays { public SearchContainer SearchContainer; + public string SearchTerm + { + get => SearchContainer.SearchTerm; + set + { + SearchContainer.SearchTerm = value; + InvalidateScrollPosition(); + } + } + protected override FlowContainer CreateScrollContentContainer() => SearchContainer = new SearchContainer { From a0374d4a67c2274673f05452e9d050451f7d07e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 01:26:11 +0900 Subject: [PATCH 239/366] Adjust centre point slightly to make dim feel better --- osu.Game/Graphics/Containers/SectionsContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index b3dd44f0e1..2dc69b0bd0 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -111,7 +111,7 @@ namespace osu.Game.Graphics.Containers /// /// The percentage of the container to consider the centre-point for deciding the active section (and scrolling to a requested section). /// - private const float scroll_y_centre = 0.1f; + private const float scroll_y_centre = 0.2f; public SectionsContainer() { From e87accafc88cc5ea384b7441893d1a95a3739354 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 01:26:33 +0900 Subject: [PATCH 240/366] Fix current section logic not accounting for hidden sections --- osu.Game/Graphics/Containers/SectionsContainer.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 2dc69b0bd0..e11d1e1300 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -22,6 +22,7 @@ namespace osu.Game.Graphics.Containers where T : Drawable { public Bindable SelectedSection { get; } = new Bindable(); + private Drawable lastClickedSection; public Drawable ExpandableHeader @@ -233,15 +234,17 @@ namespace osu.Game.Graphics.Containers float scrollCentre = fixedHeaderSize + scrollContainer.DisplayableContent * scroll_y_centre + selectionLenienceAboveSection; + var presentChildren = Children.Where(c => c.IsPresent); + if (Precision.AlmostBigger(0, scrollContainer.Current)) - SelectedSection.Value = lastClickedSection as T ?? Children.FirstOrDefault(); + SelectedSection.Value = lastClickedSection as T ?? presentChildren.FirstOrDefault(); else if (Precision.AlmostBigger(scrollContainer.Current, scrollContainer.ScrollableExtent)) - SelectedSection.Value = lastClickedSection as T ?? Children.LastOrDefault(); + SelectedSection.Value = lastClickedSection as T ?? presentChildren.LastOrDefault(); else { - SelectedSection.Value = Children + SelectedSection.Value = presentChildren .TakeWhile(section => scrollContainer.GetChildPosInContent(section) - currentScroll - scrollCentre <= 0) - .LastOrDefault() ?? Children.FirstOrDefault(); + .LastOrDefault() ?? presentChildren.FirstOrDefault(); } } } From 6637c64501aab585fe3e110e3833a1b2eab35fc0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 01:27:14 +0900 Subject: [PATCH 241/366] Dim all but the current section --- osu.Game/Overlays/Settings/SettingsSection.cs | 49 ++++++++++++++++++- osu.Game/Overlays/SettingsPanel.cs | 13 +++-- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index f993a46dc6..8d98ae484f 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -19,6 +21,10 @@ namespace osu.Game.Overlays.Settings protected FillFlowContainer FlowContent; protected override Container Content => FlowContent; + private IBindable selectedSection; + + private Container content; + public abstract Drawable CreateIcon(); public abstract LocalisableString Header { get; } @@ -36,6 +42,9 @@ namespace osu.Game.Overlays.Settings public bool FilteringActive { get; set; } + [Resolved] + private SettingsPanel settingsPanel { get; set; } + protected SettingsSection() { Margin = new MarginPadding { Top = margin }; @@ -65,7 +74,7 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X, Height = border_size, }, - new Container + content = new Container { Padding = new MarginPadding { @@ -91,6 +100,44 @@ namespace osu.Game.Overlays.Settings } }, }); + + selectedSection = settingsPanel.CurrentSection.GetBoundCopy(); + selectedSection.BindValueChanged(selected => + { + if (selected.NewValue == this) + content.FadeIn(500, Easing.OutQuint); + else + content.FadeTo(0.25f, 500, Easing.OutQuint); + }, true); + } + + private bool isCurrentSection => selectedSection.Value == this; + + protected override bool OnHover(HoverEvent e) + { + if (!isCurrentSection) + content.FadeTo(0.6f, 500, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + if (!isCurrentSection) + content.FadeTo(0.25f, 500, Easing.OutQuint); + base.OnHoverLost(e); + } + + protected override bool OnClick(ClickEvent e) + { + if (!isCurrentSection) + settingsPanel.SectionsContainer.ScrollTo(this); + + return base.OnClick(e); + } + + protected override bool ShouldBeConsideredForInput(Drawable child) + { + return isCurrentSection; } } } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 83b0d9c7dc..e4e76592d8 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,6 +22,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Overlays { + [Cached] public abstract class SettingsPanel : OsuFocusedOverlayContainer { public const float CONTENT_MARGINS = 15; @@ -46,7 +48,7 @@ namespace osu.Game.Overlays protected Sidebar Sidebar; private SidebarButton selectedSidebarButton; - protected SettingsSectionsContainer SectionsContainer; + public SettingsSectionsContainer SectionsContainer { get; private set; } private SeekLimitedSearchTextBox searchTextBox; @@ -65,6 +67,8 @@ namespace osu.Game.Overlays private Task sectionsLoadingTask; + public IBindable CurrentSection = new Bindable(); + protected SettingsPanel(bool showSidebar) { this.showSidebar = showSidebar; @@ -105,6 +109,7 @@ namespace osu.Game.Overlays Masking = true, RelativeSizeAxes = Axes.Both, ExpandableHeader = CreateHeader(), + SelectedSection = { BindTarget = CurrentSection }, FixedHeader = searchTextBox = new SeekLimitedSearchTextBox { RelativeSizeAxes = Axes.X, @@ -238,8 +243,10 @@ namespace osu.Game.Overlays if (selectedSidebarButton != null) selectedSidebarButton.Selected = false; - selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); - selectedSidebarButton.Selected = true; + selectedSidebarButton = Sidebar.Children.FirstOrDefault(b => b.Section == section.NewValue); + + if (selectedSidebarButton != null) + selectedSidebarButton.Selected = true; }, true); }); } From 61675eefe0a5fecb4f01661ad717e49b1d398a87 Mon Sep 17 00:00:00 2001 From: Davran Dilshat Date: Wed, 18 Aug 2021 17:36:57 +0100 Subject: [PATCH 242/366] Add length limit to match settings textboxes --- .../Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs index 61bb39d0c5..7bad661cf4 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs @@ -48,6 +48,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components { BackgroundUnfocused = Color4.Black; BackgroundFocused = Color4.Black; + LengthLimit = 100; } } @@ -63,6 +64,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components { BackgroundUnfocused = Color4.Black; BackgroundFocused = Color4.Black; + LengthLimit = 255; } } From ea08d48d273cb2253ed1ddba751d24a3cf369e19 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 18 Aug 2021 18:53:01 +0200 Subject: [PATCH 243/366] Remove unecessary localised string due to online view container handling visibility when user is not logged in. --- osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index 441ef2f6cf..c0460a4536 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private readonly bool noVideo; - public LocalisableString TooltipText => button.Enabled.Value ? BeatmapsetsStrings.ShowDetailsDownloadDefault : BeatmapsetsStrings.ShowDetailsLoggedOut; + public LocalisableString TooltipText => BeatmapsetsStrings.ShowDetailsDownloadDefault; private readonly IBindable localUser = new Bindable(); From 43cbd10a38a8c148ba03a62caf46bcf9c9b73758 Mon Sep 17 00:00:00 2001 From: Davran Dilshat Date: Wed, 18 Aug 2021 18:30:50 +0100 Subject: [PATCH 244/366] change limit to be on actual usage site --- .../Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs | 2 -- .../Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs index 7bad661cf4..61bb39d0c5 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchSettingsOverlay.cs @@ -48,7 +48,6 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components { BackgroundUnfocused = Color4.Black; BackgroundFocused = Color4.Black; - LengthLimit = 100; } } @@ -64,7 +63,6 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components { BackgroundUnfocused = Color4.Black; BackgroundFocused = Color4.Black; - LengthLimit = 255; } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 338d2c9e84..53d494106b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -136,6 +136,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, + LengthLimit = 100, }, }, new Section("Room visibility") @@ -195,6 +196,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, + LengthLimit = 255, }, }, } From ffbe8ddfa4ed5a97c02e9c296479549482224714 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 04:23:02 +0300 Subject: [PATCH 245/366] Refactor lounge sub screen layout for better loading screen appearance --- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 117 ++++++++---------- 1 file changed, 51 insertions(+), 66 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 24aad8c124..ee9331b71a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -76,6 +76,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [BackgroundDependencyLoader(true)] private void load([CanBeNull] IdleTracker idleTracker) { + const float controls_area_height = 25f; + if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); @@ -84,86 +86,69 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { ListingPollingComponent = CreatePollingComponent().With(c => c.Filter.BindTarget = filter), - new Container + scrollContainer = new OsuScrollContainer { + Name = @"Scrollable rooms container", RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { - Left = WaveOverlayContainer.WIDTH_PADDING, - Right = WaveOverlayContainer.WIDTH_PADDING, + Horizontal = WaveOverlayContainer.WIDTH_PADDING, + Top = Header.HEIGHT + controls_area_height + 20, }, - Child = new GridContainer + ScrollbarOverlapsContent = false, + Child = roomsContainer = new RoomsContainer { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + Filter = { BindTarget = filter } + } + }, + loadingLayer = new LoadingLayer(true), + new FillFlowContainer + { + Name = @"Header area flow", + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.WIDTH_PADDING }, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new Container { - new Dimension(GridSizeMode.Absolute, Header.HEIGHT), - new Dimension(GridSizeMode.Absolute, 25), - new Dimension(GridSizeMode.Absolute, 20) + RelativeSizeAxes = Axes.X, + Height = Header.HEIGHT, + Child = searchTextBox = new LoungeSearchTextBox + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.X, + Width = 0.6f, + }, }, - Content = new[] + new Container { - new Drawable[] + RelativeSizeAxes = Axes.X, + Height = controls_area_height, + Children = new Drawable[] { - searchTextBox = new LoungeSearchTextBox + Buttons.WithChild(CreateNewRoomButton().With(d => { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.X, - Width = 0.6f, - }, - }, - new Drawable[] - { - new Container + d.Anchor = Anchor.BottomLeft; + d.Origin = Anchor.BottomLeft; + d.Size = new Vector2(150, 37.5f); + d.Action = () => Open(); + })), + new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Depth = float.MinValue, // Contained filters should appear over the top of rooms. - Children = new Drawable[] + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10), + ChildrenEnumerable = CreateFilterControls().Select(f => f.With(d => { - Buttons.WithChild(CreateNewRoomButton().With(d => - { - d.Anchor = Anchor.BottomLeft; - d.Origin = Anchor.BottomLeft; - d.Size = new Vector2(150, 37.5f); - d.Action = () => Open(); - })), - new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10), - ChildrenEnumerable = CreateFilterControls().Select(f => f.With(d => - { - d.Anchor = Anchor.TopRight; - d.Origin = Anchor.TopRight; - })) - } - } + d.Anchor = Anchor.TopRight; + d.Origin = Anchor.TopRight; + })) } - }, - null, - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - scrollContainer = new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - ScrollbarOverlapsContent = false, - Child = roomsContainer = new RoomsContainer - { - Filter = { BindTarget = filter } - } - }, - loadingLayer = new LoadingLayer(true), - } - }, } } }, From 0e2f3dff4dda07cd8b388d952f92172a657e9f83 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 05:09:49 +0300 Subject: [PATCH 246/366] Fix rooms scroll container not masking properly due to padding --- .../Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index ee9331b71a..0664e44a73 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -86,20 +86,24 @@ namespace osu.Game.Screens.OnlinePlay.Lounge InternalChildren = new Drawable[] { ListingPollingComponent = CreatePollingComponent().With(c => c.Filter.BindTarget = filter), - scrollContainer = new OsuScrollContainer + new Container { - Name = @"Scrollable rooms container", + Name = @"Rooms area", RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = WaveOverlayContainer.WIDTH_PADDING, Top = Header.HEIGHT + controls_area_height + 20, }, - ScrollbarOverlapsContent = false, - Child = roomsContainer = new RoomsContainer + Child = scrollContainer = new OsuScrollContainer { - Filter = { BindTarget = filter } - } + RelativeSizeAxes = Axes.Both, + ScrollbarOverlapsContent = false, + Child = roomsContainer = new RoomsContainer + { + Filter = { BindTarget = filter } + } + }, }, loadingLayer = new LoadingLayer(true), new FillFlowContainer From f4ae587a3385c63f90295c02fb118c9af55935eb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 06:24:06 +0300 Subject: [PATCH 247/366] Extract room request handling logic to its own class --- ...stRequestHandlingMultiplayerRoomManager.cs | 138 ++-------------- .../OnlinePlay/TestRoomRequestsHandler.cs | 147 ++++++++++++++++++ 2 files changed, 159 insertions(+), 126 deletions(-) create mode 100644 osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs diff --git a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs index c3a944f93c..5de518990a 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestRequestHandlingMultiplayerRoomManager.cs @@ -1,150 +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 System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.Rooms; -using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; +using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { /// - /// A for use in multiplayer test scenes. Should generally not be used by itself outside of a . + /// A for use in multiplayer test scenes, backed by a . + /// Should generally not be used by itself outside of a . /// - /// - /// This implementation will pretend to be a server, handling room retrieval and manipulation requests - /// and returning a roughly expected state, without the need for a server to be running. - /// public class TestRequestHandlingMultiplayerRoomManager : MultiplayerRoomManager { - [Resolved] - private IAPIProvider api { get; set; } + public IReadOnlyList ServerSideRooms => handler.ServerSideRooms; - [Resolved] - private OsuGameBase game { get; set; } - - public IReadOnlyList ServerSideRooms => serverSideRooms; - private readonly List serverSideRooms = new List(); - - private int currentRoomId; - private int currentPlaylistItemId; + private readonly TestRoomRequestsHandler handler = new TestRoomRequestsHandler(); [BackgroundDependencyLoader] - private void load() + private void load(IAPIProvider api, OsuGameBase game) { - int currentScoreId = 0; - - // Handling here is pretending to be a server, while also updating the local state to match - // how the server would eventually respond and update the RoomManager. - ((DummyAPIAccess)api).HandleRequest = req => - { - switch (req) - { - case CreateRoomRequest createRoomRequest: - var apiRoom = new Room(); - - apiRoom.CopyFrom(createRoomRequest.Room); - - // Passwords are explicitly not copied between rooms. - apiRoom.HasPassword.Value = !string.IsNullOrEmpty(createRoomRequest.Room.Password.Value); - apiRoom.Password.Value = createRoomRequest.Room.Password.Value; - - AddServerSideRoom(apiRoom); - - var responseRoom = new APICreatedRoom(); - responseRoom.CopyFrom(createResponseRoom(apiRoom, false)); - - createRoomRequest.TriggerSuccess(responseRoom); - return true; - - case JoinRoomRequest joinRoomRequest: - { - var room = ServerSideRooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value); - - if (joinRoomRequest.Password != room.Password.Value) - { - joinRoomRequest.TriggerFailure(new InvalidOperationException("Invalid password.")); - return true; - } - - joinRoomRequest.TriggerSuccess(); - return true; - } - - case PartRoomRequest partRoomRequest: - partRoomRequest.TriggerSuccess(); - return true; - - case GetRoomsRequest getRoomsRequest: - var roomsWithoutParticipants = new List(); - - foreach (var r in ServerSideRooms) - roomsWithoutParticipants.Add(createResponseRoom(r, false)); - - getRoomsRequest.TriggerSuccess(roomsWithoutParticipants); - return true; - - case GetRoomRequest getRoomRequest: - getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true)); - return true; - - case GetBeatmapSetRequest getBeatmapSetRequest: - var onlineReq = new GetBeatmapSetRequest(getBeatmapSetRequest.ID, getBeatmapSetRequest.Type); - onlineReq.Success += res => getBeatmapSetRequest.TriggerSuccess(res); - onlineReq.Failure += e => getBeatmapSetRequest.TriggerFailure(e); - - // Get the online API from the game's dependencies. - game.Dependencies.Get().Queue(onlineReq); - return true; - - case CreateRoomScoreRequest createRoomScoreRequest: - createRoomScoreRequest.TriggerSuccess(new APIScoreToken { ID = 1 }); - return true; - - case SubmitRoomScoreRequest submitRoomScoreRequest: - submitRoomScoreRequest.TriggerSuccess(new MultiplayerScore - { - ID = currentScoreId++, - Accuracy = 1, - EndedAt = DateTimeOffset.Now, - Passed = true, - Rank = ScoreRank.S, - MaxCombo = 1000, - TotalScore = 1000000, - User = api.LocalUser.Value, - Statistics = new Dictionary() - }); - return true; - } - - return false; - }; + ((DummyAPIAccess)api).HandleRequest = request => handler.HandleRequest(request, api.LocalUser.Value, game); } - public void AddServerSideRoom(Room room) - { - room.RoomID.Value ??= currentRoomId++; - for (int i = 0; i < room.Playlist.Count; i++) - room.Playlist[i].ID = currentPlaylistItemId++; - - serverSideRooms.Add(room); - } - - private Room createResponseRoom(Room room, bool withParticipants) - { - var responseRoom = new Room(); - responseRoom.CopyFrom(room); - responseRoom.Password.Value = null; - if (!withParticipants) - responseRoom.RecentParticipants.Clear(); - return responseRoom; - } + /// + /// Adds a room to a local "server-side" list that's returned when a is fired. + /// + /// The room. + public void AddServerSideRoom(Room room) => handler.AddServerSideRoom(room); } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs new file mode 100644 index 0000000000..7f975c9985 --- /dev/null +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs @@ -0,0 +1,147 @@ +// 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.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.Rooms; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.OnlinePlay +{ + /// + /// Represents a handler which pretends to be a server, handling room retrieval and manipulation requests + /// and returning a roughly expected state, without the need for a server to be running. + /// + public class TestRoomRequestsHandler + { + public IReadOnlyList ServerSideRooms => serverSideRooms; + + private readonly List serverSideRooms = new List(); + + private int currentRoomId; + private int currentPlaylistItemId; + private int currentScoreId; + + /// + /// Handles an API request, while also updating the local state to match + /// how the server would eventually respond and update an . + /// + /// The API request to handle. + /// The local user to store in responses where required. + /// The game base for cases where actual online requests need to be sent. + /// Whether the request was successfully handled. + public bool HandleRequest(APIRequest request, User localUser, OsuGameBase game) + { + switch (request) + { + case CreateRoomRequest createRoomRequest: + var apiRoom = new Room(); + + apiRoom.CopyFrom(createRoomRequest.Room); + + // Passwords are explicitly not copied between rooms. + apiRoom.HasPassword.Value = !string.IsNullOrEmpty(createRoomRequest.Room.Password.Value); + apiRoom.Password.Value = createRoomRequest.Room.Password.Value; + + AddServerSideRoom(apiRoom); + + var responseRoom = new APICreatedRoom(); + responseRoom.CopyFrom(createResponseRoom(apiRoom, false)); + + createRoomRequest.TriggerSuccess(responseRoom); + return true; + + case JoinRoomRequest joinRoomRequest: + { + var room = ServerSideRooms.Single(r => r.RoomID.Value == joinRoomRequest.Room.RoomID.Value); + + if (joinRoomRequest.Password != room.Password.Value) + { + joinRoomRequest.TriggerFailure(new InvalidOperationException("Invalid password.")); + return true; + } + + joinRoomRequest.TriggerSuccess(); + return true; + } + + case PartRoomRequest partRoomRequest: + partRoomRequest.TriggerSuccess(); + return true; + + case GetRoomsRequest getRoomsRequest: + var roomsWithoutParticipants = new List(); + + foreach (var r in ServerSideRooms) + roomsWithoutParticipants.Add(createResponseRoom(r, false)); + + getRoomsRequest.TriggerSuccess(roomsWithoutParticipants); + return true; + + case GetRoomRequest getRoomRequest: + getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true)); + return true; + + case GetBeatmapSetRequest getBeatmapSetRequest: + var onlineReq = new GetBeatmapSetRequest(getBeatmapSetRequest.ID, getBeatmapSetRequest.Type); + onlineReq.Success += res => getBeatmapSetRequest.TriggerSuccess(res); + onlineReq.Failure += e => getBeatmapSetRequest.TriggerFailure(e); + + // Get the online API from the game's dependencies. + game.Dependencies.Get().Queue(onlineReq); + return true; + + case CreateRoomScoreRequest createRoomScoreRequest: + createRoomScoreRequest.TriggerSuccess(new APIScoreToken { ID = 1 }); + return true; + + case SubmitRoomScoreRequest submitRoomScoreRequest: + submitRoomScoreRequest.TriggerSuccess(new MultiplayerScore + { + ID = currentScoreId++, + Accuracy = 1, + EndedAt = DateTimeOffset.Now, + Passed = true, + Rank = ScoreRank.S, + MaxCombo = 1000, + TotalScore = 1000000, + User = localUser, + Statistics = new Dictionary() + }); + return true; + } + + return false; + } + + /// + /// Adds a room to a local "server-side" list that's returned when a is fired. + /// + /// The room. + public void AddServerSideRoom(Room room) + { + room.RoomID.Value ??= currentRoomId++; + for (int i = 0; i < room.Playlist.Count; i++) + room.Playlist[i].ID = currentPlaylistItemId++; + + serverSideRooms.Add(room); + } + + private Room createResponseRoom(Room room, bool withParticipants) + { + var responseRoom = new Room(); + responseRoom.CopyFrom(room); + responseRoom.Password.Value = null; + if (!withParticipants) + responseRoom.RecentParticipants.Clear(); + return responseRoom; + } + } +} From 49bc3a8250aeb0d5875f0461ef07eada7c82d915 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 06:25:47 +0300 Subject: [PATCH 248/366] Refactor playlists room manager to handle dummy API requests --- .../TestSceneLoungeRoomsContainer.cs | 4 +- .../TestSceneMultiplayerLoungeSubScreen.cs | 2 +- .../TestScenePlaylistsLoungeSubScreen.cs | 2 +- .../TestScenePlaylistsRoomSubScreen.cs | 13 -- .../Visual/OnlinePlay/BasicTestRoomManager.cs | 111 ------------------ .../OnlinePlayTestSceneDependencies.cs | 2 +- .../TestRequestHandlingRoomManager.cs | 76 ++++++++++++ 7 files changed, 81 insertions(+), 129 deletions(-) delete mode 100644 osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs create mode 100644 osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 7e822f898e..d253b7f8cf 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneLoungeRoomsContainer : OnlinePlayTestScene { - protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager; + protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager; private RoomsContainer container; @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add rooms", () => RoomManager.AddRooms(3)); AddAssert("has 3 rooms", () => container.Rooms.Count == 3); - AddStep("remove first room", () => RoomManager.Rooms.Remove(RoomManager.Rooms.FirstOrDefault())); + AddStep("remove first room", () => RoomManager.RemoveRoom(RoomManager.Rooms.FirstOrDefault())); AddAssert("has 2 rooms", () => container.Rooms.Count == 2); AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0)); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs index c66d5429d6..cc05bc24aa 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayerLoungeSubScreen : OnlinePlayTestScene { - protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager; + protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager; private LoungeSubScreen loungeScreen; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index aff0e7ba4b..f432a6436e 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Playlists { public class TestScenePlaylistsLoungeSubScreen : OnlinePlayTestScene { - protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager; + protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager; private LoungeSubScreen loungeScreen; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs index 9fc29049ef..28090be1f6 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs @@ -11,7 +11,6 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; @@ -36,18 +35,6 @@ namespace osu.Game.Tests.Visual.Playlists { Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default)); - - ((DummyAPIAccess)API).HandleRequest = req => - { - switch (req) - { - case CreateRoomScoreRequest createRoomScoreRequest: - createRoomScoreRequest.TriggerSuccess(new APIScoreToken { ID = 1 }); - return true; - } - - return false; - }; } [SetUpSteps] diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs deleted file mode 100644 index 55fbb9f1a6..0000000000 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ /dev/null @@ -1,111 +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 System.Linq; -using osu.Framework.Bindables; -using osu.Game.Beatmaps; -using osu.Game.Online.Rooms; -using osu.Game.Rulesets; -using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Components; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual.OnlinePlay -{ - /// - /// A very simple for use in online play test scenes. - /// - public class BasicTestRoomManager : IRoomManager - { - public event Action RoomsUpdated; - - public readonly BindableList Rooms = new BindableList(); - - public Action JoinRoomRequested; - - public IBindable InitialRoomsReceived { get; } = new Bindable(true); - - IBindableList IRoomManager.Rooms => Rooms; - - private int currentRoomId; - - public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) - { - room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1; - onSuccess?.Invoke(room); - - AddOrUpdateRoom(room); - } - - public void AddOrUpdateRoom(Room room) - { - var existing = Rooms.FirstOrDefault(r => r.RoomID.Value != null && r.RoomID.Value == room.RoomID.Value); - - if (existing != null) - existing.CopyFrom(room); - else - Rooms.Add(room); - - RoomsUpdated?.Invoke(); - } - - public void RemoveRoom(Room room) - { - Rooms.Remove(room); - RoomsUpdated?.Invoke(); - } - - public void ClearRooms() - { - Rooms.Clear(); - RoomsUpdated?.Invoke(); - } - - public void JoinRoom(Room room, string password, Action onSuccess = null, Action onError = null) - { - JoinRoomRequested?.Invoke(room, password); - onSuccess?.Invoke(room); - } - - public void PartRoom() - { - } - - public void AddRooms(int count, RulesetInfo ruleset = null, bool withPassword = false) - { - for (int i = 0; i < count; i++) - { - var room = new Room - { - RoomID = { Value = currentRoomId }, - Position = { Value = currentRoomId }, - Name = { Value = $"Room {currentRoomId}" }, - Host = { Value = new User { Username = "Host" } }, - EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, - Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal }, - Password = { Value = withPassword ? "password" : string.Empty } - }; - - if (ruleset != null) - { - room.Playlist.Add(new PlaylistItem - { - Ruleset = { Value = ruleset }, - Beatmap = - { - Value = new BeatmapInfo - { - Metadata = new BeatmapMetadata() - } - } - }); - } - - CreateRoom(room); - - currentRoomId++; - } - } - } -} diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index e39711b7ce..defc971eef 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -71,6 +71,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay drawableComponents.Add(drawable); } - protected virtual IRoomManager CreateRoomManager() => new BasicTestRoomManager(); + protected virtual IRoomManager CreateRoomManager() => new TestRequestHandlingRoomManager(); } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs new file mode 100644 index 0000000000..4c7fc0e18f --- /dev/null +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs @@ -0,0 +1,76 @@ +// 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 osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Online.API; +using osu.Game.Online.Rooms; +using osu.Game.Rulesets; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.OnlinePlay +{ + /// + /// A very simple for use in online play test scenes. + /// + public class TestRequestHandlingRoomManager : RoomManager + { + public Action JoinRoomRequested; + + private int currentRoomId; + + private readonly TestRoomRequestsHandler handler = new TestRoomRequestsHandler(); + + [BackgroundDependencyLoader] + private void load(IAPIProvider api, OsuGameBase game) + { + ((DummyAPIAccess)api).HandleRequest = request => handler.HandleRequest(request, api.LocalUser.Value, game); + } + + public override void JoinRoom(Room room, string password = null, Action onSuccess = null, Action onError = null) + { + JoinRoomRequested?.Invoke(room, password); + base.JoinRoom(room, password, onSuccess, onError); + } + + public void AddRooms(int count, RulesetInfo ruleset = null, bool withPassword = false) + { + for (int i = 0; i < count; i++) + { + var room = new Room + { + RoomID = { Value = -currentRoomId }, + Name = { Value = $@"Room {currentRoomId}" }, + Host = { Value = new User { Username = @"Host" } }, + EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, + Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal }, + }; + + if (withPassword) + room.Password.Value = @"password"; + + if (ruleset != null) + { + room.Playlist.Add(new PlaylistItem + { + Ruleset = { Value = ruleset }, + Beatmap = + { + Value = new BeatmapInfo + { + Metadata = new BeatmapMetadata() + } + } + }); + } + + CreateRoom(room); + + currentRoomId++; + } + } + } +} From 47ef33e7316bc93b7f001da29a3d9f8196e685d7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 06:28:31 +0300 Subject: [PATCH 249/366] Fix playlists lounge sub screen test potentially failing --- .../Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index aff0e7ba4b..509b62f69f 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -37,6 +37,7 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("reset mouse", () => InputManager.ReleaseButton(MouseButton.Left)); AddStep("add rooms", () => RoomManager.AddRooms(30)); + AddUntilStep("wait for rooms", () => roomsContainer.Rooms.Count == 30); AddUntilStep("first room is not masked", () => checkRoomVisible(roomsContainer.Rooms[0])); @@ -53,6 +54,7 @@ namespace osu.Game.Tests.Visual.Playlists public void TestScrollSelectedIntoView() { AddStep("add rooms", () => RoomManager.AddRooms(30)); + AddUntilStep("wait for rooms", () => roomsContainer.Rooms.Count == 30); AddUntilStep("first room is not masked", () => checkRoomVisible(roomsContainer.Rooms[0])); From 5fc29328cf1411bea9bc4f4c093ec32b6849087d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 06:30:22 +0300 Subject: [PATCH 250/366] Remove unused using Uh..... --- .../Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs index 4c7fc0e18f..d88fd68b20 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRequestHandlingRoomManager.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.API; From 072560ba3e583d5660f3df7d76999bca1264e390 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 07:17:42 +0300 Subject: [PATCH 251/366] Remove leftover unused using --- osu.Game/Rulesets/Mods/Mod.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 8c2a8a8e8b..9f3b5eaf5b 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; From 6d57a240acf5cd9528b2f688e4a5e4c0388eaaf6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 07:17:22 +0300 Subject: [PATCH 252/366] Add animation support for the star rating display --- .../Beatmaps/Drawables/StarRatingDisplay.cs | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 25cde5fb82..c239fda455 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; @@ -22,6 +23,7 @@ namespace osu.Game.Beatmaps.Drawables /// public class StarRatingDisplay : CompositeDrawable, IHasCurrentValue { + private readonly bool animated; private readonly Box background; private readonly SpriteIcon starIcon; private readonly OsuSpriteText starsText; @@ -34,6 +36,14 @@ namespace osu.Game.Beatmaps.Drawables set => current.Current = value; } + private readonly Bindable displayedStars = new BindableDouble(); + + /// + /// The currently displayed stars of this display wrapped in a bindable. + /// This bindable gets transformed on change rather than instantaneous, if animation is enabled. + /// + public IBindable DisplayedStars => displayedStars; + [Resolved] private OsuColour colours { get; set; } @@ -45,8 +55,11 @@ namespace osu.Game.Beatmaps.Drawables /// /// The already computed to display. /// The size of the star rating display. - public StarRatingDisplay(StarDifficulty starDifficulty, StarRatingDisplaySize size = StarRatingDisplaySize.Regular) + /// Whether the star rating display will perform transforms on change rather than updating instantaneously. + public StarRatingDisplay(StarDifficulty starDifficulty, StarRatingDisplaySize size = StarRatingDisplaySize.Regular, bool animated = false) { + this.animated = animated; + Current.Value = starDifficulty; AutoSizeAxes = Axes.Both; @@ -112,7 +125,7 @@ namespace osu.Game.Beatmaps.Drawables // see https://github.com/ppy/osu-framework/issues/3271. Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold), Shadow = false, - } + }, } } }, @@ -126,12 +139,22 @@ namespace osu.Game.Beatmaps.Drawables Current.BindValueChanged(c => { - starsText.Text = c.NewValue.Stars.ToString("0.00"); + if (animated) + this.TransformBindableTo(displayedStars, c.NewValue.Stars, 750, Easing.OutQuint); + else + displayedStars.Value = c.NewValue.Stars; + }); - background.Colour = colours.ForStarDifficulty(c.NewValue.Stars); + displayedStars.Value = Current.Value.Stars; - starIcon.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); - starsText.Colour = c.NewValue.Stars >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); + displayedStars.BindValueChanged(s => + { + starsText.Text = s.NewValue.ToLocalisableString("0.00"); + + background.Colour = colours.ForStarDifficulty(s.NewValue); + + starIcon.Colour = s.NewValue >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4Extensions.FromHex("303d47"); + starsText.Colour = s.NewValue >= 6.5 ? colours.Orange1 : colourProvider?.Background5 ?? Color4.Black.Opacity(0.75f); }, true); } } From 25e6317e7f1a51dc6cd15edbafaccb10d499a4d1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 07:18:02 +0300 Subject: [PATCH 253/366] Use animated star display in beatmap info wedge and synchronise bar --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 83 +++++++-------------- 1 file changed, 26 insertions(+), 57 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 14c32f2348..1e1f362d71 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -21,7 +21,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Configuration; @@ -157,7 +156,7 @@ namespace osu.Game.Screens.Select public BeatmapSetOnlineStatusPill StatusPill { get; private set; } public FillFlowContainer MapperContainer { get; private set; } - private DifficultyColourBar difficultyColourBar; + private Container difficultyColourBar; private StarRatingDisplay starRatingDisplay; private ILocalisedBindableString titleBinding; @@ -182,7 +181,7 @@ namespace osu.Game.Screens.Select private IBindable starDifficulty; [BackgroundDependencyLoader] - private void load(LocalisationManager localisation, BeatmapDifficultyCache difficultyCache) + private void load(OsuColour colours, LocalisationManager localisation, BeatmapDifficultyCache difficultyCache) { var beatmapInfo = beatmap.BeatmapInfo; var metadata = beatmapInfo.Metadata ?? beatmap.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); @@ -194,10 +193,26 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { - difficultyColourBar = new DifficultyColourBar + difficultyColourBar = new Container { RelativeSizeAxes = Axes.Y, - Width = 20, + Width = 20f, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Width = 0.7f, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Alpha = 0.5f, + X = 0.7f, + Width = 1 - 0.7f, + } + } }, new FillFlowContainer { @@ -230,7 +245,7 @@ namespace osu.Game.Screens.Select Shear = wedged_container_shear, Children = new Drawable[] { - starRatingDisplay = new StarRatingDisplay(default) + starRatingDisplay = new StarRatingDisplay(default, animated: true) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -292,11 +307,14 @@ namespace osu.Game.Screens.Select titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); + starRatingDisplay.DisplayedStars.BindValueChanged(s => + { + difficultyColourBar.Colour = colours.ForStarDifficulty(s.NewValue); + }, true); + starDifficulty = difficultyCache.GetBindableDifficulty(beatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); starDifficulty.BindValueChanged(s => { - difficultyColourBar.Current.Value = s.NewValue ?? default; - starRatingDisplay.FadeIn(transition_duration); starRatingDisplay.Current.Value = s.NewValue ?? default; }); @@ -480,55 +498,6 @@ namespace osu.Game.Screens.Select }; } } - - public class DifficultyColourBar : Container, IHasCurrentValue - { - private readonly BindableWithCurrent current = new BindableWithCurrent(); - - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } - - [Resolved] - private OsuColour colours { get; set; } - - [BackgroundDependencyLoader] - private void load() - { - const float full_opacity_ratio = 0.7f; - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Width = full_opacity_ratio, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Both, - Alpha = 0.5f, - X = full_opacity_ratio, - Width = 1 - full_opacity_ratio, - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - Current.BindValueChanged(c => - { - this.FadeColour(colours.ForStarDifficulty(c.NewValue.Stars), transition_duration, Easing.OutQuint); - }, true); - - FinishTransforms(true); - } - } } } } From 65c0ae757bfeb80bf3fe324d80a9cb19dc6d0fcc Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 07:18:18 +0300 Subject: [PATCH 254/366] Merge spectrum test case --- .../TestSceneStarRatingDisplay.cs | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 052251d5a8..2806e6d347 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -3,7 +3,6 @@ using System.Linq; using NUnit.Framework; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; @@ -50,32 +49,7 @@ namespace osu.Game.Tests.Visual.UserInterface { StarRatingDisplay starRating = null; - BindableDouble starRatingNumeric; - - AddStep("load display", () => - { - Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(3f), - }; - }); - - AddStep("transform over spectrum", () => - { - starRatingNumeric = new BindableDouble(); - starRatingNumeric.BindValueChanged(val => starRating.Current.Value = new StarDifficulty(val.NewValue, 1)); - this.TransformBindableTo(starRatingNumeric, 10, 10000, Easing.OutQuint); - }); - } - - [Test] - public void TestChangingStarRatingDisplay() - { - StarRatingDisplay starRating = null; - - AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1)) + AddStep("load display", () => Child = starRating = new StarRatingDisplay(new StarDifficulty(5.55, 1), animated: true) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 786beb975941b61a98e1e282f1ad0b16a34a3943 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 14:14:47 +0900 Subject: [PATCH 255/366] Fix missing initial state test step --- .../Visual/Multiplayer/TestSceneGameplayChatDisplay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs index 51960680d6..08aa967c61 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs @@ -85,6 +85,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestFocusOnTabKeyWhenExpanded() { + setLocalUserPlaying(true); + assertChatFocused(false); AddStep("press tab", () => InputManager.Key(Key.Tab)); assertChatFocused(true); From 6d00ea3375d80c953b8978a0b9505226c4506647 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 14:19:59 +0900 Subject: [PATCH 256/366] Allow toggling focus via binding --- .../Multiplayer/TestSceneGameplayChatDisplay.cs | 15 +++++++++++++++ .../Graphics/UserInterface/FocusedTextBox.cs | 2 ++ osu.Game/Input/Bindings/GlobalActionContainer.cs | 6 +++--- .../Multiplayer/GameplayChatDisplay.cs | 16 ++++++++++++---- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs index 08aa967c61..eadfc9b279 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs @@ -107,6 +107,21 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("is not visible", () => !chatDisplay.IsPresent); } + [Test] + public void TestFocusToggleViaAction() + { + AddStep("set not expanded", () => chatDisplay.Expanded.Value = false); + AddUntilStep("is not visible", () => !chatDisplay.IsPresent); + + AddStep("press tab", () => InputManager.Key(Key.Tab)); + assertChatFocused(true); + AddUntilStep("is visible", () => chatDisplay.IsPresent); + + AddStep("press tab", () => InputManager.Key(Key.Tab)); + assertChatFocused(false); + AddUntilStep("is not visible", () => !chatDisplay.IsPresent); + } + private void assertChatFocused(bool isFocused) => AddAssert($"chat {(isFocused ? "focused" : "not focused")}", () => textBox.HasFocus == isFocused); diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index f77a3109c9..2705caccff 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -25,6 +25,8 @@ namespace osu.Game.Graphics.UserInterface if (allowImmediateFocus) GetContainingInputManager().ChangeFocus(this); } + public new void KillFocus() => base.KillFocus(); + public bool HoldFocus { get => allowImmediateFocus && focus; diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 66edb25d64..0176a00e9d 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -90,7 +90,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Left, GlobalAction.SeekReplayBackward), new KeyBinding(InputKey.Right, GlobalAction.SeekReplayForward), new KeyBinding(InputKey.Control, GlobalAction.HoldForHUD), - new KeyBinding(InputKey.Tab, GlobalAction.FocusChatInput), + new KeyBinding(InputKey.Tab, GlobalAction.ToggleChatFocus), }; public IEnumerable SongSelectKeyBindings => new[] @@ -282,7 +282,7 @@ namespace osu.Game.Input.Bindings [Description("Seek replay backward")] SeekReplayBackward, - [Description("Focus chat")] - FocusChatInput + [Description("Toggle chat focus")] + ToggleChatFocus } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index 5d494379e6..e2f135d436 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -71,11 +71,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { switch (action) { - case GlobalAction.FocusChatInput: - expandedFromTextboxFocus.Value = true; + case GlobalAction.ToggleChatFocus: + if (Textbox.HasFocus) + { + Schedule(() => Textbox.KillFocus()); + } + else + { + expandedFromTextboxFocus.Value = true; + + // schedule required to ensure the textbox has become present from above bindable update. + Schedule(() => Textbox.TakeFocus()); + } - // schedule required to ensure the textbox has become present from above bindable update. - Schedule(() => Textbox.TakeFocus()); return true; } From 6bfae25cda203f6bf5482281b7aa3f4568f52225 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Aug 2021 08:30:27 +0300 Subject: [PATCH 257/366] Apply 5px vertical spacing on fill flow Regressed, was margin { bottom = 5f } from the star rating display creation method, which I've partly inlined. --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 1e1f362d71..17a26eb7ee 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -243,6 +243,7 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Top = 14, Right = shear_width / 2 }, AutoSizeAxes = Axes.Both, Shear = wedged_container_shear, + Spacing = new Vector2(0f, 5f), Children = new Drawable[] { starRatingDisplay = new StarRatingDisplay(default, animated: true) From 6469eaa427cf038725f05e93d88065e5f4135449 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 15:52:51 +0900 Subject: [PATCH 258/366] Fix background not updated in room --- .../Lounge/Components/DrawableRoom.cs | 10 +++--- .../OnlinePlay/Match/DrawableMatchRoom.cs | 2 ++ .../OnlinePlay/Match/RoomBackgroundSprite.cs | 33 +++++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Match/RoomBackgroundSprite.cs diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index c5b8bffbc6..bbec9aa21d 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -61,7 +61,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) { - InternalChildren = new Drawable[] + InternalChildren = new[] { // This resolves internal 1px gaps due to applying the (parenting) corner radius and masking across multiple filling background sprites. new Box @@ -69,10 +69,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Colour = colours.Background5, }, - new OnlinePlayBackgroundSprite + CreateBackground().With(d => { - RelativeSizeAxes = Axes.Both - }, + d.RelativeSizeAxes = Axes.Both; + }), new Container { Name = @"Room content", @@ -264,6 +264,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } + protected virtual Drawable CreateBackground() => new OnlinePlayBackgroundSprite(); + private class RoomNameText : OsuSpriteText { [Resolved(typeof(Room), nameof(Online.Rooms.Room.Name))] diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index b3e6292f45..0924773338 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -58,5 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Match if (editButton != null) host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true); } + + protected override Drawable CreateBackground() => new RoomBackgroundSprite(); } } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundSprite.cs new file mode 100644 index 0000000000..97262dd229 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundSprite.cs @@ -0,0 +1,33 @@ +// 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.Game.Beatmaps.Drawables; + +namespace osu.Game.Screens.OnlinePlay.Match +{ + public class RoomBackgroundSprite : RoomSubScreenComposite + { + protected readonly BeatmapSetCoverType BeatmapSetCoverType; + private UpdateableBeatmapBackgroundSprite sprite; + + public RoomBackgroundSprite(BeatmapSetCoverType beatmapSetCoverType = BeatmapSetCoverType.Cover) + { + BeatmapSetCoverType = beatmapSetCoverType; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = sprite = new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + SelectedItem.BindValueChanged(item => sprite.Beatmap.Value = item.NewValue?.Beatmap.Value, true); + } + } +} From 1fd746524d1963f96333cec766110acc5cbc4e2f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 16:09:17 +0900 Subject: [PATCH 259/366] Remove realtime room category, fix end-date showing for realtime --- .../Visual/Multiplayer/TestSceneDrawableRoom.cs | 8 +------- osu.Game/Online/Rooms/RoomCategory.cs | 1 - .../OnlinePlay/Lounge/Components/DrawableRoom.cs | 12 ++++++++++-- .../Multiplayer/MultiplayerLoungeSubScreen.cs | 1 - 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 489ece3271..8ca578b592 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -108,12 +108,6 @@ namespace osu.Game.Tests.Visual.Multiplayer EndDate = { Value = DateTimeOffset.Now }, }), createDrawableRoom(new Room - { - Name = { Value = "Room 4 (realtime)" }, - Status = { Value = new RoomStatusOpen() }, - Category = { Value = RoomCategory.Realtime }, - }), - createDrawableRoom(new Room { Name = { Value = "Room 4 (spotlight)" }, Status = { Value = new RoomStatusOpen() }, @@ -134,7 +128,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { Name = { Value = "Room with password" }, Status = { Value = new RoomStatusOpen() }, - Category = { Value = RoomCategory.Realtime }, + Type = { Value = MatchType.HeadToHead }, })); AddAssert("password icon hidden", () => Precision.AlmostEquals(0, drawableRoom.ChildrenOfType().Single().Alpha)); diff --git a/osu.Game/Online/Rooms/RoomCategory.cs b/osu.Game/Online/Rooms/RoomCategory.cs index bb9f1298d3..a1dcfa5fd9 100644 --- a/osu.Game/Online/Rooms/RoomCategory.cs +++ b/osu.Game/Online/Rooms/RoomCategory.cs @@ -8,6 +8,5 @@ namespace osu.Game.Online.Rooms // used for osu-web deserialization so names shouldn't be changed. Normal, Spotlight, - Realtime, } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index bbec9aa21d..106211c833 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -34,12 +34,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components protected Container ButtonsContainer { get; private set; } + private readonly Bindable roomType = new Bindable(); private readonly Bindable roomCategory = new Bindable(); private readonly Bindable hasPassword = new Bindable(); private RecentParticipantsList recentParticipantsList; private RoomSpecialCategoryPill specialCategoryPill; private PasswordProtectedIcon passwordIcon; + private EndDateInfo endDateInfo; public DrawableRoom(Room room) { @@ -144,10 +146,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }, - new EndDateInfo + endDateInfo = new EndDateInfo { Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft + Origin = Anchor.CentreLeft, }, } }, @@ -238,6 +240,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components specialCategoryPill.Hide(); }, true); + roomType.BindTo(Room.Type); + roomType.BindValueChanged(t => + { + endDateInfo.Alpha = t.NewValue == MatchType.Playlists ? 1 : 0; + }, true); + hasPassword.BindTo(Room.HasPassword); hasPassword.BindValueChanged(v => passwordIcon.Alpha = v.NewValue ? 1 : 0, true); } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index d152fc3913..6c3dfe7382 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -50,7 +50,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override Room CreateNewRoom() => new Room { Name = { Value = $"{api.LocalUser}'s awesome room" }, - Category = { Value = RoomCategory.Realtime }, Type = { Value = MatchType.HeadToHead }, }; From c31af96f1d18fb858bc4f5163439458e5dec2811 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 16:40:27 +0900 Subject: [PATCH 260/366] Pass room into RoomSettingsOverlay --- .../TestScenePlaylistsMatchSettingsOverlay.cs | 7 ++- .../Match/Components/RoomSettingsOverlay.cs | 11 +++-- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 5 ++- .../Match/MultiplayerMatchSettingsOverlay.cs | 44 +++++++++++-------- .../Multiplayer/MultiplayerMatchSubScreen.cs | 17 ++----- .../Playlists/PlaylistsRoomSettingsOverlay.cs | 29 +++++++----- .../Playlists/PlaylistsRoomSubScreen.cs | 4 +- 7 files changed, 66 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 04b44efd32..48222e6b94 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual.Playlists { SelectedRoom.Value = new Room(); - Child = settings = new TestRoomSettings + Child = settings = new TestRoomSettings(SelectedRoom.Value) { RelativeSizeAxes = Axes.Both, State = { Value = Visibility.Visible } @@ -118,6 +118,11 @@ namespace osu.Game.Tests.Visual.Playlists public OsuDropdown DurationField => ((MatchSettings)Settings).DurationField; public OsuSpriteText ErrorText => ((MatchSettings)Settings).ErrorText; + + public TestRoomSettings(Room room) + : base(room) + { + } } private class TestDependencies : OnlinePlayTestSceneDependencies diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index 80a22880d4..7a8839cdad 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; +using osu.Game.Online.Rooms; using osuTK; using osuTK.Graphics; @@ -27,8 +28,12 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected abstract bool IsLoading { get; } - protected RoomSettingsOverlay() + private readonly Room room; + + protected RoomSettingsOverlay(Room room) { + this.room = room; + RelativeSizeAxes = Axes.Both; Masking = true; CornerRadius = 10; @@ -37,12 +42,12 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components [BackgroundDependencyLoader] private void load() { - Add(Settings = CreateSettings()); + Add(Settings = CreateSettings(room)); } protected abstract void SelectBeatmap(); - protected abstract OnlinePlayComposite CreateSettings(); + protected abstract OnlinePlayComposite CreateSettings(Room room); protected override void PopIn() { diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 81fae558c8..389eba0d82 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -184,7 +184,7 @@ namespace osu.Game.Screens.OnlinePlay.Match RelativeSizeAxes = Axes.Both, // Resolves 1px masking errors between the settings overlay and the room panel. Padding = new MarginPadding(-1), - Child = settingsOverlay = CreateRoomSettingsOverlay() + Child = settingsOverlay = CreateRoomSettingsOverlay(Room) } }, }, @@ -406,7 +406,8 @@ namespace osu.Game.Screens.OnlinePlay.Match /// /// Creates the room settings overlay. /// - protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(); + /// + protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(Room room); private class UserModSelectOverlay : LocalPlayerModSelectOverlay { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 3a95ac00a6..cd78a94765 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -37,15 +37,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match protected override bool IsLoading => ongoingOperationTracker.InProgress.Value; + public MultiplayerMatchSettingsOverlay(Room room) + : base(room) + { + } + protected override void SelectBeatmap() => settings.SelectBeatmap(); - protected override OnlinePlayComposite CreateSettings() - => settings = new MatchSettings - { - RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Y, - SettingsApplied = Hide - }; + protected override OnlinePlayComposite CreateSettings(Room room) => settings = new MatchSettings(room) + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Y, + SettingsApplied = Hide + }; protected class MatchSettings : OnlinePlayComposite { @@ -73,9 +77,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match [Resolved] private MultiplayerClient client { get; set; } - [Resolved] - private Bindable currentRoom { get; set; } - [Resolved] private Bindable beatmap { get; set; } @@ -90,6 +91,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match [CanBeNull] private IDisposable applyingSettingsOperation; + private readonly Room room; + + public MatchSettings(Room room) + { + this.room = room; + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -319,24 +327,24 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match client.ChangeSettings(name: NameField.Text, password: PasswordTextBox.Text, matchType: TypePicker.Current.Value).ContinueWith(t => Schedule(() => { if (t.IsCompletedSuccessfully) - onSuccess(currentRoom.Value); + onSuccess(room); else onError(t.Exception?.AsSingular().Message ?? "Error changing settings."); })); } else { - currentRoom.Value.Name.Value = NameField.Text; - currentRoom.Value.Availability.Value = AvailabilityPicker.Current.Value; - currentRoom.Value.Type.Value = TypePicker.Current.Value; - currentRoom.Value.Password.Value = PasswordTextBox.Current.Value; + room.Name.Value = NameField.Text; + room.Availability.Value = AvailabilityPicker.Current.Value; + room.Type.Value = TypePicker.Current.Value; + room.Password.Value = PasswordTextBox.Current.Value; if (int.TryParse(MaxParticipantsField.Text, out int max)) - currentRoom.Value.MaxParticipants.Value = max; + room.MaxParticipants.Value = max; else - currentRoom.Value.MaxParticipants.Value = null; + room.MaxParticipants.Value = null; - manager?.CreateRoom(currentRoom.Value, onSuccess, onError); + manager?.CreateRoom(room, onSuccess, onError); } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 3f5837cbbe..833e6b24e0 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -48,9 +48,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private OngoingOperationTracker ongoingOperationTracker { get; set; } - [Resolved] - private Bindable currentRoom { get; set; } // Todo: This should not exist. - private readonly IBindable isConnected = new Bindable(); [CanBeNull] @@ -82,16 +79,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer handleRoomLost(); }, true); - currentRoom.BindValueChanged(room => - { - if (room.NewValue == null) - { - // the room has gone away. - // this could mean something happened during the join process, or an external connection issue occurred. - // one specific scenario is where the underlying room is created, but the signalr server returns an error during the join process. this triggers a PartRoom operation (see https://github.com/ppy/osu/blob/7654df94f6f37b8382be7dfcb4f674e03bd35427/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs#L97) - handleRoomLost(); - } - }, true); + if (client.Room == null) + handleRoomLost(); } protected override Drawable CreateMainContent() => new GridContainer @@ -223,7 +212,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer OnSpectateClick = onSpectateClick }; - protected override RoomSettingsOverlay CreateRoomSettingsOverlay() => new MultiplayerMatchSettingsOverlay(); + protected override RoomSettingsOverlay CreateRoomSettingsOverlay(Room room) => new MultiplayerMatchSettingsOverlay(room); protected override void UpdateMods() { diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs index 3eea59006a..7384c60888 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Specialized; using Humanizer; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -32,15 +31,19 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override bool IsLoading => settings.IsLoading; // should probably be replaced with an OngoingOperationTracker. + public PlaylistsRoomSettingsOverlay(Room room) + : base(room) + { + } + protected override void SelectBeatmap() => settings.SelectBeatmap(); - protected override OnlinePlayComposite CreateSettings() - => settings = new MatchSettings - { - RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Y, - EditPlaylist = () => EditPlaylist?.Invoke() - }; + protected override OnlinePlayComposite CreateSettings(Room room) => settings = new MatchSettings(room) + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Y, + EditPlaylist = () => EditPlaylist?.Invoke() + }; protected class MatchSettings : OnlinePlayComposite { @@ -66,8 +69,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [Resolved(CanBeNull = true)] private IRoomManager manager { get; set; } - [Resolved] - private Bindable currentRoom { get; set; } + private readonly Room room; + + public MatchSettings(Room room) + { + this.room = room; + } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -333,7 +340,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists Duration.Value = DurationField.Current.Value; - manager?.CreateRoom(currentRoom.Value, onSuccess, onError); + manager?.CreateRoom(room, onSuccess, onError); loadingLayer.Show(); } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 27de781d5f..cd38e658a2 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); - AddInternal(selectionPollingComponent = new SelectionPollingComponent()); + AddInternal(selectionPollingComponent = new SelectionPollingComponent(Room)); } protected override void LoadComplete() @@ -183,7 +183,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists OnStart = StartPlay }; - protected override RoomSettingsOverlay CreateRoomSettingsOverlay() => new PlaylistsRoomSettingsOverlay + protected override RoomSettingsOverlay CreateRoomSettingsOverlay(Room room) => new PlaylistsRoomSettingsOverlay(room) { EditPlaylist = () => { From 3a1154c00e85c834789d2e4772d0efc8017c1ba3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 16:40:39 +0900 Subject: [PATCH 261/366] Pass room into SelectionPollingComponent --- .../Components/SelectionPollingComponent.cs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs index 88d9469f8c..0769d0747b 100644 --- a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs @@ -3,7 +3,6 @@ using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components @@ -13,20 +12,14 @@ namespace osu.Game.Screens.OnlinePlay.Components /// public class SelectionPollingComponent : RoomPollingComponent { - [Resolved] - private Bindable selectedRoom { get; set; } - [Resolved] private IRoomManager roomManager { get; set; } - [BackgroundDependencyLoader] - private void load() + private readonly Room room; + + public SelectionPollingComponent(Room room) { - selectedRoom.BindValueChanged(_ => - { - if (IsLoaded) - PollImmediately(); - }); + this.room = room; } private GetRoomRequest pollReq; @@ -36,13 +29,13 @@ namespace osu.Game.Screens.OnlinePlay.Components if (!API.IsLoggedIn) return base.Poll(); - if (selectedRoom.Value?.RoomID.Value == null) + if (room.RoomID.Value == null) return base.Poll(); var tcs = new TaskCompletionSource(); pollReq?.Cancel(); - pollReq = new GetRoomRequest(selectedRoom.Value.RoomID.Value.Value); + pollReq = new GetRoomRequest(room.RoomID.Value.Value); pollReq.Success += result => { From 00be7f4cca50f5136a5c73d024b9eaa47cbcae4d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 16:49:08 +0900 Subject: [PATCH 262/366] Make RoomsContainer/DrawableRoom not resolve via DI --- .../Multiplayer/TestSceneDrawableRoom.cs | 11 ++++--- .../TestSceneLoungeRoomsContainer.cs | 1 + .../Lounge/Components/RoomsContainer.cs | 31 ++++++++----------- .../OnlinePlay/Lounge/DrawableLoungeRoom.cs | 15 +++++---- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 3 +- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 8ca578b592..3973dc57b2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -24,12 +24,11 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneDrawableRoom : OsuTestScene { - [Cached] - private readonly Bindable selectedRoom = new Bindable(); - [Cached] protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); + private readonly Bindable selectedRoom = new Bindable(); + [Test] public void TestMultipleStatuses() { @@ -153,7 +152,11 @@ namespace osu.Game.Tests.Visual.Multiplayer })); } - return new DrawableLoungeRoom(room) { MatchingFilter = true }; + return new DrawableLoungeRoom(room) + { + MatchingFilter = true, + SelectedRoom = { BindTarget = selectedRoom } + }; } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index b23638e514..66298e9b3d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -30,6 +30,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Width = 0.5f, + SelectedRoom = { BindTarget = SelectedRoom } }; }); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index be5558ed0b..76cb02199b 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -23,16 +23,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public class RoomsContainer : CompositeDrawable, IKeyBindingHandler { - private readonly IBindableList rooms = new BindableList(); - - private readonly FillFlowContainer roomFlow; + public readonly Bindable SelectedRoom = new Bindable(); + public readonly Bindable Filter = new Bindable(); public IReadOnlyList Rooms => roomFlow.FlowingChildren.Cast().ToArray(); - public readonly Bindable Filter = new Bindable(); - - [Resolved] - private Bindable selectedRoom { get; set; } + private readonly IBindableList rooms = new BindableList(); + private readonly FillFlowContainer roomFlow; [Resolved] private IRoomManager roomManager { get; set; } @@ -112,9 +109,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void addRooms(IEnumerable rooms) { foreach (var room in rooms) - { - roomFlow.Add(new DrawableLoungeRoom(room)); - } + roomFlow.Add(new DrawableLoungeRoom(room) { SelectedRoom = { BindTarget = SelectedRoom } }); applyFilterCriteria(Filter?.Value); } @@ -126,8 +121,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components roomFlow.RemoveAll(d => d.Room == r); // selection may have a lease due to being in a sub screen. - if (!selectedRoom.Disabled) - selectedRoom.Value = null; + if (!SelectedRoom.Disabled) + SelectedRoom.Value = null; } } @@ -139,8 +134,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components protected override bool OnClick(ClickEvent e) { - if (!selectedRoom.Disabled) - selectedRoom.Value = null; + if (!SelectedRoom.Disabled) + SelectedRoom.Value = null; return base.OnClick(e); } @@ -202,26 +197,26 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void selectNext(int direction) { - if (selectedRoom.Disabled) + if (SelectedRoom.Disabled) return; var visibleRooms = Rooms.AsEnumerable().Where(r => r.IsPresent); Room room; - if (selectedRoom.Value == null) + if (SelectedRoom.Value == null) room = visibleRooms.FirstOrDefault()?.Room; else { if (direction < 0) visibleRooms = visibleRooms.Reverse(); - room = visibleRooms.SkipWhile(r => r.Room != selectedRoom.Value).Skip(1).FirstOrDefault()?.Room; + room = visibleRooms.SkipWhile(r => r.Room != SelectedRoom.Value).Skip(1).FirstOrDefault()?.Room; } // we already have a valid selection only change selection if we still have a room to switch to. if (room != null) - selectedRoom.Value = room; + SelectedRoom.Value = room; } #endregion diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 4e106b844c..7ff3298829 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -34,11 +34,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private const float transition_duration = 60; private const float selection_border_width = 4; - [Resolved(canBeNull: true)] - private LoungeSubScreen lounge { get; set; } + public readonly Bindable SelectedRoom = new Bindable(); [Resolved(canBeNull: true)] - private Bindable selectedRoom { get; set; } + private LoungeSubScreen lounge { get; set; } private Sample sampleSelect; private Sample sampleJoin; @@ -89,7 +88,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge else Alpha = 0; - selectedRoom.BindValueChanged(updateSelectedRoom, true); + SelectedRoom.BindValueChanged(updateSelectedRoom, true); } private void updateSelectedRoom(ValueChangedEvent selected) @@ -135,7 +134,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge public bool OnPressed(GlobalAction action) { - if (selectedRoom.Value != Room) + if (SelectedRoom.Value != Room) return false; switch (action) @@ -152,14 +151,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { } - protected override bool ShouldBeConsideredForInput(Drawable child) => selectedRoom.Value == Room || child is HoverSounds; + protected override bool ShouldBeConsideredForInput(Drawable child) => SelectedRoom.Value == Room || child is HoverSounds; protected override bool OnClick(ClickEvent e) { - if (Room != selectedRoom.Value) + if (Room != SelectedRoom.Value) { sampleSelect?.Play(); - selectedRoom.Value = Room; + SelectedRoom.Value = Room; return true; } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 8bed3d6049..677b9c0782 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -159,7 +159,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge ScrollbarOverlapsContent = false, Child = roomsContainer = new RoomsContainer { - Filter = { BindTarget = filter } + Filter = { BindTarget = filter }, + SelectedRoom = { BindTarget = selectedRoom } } }, } From 4d1897c6b42f54657ef0025df8526c1ea1ff9477 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 16:49:53 +0900 Subject: [PATCH 263/366] Remove unnecessary resolve into ListingPollingComponent --- .../Screens/OnlinePlay/Components/ListingPollingComponent.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index 1387b5a671..daac6a66cd 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -20,9 +20,6 @@ namespace osu.Game.Screens.OnlinePlay.Components public readonly Bindable Filter = new Bindable(); - [Resolved] - private Bindable selectedRoom { get; set; } - [BackgroundDependencyLoader] private void load() { From 6b6d52c23b99fd981725d6f79ea41e4210a75735 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 16:53:07 +0900 Subject: [PATCH 264/366] Add dependency container to RoomSubScreen --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 389eba0d82..487ec9bb49 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -239,6 +239,14 @@ namespace osu.Game.Screens.OnlinePlay.Match UserMods.BindValueChanged(_ => Scheduler.AddOnce(UpdateMods)); } + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + return new CachedModelDependencyContainer(base.CreateChildDependencies(parent)) + { + Model = { Value = Room } + }; + } + public override bool OnBackButton() { if (Room.RoomID.Value == null) From da8a1692d9cbdcf8ba24dde2ac30e43cfc6ccf11 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 17:40:59 +0900 Subject: [PATCH 265/366] Add test coverage of multiplayer room/state messagepack serialisation --- ...TestMultiplayerMessagePackSerialization.cs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs diff --git a/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs b/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs new file mode 100644 index 0000000000..5491774e26 --- /dev/null +++ b/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs @@ -0,0 +1,72 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using MessagePack; +using NUnit.Framework; +using osu.Game.Online; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; + +namespace osu.Game.Tests.Online +{ + [TestFixture] + public class TestMultiplayerMessagePackSerialization + { + [Test] + public void TestSerialiseRoom() + { + var room = new MultiplayerRoom(1) + { + MatchState = new TeamVersusRoomState() + }; + + var serialized = MessagePackSerializer.Serialize(room); + + var deserialized = MessagePackSerializer.Deserialize(serialized); + + Assert.IsTrue(deserialized.MatchState is TeamVersusRoomState); + } + + [Test] + public void TestSerialiseUserStateExpected() + { + var state = new TeamVersusUserState(); + + var serialized = MessagePackSerializer.Serialize(typeof(MatchUserState), state); + var deserialized = MessagePackSerializer.Deserialize(serialized); + + Assert.IsTrue(deserialized is TeamVersusUserState); + } + + [Test] + public void TestSerialiseUnionFailsWithSingalR() + { + var state = new TeamVersusUserState(); + + // SignalR serialises using the actual type, rather than a base specification. + var serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state); + + // works with explicit type specified. + MessagePackSerializer.Deserialize(serialized); + + // fails with base (union) type. + Assert.Throws(() => MessagePackSerializer.Deserialize(serialized)); + } + + [Test] + public void TestSerialiseUnionSucceedsWithWorkaround() + { + var state = new TeamVersusUserState(); + + // SignalR serialises using the actual type, rather than a base specification. + var serialized = MessagePackSerializer.Serialize(typeof(TeamVersusUserState), state, SignalRUnionWorkaroundResolver.OPTIONS); + + // works with explicit type specified. + MessagePackSerializer.Deserialize(serialized); + + // works with custom resolver. + var deserialized = MessagePackSerializer.Deserialize(serialized, SignalRUnionWorkaroundResolver.OPTIONS); + Assert.IsTrue(deserialized is TeamVersusUserState); + } + } +} From fa01e4fad2ba730ee7e0d73c47d3f929ec979b7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 17:41:50 +0900 Subject: [PATCH 266/366] Add workaround for SignalR union serialisation --- osu.Game/Online/HubClientConnector.cs | 7 ++- .../Online/SignalRUnionWorkaroundResolver.cs | 61 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Online/SignalRUnionWorkaroundResolver.cs diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs index d2dba8a402..e9d6960c71 100644 --- a/osu.Game/Online/HubClientConnector.cs +++ b/osu.Game/Online/HubClientConnector.cs @@ -148,7 +148,12 @@ namespace osu.Game.Online }); if (RuntimeInfo.SupportsJIT && preferMessagePack) - builder.AddMessagePackProtocol(); + { + builder.AddMessagePackProtocol(options => + { + options.SerializerOptions = SignalRUnionWorkaroundResolver.OPTIONS; + }); + } else { // eventually we will precompile resolvers for messagepack, but this isn't working currently diff --git a/osu.Game/Online/SignalRUnionWorkaroundResolver.cs b/osu.Game/Online/SignalRUnionWorkaroundResolver.cs new file mode 100644 index 0000000000..e44da044cc --- /dev/null +++ b/osu.Game/Online/SignalRUnionWorkaroundResolver.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 System.Collections.Generic; +using MessagePack; +using MessagePack.Formatters; +using MessagePack.Resolvers; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; + +namespace osu.Game.Online +{ + /// + /// Handles SignalR being unable to comprehend [Union] types correctly by redirecting to a known base (union) type. + /// See https://github.com/dotnet/aspnetcore/issues/7298. + /// + public class SignalRUnionWorkaroundResolver : IFormatterResolver + { + public static readonly MessagePackSerializerOptions OPTIONS = + MessagePackSerializerOptions.Standard.WithResolver(new SignalRUnionWorkaroundResolver()); + + private static readonly Dictionary formatter_map = new Dictionary + { + { typeof(TeamVersusUserState), new TypeRedirectingFormatter() }, + { typeof(TeamVersusRoomState), new TypeRedirectingFormatter() }, + { typeof(ChangeTeamRequest), new TypeRedirectingFormatter() }, + + // These should not be required. The fallback should work. But something is weird with the way caching is done. + // For future adventurers, I would not advise looking into this further. It's likely not worth the effort. + { typeof(MatchUserState), new TypeRedirectingFormatter() }, + { typeof(MatchRoomState), new TypeRedirectingFormatter() }, + { typeof(MatchUserRequest), new TypeRedirectingFormatter() }, + { typeof(MatchServerEvent), new TypeRedirectingFormatter() }, + }; + + public IMessagePackFormatter GetFormatter() + { + if (formatter_map.TryGetValue(typeof(T), out var formatter)) + return (IMessagePackFormatter)formatter; + + return StandardResolver.Instance.GetFormatter(); + } + + public class TypeRedirectingFormatter : IMessagePackFormatter + { + private readonly IMessagePackFormatter baseFormatter; + + public TypeRedirectingFormatter() + { + baseFormatter = StandardResolver.Instance.GetFormatter(); + } + + public void Serialize(ref MessagePackWriter writer, TActual value, MessagePackSerializerOptions options) => + baseFormatter.Serialize(ref writer, (TBase)(object)value, StandardResolver.Options); + + public TActual Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) => + (TActual)(object)baseFormatter.Deserialize(ref reader, StandardResolver.Options); + } + } +} From f95c6f0de5b484e1502ac06b2478069dabe9f275 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 17:42:13 +0900 Subject: [PATCH 267/366] Switch multiplayer back to messagepack --- osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index c38a648a6a..965674c2f2 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -39,7 +39,7 @@ namespace osu.Game.Online.Multiplayer { // Importantly, we are intentionally not using MessagePack here to correctly support derived class serialization. // More information on the limitations / reasoning can be found in osu-server-spectator's initialisation code. - connector = api.GetHubConnector(nameof(OnlineMultiplayerClient), endpoint, false); + connector = api.GetHubConnector(nameof(OnlineMultiplayerClient), endpoint); if (connector != null) { From 2b5a42e06325d0f1188be1bef1c0937cb569308e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 17:42:26 +0900 Subject: [PATCH 268/366] Add missing union specification for `MatchUserRequest` --- osu.Game/Online/Multiplayer/MatchUserRequest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Online/Multiplayer/MatchUserRequest.cs b/osu.Game/Online/Multiplayer/MatchUserRequest.cs index 15c3ad0776..8c6809e7f3 100644 --- a/osu.Game/Online/Multiplayer/MatchUserRequest.cs +++ b/osu.Game/Online/Multiplayer/MatchUserRequest.cs @@ -3,6 +3,7 @@ using System; using MessagePack; +using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; namespace osu.Game.Online.Multiplayer { @@ -11,6 +12,7 @@ namespace osu.Game.Online.Multiplayer /// [Serializable] [MessagePackObject] + [Union(0, typeof(ChangeTeamRequest))] // IMPORTANT: Add rules to SignalRUnionWorkaroundResolver for new derived types. public abstract class MatchUserRequest { } From bc025efce57932a0dd28ba0e21683bfa1b8dd85e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 17:42:44 +0900 Subject: [PATCH 269/366] Add commenting regarding workaround to avoid potential omission in the future --- osu.Game/Online/Multiplayer/MatchRoomState.cs | 6 +++--- osu.Game/Online/Multiplayer/MatchUserState.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MatchRoomState.cs b/osu.Game/Online/Multiplayer/MatchRoomState.cs index 5b662af100..edd34fb5a3 100644 --- a/osu.Game/Online/Multiplayer/MatchRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRoomState.cs @@ -15,9 +15,9 @@ namespace osu.Game.Online.Multiplayer /// [Serializable] [MessagePackObject] - [Union(0, typeof(TeamVersusRoomState))] - // TODO: this will need to be abstract or interface when/if we get messagepack working. for now it isn't as it breaks json serialisation. - public class MatchRoomState + [Union(0, typeof(TeamVersusRoomState))] // IMPORTANT: Add rules to SignalRUnionWorkaroundResolver for new derived types. + // TODO: abstract breaks json serialisation. attention will be required for iOS support (unless we get messagepack AOT working instead). + public abstract class MatchRoomState { } } diff --git a/osu.Game/Online/Multiplayer/MatchUserState.cs b/osu.Game/Online/Multiplayer/MatchUserState.cs index f457191bb5..69245deba0 100644 --- a/osu.Game/Online/Multiplayer/MatchUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchUserState.cs @@ -15,9 +15,9 @@ namespace osu.Game.Online.Multiplayer /// [Serializable] [MessagePackObject] - [Union(0, typeof(TeamVersusUserState))] - // TODO: this will need to be abstract or interface when/if we get messagepack working. for now it isn't as it breaks json serialisation. - public class MatchUserState + [Union(0, typeof(TeamVersusUserState))] // IMPORTANT: Add rules to SignalRUnionWorkaroundResolver for new derived types. + // TODO: abstract breaks json serialisation. attention will be required for iOS support (unless we get messagepack AOT working instead). + public abstract class MatchUserState { } } From 4d1582d721e0af061117f2ad49fded615be7f003 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 18:14:45 +0900 Subject: [PATCH 270/366] Play settings hide animation if visible when exiting `RoomSubScreen` --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 81fae558c8..ec56edaa4d 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -244,6 +244,7 @@ namespace osu.Game.Screens.OnlinePlay.Match if (Room.RoomID.Value == null) { // room has not been created yet; exit immediately. + settingsOverlay.Hide(); return base.OnBackButton(); } From 493f47787b5c9a2bc3366b6ea55f8dc8269f6079 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 18:18:42 +0900 Subject: [PATCH 271/366] Disable condition for the time being --- .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 833e6b24e0..61cb040830 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -79,8 +79,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer handleRoomLost(); }, true); - if (client.Room == null) - handleRoomLost(); + // if (client.Room == null) + // handleRoomLost(); } protected override Drawable CreateMainContent() => new GridContainer From 023f3fb70e263f6496066a0f399c978dae5e801b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 18:19:31 +0900 Subject: [PATCH 272/366] Use BackgroundScreen for multiplayer backgrounds --- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 3 + .../Screens/OnlinePlay/OnlinePlayScreen.cs | 61 ------------------- .../Screens/OnlinePlay/OnlinePlaySubScreen.cs | 9 ++- .../OnlinePlay/OnlinePlaySubScreenStack.cs | 14 +++++ 4 files changed, 25 insertions(+), 62 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 677b9c0782..7712e7d734 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -23,6 +23,7 @@ using osu.Game.Input; using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Rulesets; +using osu.Game.Screens.Backgrounds; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; @@ -36,6 +37,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public override string Title => "Lounge"; + protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); + protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); protected Container Buttons { get; } = new Container diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index e5962db608..c057c814ca 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -78,32 +78,16 @@ namespace osu.Game.Screens.OnlinePlay [BackgroundDependencyLoader] private void load() { - var backgroundColour = Color4Extensions.FromHex(@"3e3a44"); - InternalChild = waves = new MultiplayerWaveContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = backgroundColour, - }, new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new BeatmapBackgroundSprite - { - RelativeSizeAxes = Axes.Both - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.9f), Color4.Black.Opacity(0.6f)) - }, screenStack = new OnlinePlaySubScreenStack { RelativeSizeAxes = Axes.Both @@ -276,51 +260,6 @@ namespace osu.Game.Screens.OnlinePlay } } - private class BeatmapBackgroundSprite : OnlinePlayBackgroundSprite - { - protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BlurredBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; - - public class BlurredBackgroundSprite : UpdateableBeatmapBackgroundSprite - { - public BlurredBackgroundSprite(BeatmapSetCoverType type) - : base(type) - { - } - - protected override double LoadDelay => 200; - - protected override Drawable CreateDrawable(BeatmapInfo model) => - new BufferedLoader(base.CreateDrawable(model)); - } - - // This class is an unfortunate requirement due to `LongRunningLoad` requiring direct async loading. - // It means that if the web request fetching the beatmap background takes too long, it will suddenly appear. - internal class BufferedLoader : BufferedContainer - { - private readonly Drawable drawable; - - public BufferedLoader(Drawable drawable) - { - this.drawable = drawable; - - RelativeSizeAxes = Axes.Both; - BlurSigma = new Vector2(10); - FrameBufferScale = new Vector2(0.5f); - CacheDrawnFrameBuffer = true; - } - - [BackgroundDependencyLoader] - private void load() - { - LoadComponentAsync(drawable, d => - { - Add(d); - ForceRedraw(); - }); - } - } - } - ScreenStack IHasSubScreenStack.SubScreenStack => screenStack; } } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index e1bd889088..58531a4b1c 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -35,13 +35,16 @@ namespace osu.Game.Screens.OnlinePlay public override void OnEntering(IScreen last) { - this.FadeInFromZero(APPEAR_DURATION, Easing.OutQuint); + base.OnEntering(last); + this.FadeInFromZero(APPEAR_DURATION, Easing.OutQuint); this.MoveToX(X_SHIFT).MoveToX(0, X_MOVE_DURATION, Easing.OutQuint); } public override bool OnExiting(IScreen next) { + base.OnExiting(next); + this.FadeOut(DISAPPEAR_DURATION, Easing.OutQuint); this.MoveToX(X_SHIFT, X_MOVE_DURATION, Easing.OutQuint); @@ -50,12 +53,16 @@ namespace osu.Game.Screens.OnlinePlay public override void OnResuming(IScreen last) { + base.OnResuming(last); + this.Delay(RESUME_TRANSITION_DELAY).FadeIn(APPEAR_DURATION, Easing.OutQuint); this.MoveToX(0, X_MOVE_DURATION, Easing.OutQuint); } public override void OnSuspending(IScreen next) { + base.OnSuspending(next); + this.FadeOut(DISAPPEAR_DURATION, Easing.OutQuint); this.MoveToX(-X_SHIFT, X_MOVE_DURATION, Easing.OutQuint); } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs index 7f2a0980c1..69fa3b0916 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs @@ -1,12 +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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; +using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay { public class OnlinePlaySubScreenStack : OsuScreenStack { + public OnlinePlaySubScreenStack() + { + AddInternal(new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.9f), Color4.Black.Opacity(0.6f)) + }); + } + protected override void ScreenChanged(IScreen prev, IScreen next) { base.ScreenChanged(prev, next); From 4afc808ffcf32c1930f7a1bd256b62926b6c65e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 18:25:40 +0900 Subject: [PATCH 273/366] Remove horizontal transitions for now They look bad with the current toolbar implementation. We can probably add them back once the toolbar is moved to the lounge. --- osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index e1bd889088..49cc77a5d8 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -23,12 +23,6 @@ namespace osu.Game.Screens.OnlinePlay RelativeSizeAxes = Axes.Both; } - public const float X_SHIFT = 200; - - public const double X_MOVE_DURATION = 800; - - public const double RESUME_TRANSITION_DELAY = DISAPPEAR_DURATION / 2; - public const double APPEAR_DURATION = 800; public const double DISAPPEAR_DURATION = 500; @@ -36,28 +30,23 @@ namespace osu.Game.Screens.OnlinePlay public override void OnEntering(IScreen last) { this.FadeInFromZero(APPEAR_DURATION, Easing.OutQuint); - this.FadeInFromZero(APPEAR_DURATION, Easing.OutQuint); - this.MoveToX(X_SHIFT).MoveToX(0, X_MOVE_DURATION, Easing.OutQuint); } public override bool OnExiting(IScreen next) { this.FadeOut(DISAPPEAR_DURATION, Easing.OutQuint); - this.MoveToX(X_SHIFT, X_MOVE_DURATION, Easing.OutQuint); return false; } public override void OnResuming(IScreen last) { - this.Delay(RESUME_TRANSITION_DELAY).FadeIn(APPEAR_DURATION, Easing.OutQuint); - this.MoveToX(0, X_MOVE_DURATION, Easing.OutQuint); + this.FadeIn(APPEAR_DURATION, Easing.OutQuint); } public override void OnSuspending(IScreen next) { this.FadeOut(DISAPPEAR_DURATION, Easing.OutQuint); - this.MoveToX(-X_SHIFT, X_MOVE_DURATION, Easing.OutQuint); } public override string ToString() => Title; From 675e2e34baf1d6796e96b7911bac786352538853 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 19:02:05 +0900 Subject: [PATCH 274/366] Add padding between beatmap panel and edit button --- .../OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs index 56b87302c2..2e94e51385 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/BeatmapSelectionControl.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Screens; using osu.Game.Online.API; using osu.Game.Screens.OnlinePlay.Match.Components; +using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { @@ -35,6 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, + Spacing = new Vector2(5), Children = new Drawable[] { beatmapPanelContainer = new Container From be774980440e89cbbc8451ef215138bf1a3046da Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 19:02:31 +0900 Subject: [PATCH 275/366] Move chat to right column in multiplayer match screen --- .../Multiplayer/MultiplayerMatchSubScreen.cs | 106 ++++++++---------- 1 file changed, 47 insertions(+), 59 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 3f5837cbbe..6a41403aff 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -141,79 +141,67 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // Spacer null, // Main right column - new FillFlowContainer + new GridContainer { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new[] + RelativeSizeAxes = Axes.Both, + Content = new[] { - new FillFlowContainer + new Drawable[] { new OverlinedHeader("Beatmap") }, + new Drawable[] { new BeatmapSelectionControl { RelativeSizeAxes = Axes.X } }, + new[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + UserModsSection = new FillFlowContainer { - new OverlinedHeader("Beatmap"), - new BeatmapSelectionControl { RelativeSizeAxes = Axes.X } - } - }, - UserModsSection = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 10 }, - Children = new Drawable[] - { - new OverlinedHeader("Extra mods"), - new FillFlowContainer + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 10 }, + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] + new OverlinedHeader("Extra mods"), + new FillFlowContainer { - new UserModSelectButton + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Width = 90, - Text = "Select", - Action = ShowUserModSelect, - }, - new ModDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Current = UserMods, - Scale = new Vector2(0.8f), - }, - } + new UserModSelectButton + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 90, + Text = "Select", + Action = ShowUserModSelect, + }, + new ModDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = UserMods, + Scale = new Vector2(0.8f), + }, + } + }, } - } - } + }, + }, + new Drawable[] { new OverlinedHeader("Chat") { Margin = new MarginPadding { Vertical = 5 }, }, }, + new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(), } - } + }, } } } } }, - new Drawable[] - { - new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] { new OverlinedHeader("Chat") }, - new Drawable[] { new MatchChatDisplay { RelativeSizeAxes = Axes.Both } } - } - } - } }, }; From 16aecfe934c9d893e694af1429ad0cede7c2d679 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 19:02:54 +0900 Subject: [PATCH 276/366] Start free mod selection area hidden on screen display --- .../Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 1 + osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 6a41403aff..3a012787a4 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -155,6 +155,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Margin = new MarginPadding { Top = 10 }, + Alpha = 0, Children = new Drawable[] { new OverlinedHeader("Extra mods"), diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 27de781d5f..729ddbef8c 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -120,6 +120,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Alpha = 0, Margin = new MarginPadding { Bottom = 10 }, Children = new Drawable[] { From 8fce5911a951dbe1cbc6884e0f596e2e5d50763b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 19:08:46 +0900 Subject: [PATCH 277/366] Adjust spacing and padding of footer buttons --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 9 +++++++-- .../Multiplayer/Match/MultiplayerMatchFooter.cs | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index ec56edaa4d..10df7cbadc 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -195,14 +195,19 @@ namespace osu.Game.Screens.OnlinePlay.Match new Container { RelativeSizeAxes = Axes.Both, - Children = new[] + Children = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, Colour = Color4Extensions.FromHex(@"28242d") // Temporary. }, - CreateFooter() + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(5), + Child = CreateFooter() + }, } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs index 9e8d51e64e..036e37ddfd 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { new Dimension(), new Dimension(maxSize: spectate_button_width), - new Dimension(GridSizeMode.Absolute, 10), + new Dimension(GridSizeMode.Absolute, 5), new Dimension(maxSize: ready_button_width), new Dimension() } From 44e157447c7d005079e2ede801ee6ad6fe5a802c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Aug 2021 19:10:54 +0900 Subject: [PATCH 278/366] Initial rework of backgrounds --- .../Components/PlaylistItemBackground.cs | 44 ++++++++++ .../Components/RoomBackgroundScreen.cs | 82 +++++++++++++++++++ .../OnlinePlay/Lounge/LoungeSubScreen.cs | 6 +- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 6 -- 4 files changed, 130 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs create mode 100644 osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs new file mode 100644 index 0000000000..90ad6e0f6e --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.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 osu.Framework.Allocation; +using osu.Framework.Graphics.Textures; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Backgrounds; +using osu.Game.Online.Rooms; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + public class PlaylistItemBackground : Background + { + public readonly BeatmapInfo? BeatmapInfo; + + public PlaylistItemBackground(PlaylistItem? playlistItem) + { + BeatmapInfo = playlistItem?.Beatmap.Value; + } + + [BackgroundDependencyLoader] + private void load(BeatmapManager beatmaps, LargeTextureStore textures) + { + Texture? texture = null; + + // prefer online cover where available. + if (BeatmapInfo?.BeatmapSet?.OnlineInfo?.Covers.Cover != null) + texture = textures.Get(BeatmapInfo.BeatmapSet.OnlineInfo.Covers.Cover); + + Sprite.Texture = texture ?? beatmaps.DefaultBeatmap.Background; + } + + public override bool Equals(Background? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return other.GetType() == GetType() + && ((PlaylistItemBackground)other).BeatmapInfo == BeatmapInfo; + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs new file mode 100644 index 0000000000..c6e467233e --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs @@ -0,0 +1,82 @@ +// 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.Linq; +using System.Threading; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Online.Rooms; +using osuTK; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + public class RoomBackgroundScreen : BackgroundScreen + { + private CancellationTokenSource? cancellationSource; + private PlaylistItemBackground? background; + + private readonly BindableList playlist = new BindableList(); + + public RoomBackgroundScreen() + { + playlist.BindCollectionChanged((_, __) => updateBackground()); + } + + private Room? room; + + public Room? Room + { + get => room; + set + { + if (room == value) + return; + + if (room != null) + playlist.UnbindFrom(room.Playlist); + + room = value; + + if (room != null) + playlist.BindTo(room.Playlist); + else + playlist.Clear(); + } + } + + private void updateBackground() + { + Schedule(() => + { + var playlistItem = playlist.FirstOrDefault(); + var beatmap = playlistItem?.Beatmap.Value; + + if (background?.BeatmapInfo?.BeatmapSet?.OnlineInfo?.Covers?.Cover == beatmap?.BeatmapSet?.OnlineInfo?.Covers?.Cover) + return; + + cancellationSource?.Cancel(); + LoadComponentAsync(new PlaylistItemBackground(playlistItem), switchBackground, (cancellationSource = new CancellationTokenSource()).Token); + }); + } + + private void switchBackground(PlaylistItemBackground newBackground) + { + float newDepth = 0; + + if (background != null) + { + newDepth = background.Depth + 1; + background.FinishTransforms(); + background.FadeOut(250); + background.Expire(); + } + + newBackground.Depth = newDepth; + newBackground.BlurTo(new Vector2(10)); + + AddInternal(background = newBackground); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 7712e7d734..c5d9616ee3 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -23,7 +23,6 @@ using osu.Game.Input; using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Rulesets; -using osu.Game.Screens.Backgrounds; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; @@ -37,7 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public override string Title => "Lounge"; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); + protected override BackgroundScreen CreateBackground() => new RoomBackgroundScreen(); protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); @@ -180,6 +179,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge var drawable = roomsContainer.Rooms.FirstOrDefault(r => r.Room == val.NewValue); if (drawable != null) scrollContainer.ScrollIntoView(drawable); + + ApplyToBackground(b => ((RoomBackgroundScreen)b).Room = val.NewValue); }); } @@ -246,6 +247,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge public override void OnEntering(IScreen last) { base.OnEntering(last); + onReturning(); } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index c057c814ca..576598cb1e 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -6,13 +6,9 @@ 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.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Screens; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Online.Rooms; @@ -21,8 +17,6 @@ using osu.Game.Screens.Menu; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Users; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay { From a65cd36a5f25296b5348f483208ad37458437841 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 19:19:46 +0900 Subject: [PATCH 279/366] Move some constants to `const`s --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 17a26eb7ee..297a16dd1d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -73,17 +73,19 @@ namespace osu.Game.Screens.Select ruleset.BindValueChanged(_ => updateDisplay()); } + private const double animation_duration = 800; + protected override void PopIn() { - this.MoveToX(0, 800, Easing.OutQuint); - this.RotateTo(0, 800, Easing.OutQuint); + this.MoveToX(0, animation_duration, Easing.OutQuint); + this.RotateTo(0, animation_duration, Easing.OutQuint); this.FadeIn(transition_duration); } protected override void PopOut() { - this.MoveToX(-100, 800, Easing.In); - this.RotateTo(10, 800, Easing.In); + this.MoveToX(-100, animation_duration, Easing.In); + this.RotateTo(10, animation_duration, Easing.In); this.FadeOut(transition_duration * 2, Easing.In); } @@ -191,6 +193,8 @@ namespace osu.Game.Screens.Select titleBinding = localisation.GetLocalisedString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); artistBinding = localisation.GetLocalisedString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist)); + const float top_height = 0.7f; + Children = new Drawable[] { difficultyColourBar = new Container @@ -202,15 +206,15 @@ namespace osu.Game.Screens.Select new Box { RelativeSizeAxes = Axes.Both, - Width = 0.7f, + Width = top_height, }, new Box { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, Alpha = 0.5f, - X = 0.7f, - Width = 1 - 0.7f, + X = top_height, + Width = 1 - top_height, } } }, From a6b7ca1a4c44a5f303abcf3c4c1cc59facdee905 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Aug 2021 19:55:10 +0900 Subject: [PATCH 280/366] Ensure all request failures are correctly handled during login --- osu.Game/Online/API/APIAccess.cs | 4 ++-- osu.Game/Online/API/APIRequest.cs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index f7a3f4602f..96d62e95a2 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -309,7 +309,7 @@ namespace osu.Game.Online.API if (IsLoggedIn) state.Value = APIState.Online; failureCount = 0; - return true; + return req.CompletionState == APIRequestCompletionState.Completed; } catch (HttpRequestException re) { @@ -381,7 +381,7 @@ namespace osu.Game.Online.API } } - public bool IsLoggedIn => localUser.Value.Id > 1; + public bool IsLoggedIn => localUser.Value.Id > 1; // TODO: should this also be true if attempting to connect? public void Queue(APIRequest request) { diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index e117293ce6..cf17ed4b5d 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -84,7 +84,7 @@ namespace osu.Game.Online.API /// The state of this request, from an outside perspective. /// This is used to ensure correct notification events are fired. /// - private APIRequestCompletionState completionState; + public APIRequestCompletionState CompletionState { get; private set; } public void Perform(IAPIProvider api) { @@ -127,10 +127,10 @@ namespace osu.Game.Online.API { lock (completionStateLock) { - if (completionState != APIRequestCompletionState.Waiting) + if (CompletionState != APIRequestCompletionState.Waiting) return; - completionState = APIRequestCompletionState.Completed; + CompletionState = APIRequestCompletionState.Completed; } if (API == null) @@ -143,10 +143,10 @@ namespace osu.Game.Online.API { lock (completionStateLock) { - if (completionState != APIRequestCompletionState.Waiting) + if (CompletionState != APIRequestCompletionState.Waiting) return; - completionState = APIRequestCompletionState.Failed; + CompletionState = APIRequestCompletionState.Failed; } if (API == null) @@ -161,7 +161,7 @@ namespace osu.Game.Online.API { lock (completionStateLock) { - if (completionState != APIRequestCompletionState.Waiting) + if (CompletionState != APIRequestCompletionState.Waiting) return; WebRequest?.Abort(); @@ -200,7 +200,7 @@ namespace osu.Game.Online.API get { lock (completionStateLock) - return completionState == APIRequestCompletionState.Failed; + return CompletionState == APIRequestCompletionState.Failed; } } From bf7f0a5d30fe779c308ec0299ee7a779a4aadbd8 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 19 Aug 2021 19:02:04 +0200 Subject: [PATCH 281/366] Remove double whitespace --- osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index c0460a4536..ad045c4b17 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -141,7 +141,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { new OsuSpriteText { - Text = BeatmapsetsStrings.ShowDetailsDownloadDefault, + Text = BeatmapsetsStrings.ShowDetailsDownloadDefault, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, new OsuSpriteText From 5f1948d040b054a4ec68e964166b2c61aedb2d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 19 Aug 2021 22:31:11 +0200 Subject: [PATCH 282/366] Add failing test case --- .../Visual/Settings/TestSceneSettingsItem.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs index df59b9284b..d9cce69ee3 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs @@ -76,5 +76,23 @@ namespace osu.Game.Tests.Visual.Settings AddStep("restore default", () => sliderBar.Current.SetDefault()); AddUntilStep("restore button hidden", () => restoreDefaultValueButton.Alpha == 0); } + + [Test] + public void TestWarningTextVisibility() + { + SettingsNumberBox numberBox = null; + + AddStep("create settings item", () => Child = numberBox = new SettingsNumberBox()); + AddAssert("warning text not created", () => !numberBox.ChildrenOfType().Any()); + + AddStep("set warning text", () => numberBox.WarningText = "this is a warning!"); + AddAssert("warning text created", () => numberBox.ChildrenOfType().Single().Alpha == 1); + + AddStep("unset warning text", () => numberBox.WarningText = default); + AddAssert("warning text hidden", () => numberBox.ChildrenOfType().Single().Alpha == 0); + + AddStep("set warning text again", () => numberBox.WarningText = "another warning!"); + AddAssert("warning text shown again", () => numberBox.ChildrenOfType().Single().Alpha == 1); + } } } From 143b8df1b2018d1b5efb169581d199064780cdf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 19 Aug 2021 22:33:05 +0200 Subject: [PATCH 283/366] Fix backwards warning text presence check --- 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 6621caef4e..5282217013 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.Settings { set { - bool hasValue = string.IsNullOrWhiteSpace(value.ToString()); + bool hasValue = !string.IsNullOrWhiteSpace(value.ToString()); if (warningText == null) { @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.Settings FlowContent.Add(warningText = new SettingsNoticeText(colours) { Margin = new MarginPadding { Bottom = 5 } }); } - warningText.Alpha = hasValue ? 0 : 1; + warningText.Alpha = hasValue ? 1 : 0; warningText.Text = value.ToString(); // TODO: Remove ToString() call after TextFlowContainer supports localisation (see https://github.com/ppy/osu-framework/issues/4636). } } From 4d9c415e730ecc488d9b4f7a9758fc208ff4968c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 20 Aug 2021 04:37:35 +0300 Subject: [PATCH 284/366] Remove unnecessary queue in beatmap difficulty cache tests --- .../TestSceneBeatmapDifficultyCache.cs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index b6ba5b748a..6856e466cf 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -32,7 +32,6 @@ namespace osu.Game.Tests.Beatmaps private TestBeatmapDifficultyCache difficultyCache; private IBindable starDifficultyBindable; - private Queue> starDifficultyChangesQueue; [BackgroundDependencyLoader] private void load(OsuGameBase osu) @@ -49,14 +48,10 @@ namespace osu.Game.Tests.Beatmaps Child = difficultyCache = new TestBeatmapDifficultyCache(); - starDifficultyChangesQueue = new Queue>(); starDifficultyBindable = difficultyCache.GetBindableDifficulty(importedSet.Beatmaps.First()); - starDifficultyBindable.BindValueChanged(starDifficultyChangesQueue.Enqueue); }); - AddAssert($"star difficulty -> {BASE_STARS}", () => - starDifficultyChangesQueue.Dequeue().NewValue?.Stars == BASE_STARS && - starDifficultyChangesQueue.Count == 0); + AddAssert($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value?.Stars == BASE_STARS); } [Test] @@ -65,19 +60,13 @@ namespace osu.Game.Tests.Beatmaps OsuModDoubleTime dt = null; AddStep("change selected mod to DT", () => SelectedMods.Value = new[] { dt = new OsuModDoubleTime { SpeedChange = { Value = 1.5 } } }); - AddAssert($"star difficulty -> {BASE_STARS + 1.5}", () => - starDifficultyChangesQueue.Dequeue().NewValue?.Stars == BASE_STARS + 1.5 && - starDifficultyChangesQueue.Count == 0); + AddAssert($"star difficulty -> {BASE_STARS + 1.5}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.5); AddStep("change DT speed to 1.25", () => dt.SpeedChange.Value = 1.25); - AddAssert($"star difficulty -> {BASE_STARS + 1.25}", () => - starDifficultyChangesQueue.Dequeue().NewValue?.Stars == BASE_STARS + 1.25 && - starDifficultyChangesQueue.Count == 0); + AddAssert($"star difficulty -> {BASE_STARS + 1.25}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.25); AddStep("change selected mod to NC", () => SelectedMods.Value = new[] { new OsuModNightcore { SpeedChange = { Value = 1.75 } } }); - AddAssert($"star difficulty -> {BASE_STARS + 1.75}", () => - starDifficultyChangesQueue.Dequeue().NewValue?.Stars == BASE_STARS + 1.75 && - starDifficultyChangesQueue.Count == 0); + AddAssert($"star difficulty -> {BASE_STARS + 1.75}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.75); } [Test] From d98742522b339b4c92a49406bd9df7fe052b4225 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 20 Aug 2021 04:40:03 +0300 Subject: [PATCH 285/366] Remove unused using directive --- osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index 6856e466cf..bdf4fb8d0c 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; From 73b40a6244abacb48bbf34f537f7ac11343c0e84 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 20 Aug 2021 05:29:30 +0300 Subject: [PATCH 286/366] Switch to until step to account for asynchronous operations --- .../Beatmaps/TestSceneBeatmapDifficultyCache.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index bdf4fb8d0c..da457c9e8f 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Beatmaps starDifficultyBindable = difficultyCache.GetBindableDifficulty(importedSet.Beatmaps.First()); }); - AddAssert($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value?.Stars == BASE_STARS); + AddUntilStep($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value?.Stars == BASE_STARS); } [Test] @@ -59,13 +59,13 @@ namespace osu.Game.Tests.Beatmaps OsuModDoubleTime dt = null; AddStep("change selected mod to DT", () => SelectedMods.Value = new[] { dt = new OsuModDoubleTime { SpeedChange = { Value = 1.5 } } }); - AddAssert($"star difficulty -> {BASE_STARS + 1.5}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.5); + AddUntilStep($"star difficulty -> {BASE_STARS + 1.5}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.5); AddStep("change DT speed to 1.25", () => dt.SpeedChange.Value = 1.25); - AddAssert($"star difficulty -> {BASE_STARS + 1.25}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.25); + AddUntilStep($"star difficulty -> {BASE_STARS + 1.25}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.25); AddStep("change selected mod to NC", () => SelectedMods.Value = new[] { new OsuModNightcore { SpeedChange = { Value = 1.75 } } }); - AddAssert($"star difficulty -> {BASE_STARS + 1.75}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.75); + AddUntilStep($"star difficulty -> {BASE_STARS + 1.75}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.75); } [Test] From 1e6119da0b2cab68368f370dad96591478cf7a4a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 20 Aug 2021 05:36:39 +0300 Subject: [PATCH 287/366] Update code inspection settings to hide "merge into pattern" again --- osu.sln.DotSettings | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index d884ea31c5..e42b30e944 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -105,8 +105,9 @@ HINT HINT WARNING + DO_NOT_SHOW + DO_NOT_SHOW WARNING - DO_NOT_SHOW WARNING WARNING WARNING From 2825e15fd4af729be343f3b029eb13be7e0f8f72 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 11:54:37 +0900 Subject: [PATCH 288/366] 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 24d07b4588..f74b5d410b 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 928620b32e..e4838dc95a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 77f9052e85..5338ad5deb 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 1e02d61b852762425553b7873ccf01eb15cb9060 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 19 Aug 2021 20:06:25 -0700 Subject: [PATCH 289/366] Fix nub glow color not having 0 alpha when being set --- osu.Game/Graphics/UserInterface/Nub.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index cbf3e6b3aa..80d83e17c1 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -149,7 +149,7 @@ namespace osu.Game.Graphics.UserInterface glowColour = value; var effect = EdgeEffect; - effect.Colour = value; + effect.Colour = value.Opacity(0); EdgeEffect = effect; } } From da8eba999657826a8dd8a611f5c62576749f6b44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 12:11:41 +0900 Subject: [PATCH 290/366] Return early to avoid updating state and failure count in fail cases --- osu.Game/Online/API/APIAccess.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 96d62e95a2..af14cdc7b3 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -305,11 +305,13 @@ namespace osu.Game.Online.API { req.Perform(this); + if (req.CompletionState != APIRequestCompletionState.Completed) + return false; + // we could still be in initialisation, at which point we don't want to say we're Online yet. if (IsLoggedIn) state.Value = APIState.Online; - failureCount = 0; - return req.CompletionState == APIRequestCompletionState.Completed; + return true; } catch (HttpRequestException re) { From 284c871e39f4272d036547eceae8257bad7871c5 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 19 Aug 2021 20:33:19 -0700 Subject: [PATCH 291/366] Fix glow color potentially being set incorrectly when glowing Co-authored-by: Salman Ahmed --- osu.Game/Graphics/UserInterface/Nub.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 80d83e17c1..664f32b083 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -149,7 +149,7 @@ namespace osu.Game.Graphics.UserInterface glowColour = value; var effect = EdgeEffect; - effect.Colour = value.Opacity(0); + effect.Colour = Glowing ? value : value.Opacity(0); EdgeEffect = effect; } } From 19cc4a14a36ce0ccb7d5f418e2a09c2a361887c5 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 20 Aug 2021 09:22:15 +0200 Subject: [PATCH 292/366] Localise top score mods statistics --- .../Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 582528b675..23069eccdf 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -235,7 +235,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } private ModsInfoColumn(FillFlowContainer modsContainer) - : base("mods", modsContainer) + : base(BeatmapsetsStrings.ShowScoreboardHeadersMods, modsContainer) { this.modsContainer = modsContainer; } From 0a1c9a6c05bd33adf8f73f1d9f3c39710ed65bc6 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 20 Aug 2021 09:26:38 +0200 Subject: [PATCH 293/366] Move DownloadButtonStrings -> CommonStrings --- osu.Game/Localisation/CommonStrings.cs | 12 +++++++++- .../Localisation/DownloadButtonStrings.cs | 24 ------------------- .../Buttons/HeaderDownloadButton.cs | 5 ++-- 3 files changed, 13 insertions(+), 28 deletions(-) delete mode 100644 osu.Game/Localisation/DownloadButtonStrings.cs diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index bf488d2590..b4381fc442 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -29,6 +29,16 @@ namespace osu.Game.Localisation /// public static LocalisableString Height => new TranslatableString(getKey(@"height"), @"Height"); + /// + /// "Downloading..." + /// + public static LocalisableString Downloading => new TranslatableString(getKey(@"downloading"), @"Downloading..."); + + /// + /// "Importing..." + /// + public static LocalisableString Importing => new TranslatableString(getKey(@"importing"), @"Importing..."); + private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} diff --git a/osu.Game/Localisation/DownloadButtonStrings.cs b/osu.Game/Localisation/DownloadButtonStrings.cs deleted file mode 100644 index 736f309624..0000000000 --- a/osu.Game/Localisation/DownloadButtonStrings.cs +++ /dev/null @@ -1,24 +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.Localisation; - -namespace osu.Game.Localisation -{ - public static class DownloadButtonStrings - { - private const string prefix = @"osu.Game.Resources.Localisation.DownloadButton"; - - /// - /// "Downloading..." - /// - public static LocalisableString Downloading => new TranslatableString(getKey(@"downloading"), @"Downloading..."); - - /// - /// "Importing..." - /// - public static LocalisableString Importing => new TranslatableString(getKey(@"importing"), @"Importing..."); - - private static string getKey(string key) => $@"{prefix}:{key}"; - } -} diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index ad045c4b17..e7a55079ec 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -19,7 +19,6 @@ using osu.Game.Resources.Localisation.Web; using osu.Game.Users; using osuTK; using osuTK.Graphics; -using osu.Game.Localisation; namespace osu.Game.Overlays.BeatmapSet.Buttons { @@ -115,7 +114,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { new OsuSpriteText { - Text = DownloadButtonStrings.Downloading, + Text = Localisation.CommonStrings.Downloading, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, }; @@ -126,7 +125,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { new OsuSpriteText { - Text = DownloadButtonStrings.Importing, + Text = Localisation.CommonStrings.Importing, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, }; From 9b4c806855b2e4ce7371983a83f13e6c7f8d65d0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 20 Aug 2021 09:47:23 +0200 Subject: [PATCH 294/366] Apply review suggestions. --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 80dc185bb5..2dcb2f1777 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -81,10 +81,26 @@ namespace osu.Game.Overlays.BeatmapSet Direction = FillDirection.Horizontal, Children = new[] { - length = new Statistic(BeatmapStatisticsIconType.Length, BeatmapsetsStrings.ShowStatsTotalLength(string.Empty)) { Width = 0.25f }, - bpm = new Statistic(BeatmapStatisticsIconType.Bpm, BeatmapsetsStrings.ShowStatsBpm) { Width = 0.25f }, - circleCount = new Statistic(BeatmapStatisticsIconType.Circles, BeatmapsetsStrings.ShowStatsCountCircles) { Width = 0.25f }, - sliderCount = new Statistic(BeatmapStatisticsIconType.Sliders, BeatmapsetsStrings.ShowStatsCountSliders) { Width = 0.25f }, + length = new Statistic(BeatmapStatisticsIconType.Length) + { + Width = 0.25f, + TooltipText = default, + }, + bpm = new Statistic(BeatmapStatisticsIconType.Bpm) + { + Width = 0.25f, + TooltipText = BeatmapsetsStrings.ShowStatsBpm + }, + circleCount = new Statistic(BeatmapStatisticsIconType.Circles) + { + Width = 0.25f, + TooltipText = BeatmapsetsStrings.ShowStatsCountCircles + }, + sliderCount = new Statistic(BeatmapStatisticsIconType.Sliders) + { + Width = 0.25f, + TooltipText = BeatmapsetsStrings.ShowStatsCountSliders + }, }, }; } @@ -107,9 +123,8 @@ namespace osu.Game.Overlays.BeatmapSet set => this.value.Text = value; } - public Statistic(BeatmapStatisticsIconType icon, LocalisableString name) + public Statistic(BeatmapStatisticsIconType icon) { - TooltipText = name; RelativeSizeAxes = Axes.X; Height = 24f; From cff7b1e98f495b11c34d3d92850c7edfa9cd4e1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 16:50:27 +0900 Subject: [PATCH 295/366] Ensure the correct fade level is applied over all state changes --- osu.Game/Overlays/Settings/SettingsSection.cs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 8d98ae484f..5c38dee356 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -102,28 +102,20 @@ namespace osu.Game.Overlays.Settings }); selectedSection = settingsPanel.CurrentSection.GetBoundCopy(); - selectedSection.BindValueChanged(selected => - { - if (selected.NewValue == this) - content.FadeIn(500, Easing.OutQuint); - else - content.FadeTo(0.25f, 500, Easing.OutQuint); - }, true); + selectedSection.BindValueChanged(_ => updateContentFade(), true); } private bool isCurrentSection => selectedSection.Value == this; protected override bool OnHover(HoverEvent e) { - if (!isCurrentSection) - content.FadeTo(0.6f, 500, Easing.OutQuint); + updateContentFade(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - if (!isCurrentSection) - content.FadeTo(0.25f, 500, Easing.OutQuint); + updateContentFade(); base.OnHoverLost(e); } @@ -135,9 +127,19 @@ namespace osu.Game.Overlays.Settings return base.OnClick(e); } - protected override bool ShouldBeConsideredForInput(Drawable child) + protected override bool ShouldBeConsideredForInput(Drawable child) => + // only the current section should accept input. + // this provides the behaviour of the first click scrolling the target section to the centre of the screen. + isCurrentSection; + + private void updateContentFade() { - return isCurrentSection; + float targetFade = 1; + + if (!isCurrentSection) + targetFade = IsHovered ? 0.6f : 0.25f; + + content.FadeTo(targetFade, 500, Easing.OutQuint); } } } From c7266c74a09bcfdcdf94d95049f224d03a034397 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:00:20 +0900 Subject: [PATCH 296/366] Always prefer clicked section when present --- .../Graphics/Containers/SectionsContainer.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index e11d1e1300..4b368b98ad 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics.Containers { public Bindable SelectedSection { get; } = new Bindable(); - private Drawable lastClickedSection; + private T lastClickedSection; public Drawable ExpandableHeader { @@ -145,10 +145,12 @@ namespace osu.Game.Graphics.Containers footerHeight = null; } - public void ScrollTo(Drawable section) + public void ScrollTo(Drawable target) { - lastClickedSection = section; - scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(section) - scrollContainer.DisplayableContent * scroll_y_centre - (FixedHeader?.BoundingBox.Height ?? 0)); + if (target is T section) + lastClickedSection = section; + + scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(target) - scrollContainer.DisplayableContent * scroll_y_centre - (FixedHeader?.BoundingBox.Height ?? 0)); } public void ScrollToTop() => scrollContainer.ScrollTo(0); @@ -236,10 +238,12 @@ namespace osu.Game.Graphics.Containers var presentChildren = Children.Where(c => c.IsPresent); - if (Precision.AlmostBigger(0, scrollContainer.Current)) - SelectedSection.Value = lastClickedSection as T ?? presentChildren.FirstOrDefault(); + if (lastClickedSection != null) + SelectedSection.Value = lastClickedSection; + else if (Precision.AlmostBigger(0, scrollContainer.Current)) + SelectedSection.Value = presentChildren.FirstOrDefault(); else if (Precision.AlmostBigger(scrollContainer.Current, scrollContainer.ScrollableExtent)) - SelectedSection.Value = lastClickedSection as T ?? presentChildren.LastOrDefault(); + SelectedSection.Value = presentChildren.LastOrDefault(); else { SelectedSection.Value = presentChildren From 8524937c82c6bc504de2528748d8667e005e563f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 17:02:55 +0900 Subject: [PATCH 297/366] Move screenstack up a level --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 576598cb1e..2e1d353d47 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -77,17 +77,7 @@ namespace osu.Game.Screens.OnlinePlay RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - screenStack = new OnlinePlaySubScreenStack - { - RelativeSizeAxes = Axes.Both - } - } - }, + screenStack = new OnlinePlaySubScreenStack { RelativeSizeAxes = Axes.Both }, new Header(ScreenTitle, screenStack), RoomManager, ongoingOperationTracker From 3d96da84e6c3362fb6252cd086ec870050f72c1d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 17:05:46 +0900 Subject: [PATCH 298/366] Set a default background --- .../Screens/OnlinePlay/Components/RoomBackgroundScreen.cs | 8 ++++++++ osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs index c6e467233e..efcfa35e19 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.Rooms; @@ -20,10 +21,17 @@ namespace osu.Game.Screens.OnlinePlay.Components private readonly BindableList playlist = new BindableList(); public RoomBackgroundScreen() + : base(false) { playlist.BindCollectionChanged((_, __) => updateBackground()); } + [BackgroundDependencyLoader] + private void load() + { + switchBackground(new PlaylistItemBackground(null)); + } + private Room? room; public Room? Room diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 2e1d353d47..76815172e5 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Graphics.Containers; From 139ff2d6e2a5a242ac2be92ba8737e81132d4f5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:40:03 +0900 Subject: [PATCH 299/366] Only fade header in when hovering a section Feels less like the controls are interactive when hovering this way. --- osu.Game/Overlays/Settings/SettingsSection.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 5c38dee356..6f167bf059 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings private IBindable selectedSection; - private Container content; + private OsuSpriteText header; public abstract Drawable CreateIcon(); public abstract LocalisableString Header { get; } @@ -70,11 +70,12 @@ namespace osu.Game.Overlays.Settings { new Box { + Name = "separator", Colour = new Color4(0, 0, 0, 255), RelativeSizeAxes = Axes.X, Height = border_size, }, - content = new Container + new Container { Padding = new MarginPadding { @@ -85,7 +86,7 @@ namespace osu.Game.Overlays.Settings AutoSizeAxes = Axes.Y, Children = new Drawable[] { - new OsuSpriteText + header = new OsuSpriteText { Font = OsuFont.GetFont(size: header_size), Text = Header, @@ -134,12 +135,17 @@ namespace osu.Game.Overlays.Settings private void updateContentFade() { - float targetFade = 1; + float contentFade = 1; + float headerFade = 1; if (!isCurrentSection) - targetFade = IsHovered ? 0.6f : 0.25f; + { + contentFade = 0.25f; + headerFade = IsHovered ? 0.5f : 0.25f; + } - content.FadeTo(targetFade, 500, Easing.OutQuint); + header.FadeTo(headerFade, 500, Easing.OutQuint); + FlowContent.FadeTo(contentFade, 500, Easing.OutQuint); } } } From 2d19f37dc6100a605b725e8d1eeb938109c43e06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:40:41 +0900 Subject: [PATCH 300/366] Add missing `new` method in `UserTrackingScrollContainer` for scrolling into view --- osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs index 17506ce0f5..0561051e35 100644 --- a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs +++ b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs @@ -42,6 +42,12 @@ namespace osu.Game.Graphics.Containers base.OnUserScroll(value, animated, distanceDecay); } + public new void ScrollIntoView(Drawable target, bool animated = true) + { + UserScrolling = false; + base.ScrollIntoView(target, animated); + } + public new void ScrollTo(float value, bool animated = true, double? distanceDecay = null) { UserScrolling = false; From 03e6ca5ba930830960bb5541f7b7be6fb2dc0f9a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:40:56 +0900 Subject: [PATCH 301/366] Adjust scroll behaviour to feel better --- .../Graphics/Containers/SectionsContainer.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 4b368b98ad..d0aa885f3e 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -112,7 +112,7 @@ namespace osu.Game.Graphics.Containers /// /// The percentage of the container to consider the centre-point for deciding the active section (and scrolling to a requested section). /// - private const float scroll_y_centre = 0.2f; + private const float scroll_y_centre = 0.1f; public SectionsContainer() { @@ -147,10 +147,22 @@ namespace osu.Game.Graphics.Containers public void ScrollTo(Drawable target) { + lastKnownScroll = null; + + float fixedHeaderSize = FixedHeader?.BoundingBox.Height ?? 0; + + // implementation similar to ScrollIntoView but a bit more nuanced. + float top = scrollContainer.GetChildPosInContent(target); + + var bottomScrollExtent = scrollContainer.ScrollableExtent - fixedHeaderSize; + + if (top > bottomScrollExtent) + scrollContainer.ScrollToEnd(); + else + scrollContainer.ScrollTo(top - fixedHeaderSize - scrollContainer.DisplayableContent * scroll_y_centre); + if (target is T section) lastClickedSection = section; - - scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(target) - scrollContainer.DisplayableContent * scroll_y_centre - (FixedHeader?.BoundingBox.Height ?? 0)); } public void ScrollToTop() => scrollContainer.ScrollTo(0); From 258ba4674cf210b66e9ca29405b4764c5989d04e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 17:50:49 +0900 Subject: [PATCH 302/366] Fix background overflows --- osu.Game/Screens/BackgroundScreen.cs | 18 +++++++-------- osu.Game/Screens/BackgroundScreenStack.cs | 4 +++- .../Components/RoomBackgroundScreen.cs | 22 +++++++++++++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index a6fb94b151..a706934cce 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -11,6 +11,9 @@ namespace osu.Game.Screens { public abstract class BackgroundScreen : Screen, IEquatable { + protected const float TRANSITION_LENGTH = 500; + private const float x_movement_amount = 50; + private readonly bool animateOnEnter; public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; @@ -27,9 +30,6 @@ namespace osu.Game.Screens return other?.GetType() == GetType(); } - private const float transition_length = 500; - private const float x_movement_amount = 50; - protected override bool OnKeyDown(KeyDownEvent e) { // we don't want to handle escape key. @@ -55,8 +55,8 @@ namespace osu.Game.Screens this.FadeOut(); this.MoveToX(x_movement_amount); - this.FadeIn(transition_length, Easing.InOutQuart); - this.MoveToX(0, transition_length, Easing.InOutQuart); + this.FadeIn(TRANSITION_LENGTH, Easing.InOutQuart); + this.MoveToX(0, TRANSITION_LENGTH, Easing.InOutQuart); } base.OnEntering(last); @@ -64,7 +64,7 @@ namespace osu.Game.Screens public override void OnSuspending(IScreen next) { - this.MoveToX(-x_movement_amount, transition_length, Easing.InOutQuart); + this.MoveToX(-x_movement_amount, TRANSITION_LENGTH, Easing.InOutQuart); base.OnSuspending(next); } @@ -72,8 +72,8 @@ namespace osu.Game.Screens { if (IsLoaded) { - this.FadeOut(transition_length, Easing.OutExpo); - this.MoveToX(x_movement_amount, transition_length, Easing.OutExpo); + this.FadeOut(TRANSITION_LENGTH, Easing.OutExpo); + this.MoveToX(x_movement_amount, TRANSITION_LENGTH, Easing.OutExpo); } return base.OnExiting(next); @@ -82,7 +82,7 @@ namespace osu.Game.Screens public override void OnResuming(IScreen last) { if (IsLoaded) - this.MoveToX(0, transition_length, Easing.OutExpo); + this.MoveToX(0, TRANSITION_LENGTH, Easing.OutExpo); base.OnResuming(last); } } diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs index 9c0c5da0fb..17894d2474 100644 --- a/osu.Game/Screens/BackgroundScreenStack.cs +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -10,10 +10,12 @@ namespace osu.Game.Screens { public class BackgroundScreenStack : ScreenStack { + public const float BACKGROUND_SCALE = 1.06f; + public BackgroundScreenStack() : base(false) { - Scale = new Vector2(1.06f); + Scale = new Vector2(BACKGROUND_SCALE); RelativeSizeAxes = Axes.Both; Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs index efcfa35e19..393cf49bb7 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs @@ -8,6 +8,7 @@ using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Screens; using osu.Game.Online.Rooms; using osuTK; @@ -86,5 +87,26 @@ namespace osu.Game.Screens.OnlinePlay.Components AddInternal(background = newBackground); } + + protected override void Update() + { + base.Update(); + + // This is a static screen, so override the scale set in base.Update(), but also the scale set by the screen stack. + Scale = new Vector2(1f / BackgroundScreenStack.BACKGROUND_SCALE); + } + + public override void OnSuspending(IScreen next) + { + base.OnSuspending(next); + this.MoveToX(0, TRANSITION_LENGTH); + } + + public override bool OnExiting(IScreen next) + { + var result = base.OnExiting(next); + this.MoveToX(0); + return result; + } } } From 591ba8cb099a0ab4d9488fea7877ea4304c6179e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 17:56:35 +0900 Subject: [PATCH 303/366] Ensure the final scroll target is used when checking for whether too far down --- osu.Game/Graphics/Containers/SectionsContainer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index d0aa885f3e..76492cab55 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -154,12 +154,13 @@ namespace osu.Game.Graphics.Containers // implementation similar to ScrollIntoView but a bit more nuanced. float top = scrollContainer.GetChildPosInContent(target); - var bottomScrollExtent = scrollContainer.ScrollableExtent - fixedHeaderSize; + float bottomScrollExtent = scrollContainer.ScrollableExtent - fixedHeaderSize; + float scrollTarget = top - fixedHeaderSize - scrollContainer.DisplayableContent * scroll_y_centre; - if (top > bottomScrollExtent) + if (scrollTarget > bottomScrollExtent) scrollContainer.ScrollToEnd(); else - scrollContainer.ScrollTo(top - fixedHeaderSize - scrollContainer.DisplayableContent * scroll_y_centre); + scrollContainer.ScrollTo(scrollTarget); if (target is T section) lastClickedSection = section; From c22c6f3a49057544546594d2d4d34c9a255c2f02 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 18:14:12 +0900 Subject: [PATCH 304/366] Initial room background implementation --- ...creen.cs => OnlinePlayBackgroundScreen.cs} | 35 +++++---------- .../Lounge/LoungeBackgroundScreen.cs | 45 +++++++++++++++++++ .../OnlinePlay/Lounge/LoungeSubScreen.cs | 4 +- .../OnlinePlay/Match/RoomBackgroundScreen.cs | 19 ++++++++ .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 5 +++ 5 files changed, 83 insertions(+), 25 deletions(-) rename osu.Game/Screens/OnlinePlay/Components/{RoomBackgroundScreen.cs => OnlinePlayBackgroundScreen.cs} (74%) create mode 100644 osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs create mode 100644 osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs similarity index 74% rename from osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs rename to osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index 393cf49bb7..5077979bf0 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -1,57 +1,47 @@ // 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.Linq; using System.Threading; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Online.Rooms; using osuTK; +#nullable enable + namespace osu.Game.Screens.OnlinePlay.Components { - public class RoomBackgroundScreen : BackgroundScreen + public abstract class OnlinePlayBackgroundScreen : BackgroundScreen { private CancellationTokenSource? cancellationSource; private PlaylistItemBackground? background; - private readonly BindableList playlist = new BindableList(); - - public RoomBackgroundScreen() + protected OnlinePlayBackgroundScreen() : base(false) { - playlist.BindCollectionChanged((_, __) => updateBackground()); } [BackgroundDependencyLoader] private void load() { - switchBackground(new PlaylistItemBackground(null)); + switchBackground(new PlaylistItemBackground(playlistItem)); } - private Room? room; + private PlaylistItem? playlistItem; - public Room? Room + protected PlaylistItem? PlaylistItem { - get => room; + get => playlistItem; set { - if (room == value) + if (playlistItem == value) return; - if (room != null) - playlist.UnbindFrom(room.Playlist); + playlistItem = value; - room = value; - - if (room != null) - playlist.BindTo(room.Playlist); - else - playlist.Clear(); + if (LoadState > LoadState.Ready) + updateBackground(); } } @@ -59,7 +49,6 @@ namespace osu.Game.Screens.OnlinePlay.Components { Schedule(() => { - var playlistItem = playlist.FirstOrDefault(); var beatmap = playlistItem?.Beatmap.Value; if (background?.BeatmapInfo?.BeatmapSet?.OnlineInfo?.Covers?.Cover == beatmap?.BeatmapSet?.OnlineInfo?.Covers?.Cover) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs new file mode 100644 index 0000000000..7d38e220d3 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.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. + +#nullable enable + +using System.Linq; +using osu.Framework.Bindables; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; +using PlaylistItem = osu.Game.Online.Rooms.PlaylistItem; + +namespace osu.Game.Screens.OnlinePlay.Lounge +{ + public class LoungeBackgroundScreen : OnlinePlayBackgroundScreen + { + private readonly BindableList playlist = new BindableList(); + + public LoungeBackgroundScreen() + { + playlist.BindCollectionChanged((_, __) => PlaylistItem = playlist.FirstOrDefault()); + } + + private Room? selectedRoom; + + public Room? SelectedRoom + { + get => selectedRoom; + set + { + if (selectedRoom == value) + return; + + if (selectedRoom != null) + playlist.UnbindFrom(selectedRoom.Playlist); + + selectedRoom = value; + + if (selectedRoom != null) + playlist.BindTo(selectedRoom.Playlist); + else + playlist.Clear(); + } + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 34beba923f..90e5a62d7e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public override string Title => "Lounge"; - protected override BackgroundScreen CreateBackground() => new RoomBackgroundScreen(); + protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen(); protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); @@ -169,7 +169,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge if (drawable != null) scrollContainer.ScrollIntoView(drawable); - ApplyToBackground(b => ((RoomBackgroundScreen)b).Room = val.NewValue); + ApplyToBackground(b => ((LoungeBackgroundScreen)b).SelectedRoom = val.NewValue); }); } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs new file mode 100644 index 0000000000..cacc3864c2 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs @@ -0,0 +1,19 @@ +// 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.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; + +namespace osu.Game.Screens.OnlinePlay.Match +{ + public class RoomBackgroundScreen : OnlinePlayBackgroundScreen + { + public readonly Bindable SelectedItem = new Bindable(); + + public RoomBackgroundScreen() + { + SelectedItem.BindValueChanged(item => PlaylistItem = item.NewValue); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index d6a23ff708..8097e91c2e 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -29,6 +29,11 @@ namespace osu.Game.Screens.OnlinePlay.Match [Cached(typeof(IBindable))] protected readonly Bindable SelectedItem = new Bindable(); + protected override BackgroundScreen CreateBackground() => new RoomBackgroundScreen + { + SelectedItem = { BindTarget = SelectedItem } + }; + public override bool DisallowExternalBeatmapRulesetChanges => true; /// From d304e283e4a24506923f48097b84494086ef38d6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 18:14:59 +0900 Subject: [PATCH 305/366] Don't deselect online room when joined --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 4e106b844c..70342680e2 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -172,8 +172,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge sampleJoin?.Play(); lounge?.Join(Room, null); - - return base.OnClick(e); + return true; } public class PasswordEntryPopover : OsuPopover From cbee379f62cdc49b8227067fd952f5bd57bbe172 Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Fri, 20 Aug 2021 12:30:49 +0300 Subject: [PATCH 306/366] Test scrolled to section top is visible --- .../UserInterface/TestSceneSectionsContainer.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs index 5c2e6e457d..2312c57af2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; using osu.Game.Graphics.Containers; using osuTK.Graphics; @@ -61,10 +62,12 @@ namespace osu.Game.Tests.Visual.UserInterface )); AddStep("scroll up", () => triggerUserScroll(1)); AddStep("scroll down", () => triggerUserScroll(-1)); + AddStep("scroll up a bit", () => triggerUserScroll(0.1f)); + AddStep("scroll down a bit", () => triggerUserScroll(-0.1f)); } [Test] - public void TestCorrectSectionSelected() + public void TestCorrectSelectionAndVisibleTop() { const int sections_count = 11; float[] alternating = { 0.07f, 0.33f, 0.16f, 0.33f }; @@ -79,6 +82,12 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep($"scroll to section {scrollIndex + 1}", () => container.ScrollTo(container.Children[scrollIndex])); AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[scrollIndex]); + AddUntilStep("section top is visible", () => + { + float scrollPosition = container.ChildrenOfType().First().Current; + float sectionTop = container.Children[scrollIndex].BoundingBox.Top; + return scrollPosition < sectionTop; + }); } for (int i = 1; i < sections_count; i++) From 77149044a5954278d9deef2b014c5fe267033915 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 19:33:47 +0900 Subject: [PATCH 307/366] Allow intro screen to retrieve beatmap even if rulesets is not loaded --- osu.Game/Beatmaps/BeatmapManager.cs | 36 +++++++++++++++++++++++++++- osu.Game/Beatmaps/BeatmapStore.cs | 7 ++++++ osu.Game/Screens/Menu/IntroScreen.cs | 3 ++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 4a78ceb299..241649062e 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -365,6 +365,10 @@ namespace osu.Game.Beatmaps queryable = beatmaps.BeatmapSetsOverview; break; + case IncludedDetails.AllButRuleset: + queryable = beatmaps.BeatmapSetsWithoutRuleset; + break; + case IncludedDetails.AllButFiles: queryable = beatmaps.BeatmapSetsWithoutFiles; break; @@ -384,8 +388,33 @@ namespace osu.Game.Beatmaps /// Perform a lookup query on available s. /// /// The query. + /// The level of detail to include in the returned objects. /// Results from the provided query. - public IEnumerable QueryBeatmapSets(Expression> query) => beatmaps.ConsumableItems.AsNoTracking().Where(query); + public IEnumerable QueryBeatmapSets(Expression> query, IncludedDetails includes = IncludedDetails.All) + { + IQueryable queryable; + + switch (includes) + { + case IncludedDetails.Minimal: + queryable = beatmaps.BeatmapSetsOverview; + break; + + case IncludedDetails.AllButRuleset: + queryable = beatmaps.BeatmapSetsWithoutRuleset; + break; + + case IncludedDetails.AllButFiles: + queryable = beatmaps.BeatmapSetsWithoutFiles; + break; + + default: + queryable = beatmaps.ConsumableItems; + break; + } + + return queryable.AsNoTracking().Where(query); + } /// /// Perform a lookup query on available s. @@ -554,6 +583,11 @@ namespace osu.Game.Beatmaps /// AllButFiles, + /// + /// Include everything except ruleset. Used for cases where we aren't sure the ruleset is present but still want to consume the beatmap. + /// + AllButRuleset, + /// /// Include everything. /// diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index 642bafd2ac..e3214b7c03 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -92,6 +92,13 @@ namespace osu.Game.Beatmaps .Include(s => s.Beatmaps) .AsNoTracking(); + public IQueryable BeatmapSetsWithoutRuleset => ContextFactory.Get().BeatmapSetInfo + .Include(s => s.Metadata) + .Include(s => s.Files).ThenInclude(f => f.FileInfo) + .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) + .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata) + .AsNoTracking(); + public IQueryable BeatmapSetsWithoutFiles => ContextFactory.Get().BeatmapSetInfo .Include(s => s.Metadata) .Include(s => s.Beatmaps).ThenInclude(s => s.Ruleset) diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index 71f3b60026..07a94fb97e 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -109,7 +110,7 @@ namespace osu.Game.Screens.Menu bool loadThemedIntro() { - setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == BeatmapHash); + setInfo = beatmaps.QueryBeatmapSets(b => b.Hash == BeatmapHash, IncludedDetails.AllButRuleset).FirstOrDefault(); if (setInfo == null) return false; From b9ff94485db48af93f12ea0fbd879737d76a7bd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 19:45:52 +0900 Subject: [PATCH 308/366] Revert usage of `OsuGameTestScene` for `TestSceneOsuGame` Turns out we likely don't want this, as it means the testing user (using a visual test browser) will not have access to their beatmaps. Can revisit at a future date if the temporary files are still an issue. --- .../TestSceneOsuGame.cs | 23 +++++++++++- .../TestSceneOsuGame.cs | 23 +++++++++++- .../TestSceneOsuGame.cs | 23 +++++++++++- .../TestSceneOsuGame.cs | 23 +++++++++++- .../Visual/Navigation/TestSceneOsuGame.cs | 37 ++++++++++++++++++- 5 files changed, 123 insertions(+), 6 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs index fb63f69f72..9c512a01ea 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs @@ -1,11 +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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; using osu.Game.Tests.Visual; +using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyFreeform.Tests { - public class TestSceneOsuGame : OsuGameTestScene + public class TestSceneOsuGame : OsuTestScene { + [BackgroundDependencyLoader] + private void load(GameHost host, OsuGameBase gameBase) + { + OsuGame game = new OsuGame(); + game.SetHost(host); + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + game + }; + } } } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs index a99a400afa..270d906b01 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs @@ -1,11 +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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; using osu.Game.Tests.Visual; +using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.Tests { - public class TestSceneOsuGame : OsuGameTestScene + public class TestSceneOsuGame : OsuTestScene { + [BackgroundDependencyLoader] + private void load(GameHost host, OsuGameBase gameBase) + { + OsuGame game = new OsuGame(); + game.SetHost(host); + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + game + }; + } } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs index debdc14b57..aed6abb6bf 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs @@ -1,11 +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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; using osu.Game.Tests.Visual; +using osuTK.Graphics; namespace osu.Game.Rulesets.EmptyScrolling.Tests { - public class TestSceneOsuGame : OsuGameTestScene + public class TestSceneOsuGame : OsuTestScene { + [BackgroundDependencyLoader] + private void load(GameHost host, OsuGameBase gameBase) + { + OsuGame game = new OsuGame(); + game.SetHost(host); + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + game + }; + } } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs index a99a400afa..270d906b01 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs @@ -1,11 +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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; using osu.Game.Tests.Visual; +using osuTK.Graphics; namespace osu.Game.Rulesets.Pippidon.Tests { - public class TestSceneOsuGame : OsuGameTestScene + public class TestSceneOsuGame : OsuTestScene { + [BackgroundDependencyLoader] + private void load(GameHost host, OsuGameBase gameBase) + { + OsuGame game = new OsuGame(); + game.SetHost(host); + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + game + }; + } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index d3f1a852d1..48e68b03fb 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -6,7 +6,11 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; +using osu.Framework.Platform; +using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; @@ -24,11 +28,12 @@ using osu.Game.Scoring; using osu.Game.Screens.Menu; using osu.Game.Skinning; using osu.Game.Utils; +using osuTK.Graphics; namespace osu.Game.Tests.Visual.Navigation { [TestFixture] - public class TestSceneOsuGame : OsuGameTestScene + public class TestSceneOsuGame : OsuTestScene { private IReadOnlyList requiredGameDependencies => new[] { @@ -79,9 +84,37 @@ namespace osu.Game.Tests.Visual.Navigation typeof(PreviewTrackManager), }; + private OsuGame game; + [Resolved] private OsuGameBase gameBase { get; set; } + [Resolved] + private GameHost host { get; set; } + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create game", () => + { + game = new OsuGame(); + game.SetHost(host); + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + game + }; + }); + + AddUntilStep("wait for load", () => game.IsLoaded); + } + + [Test] public void TestNullRulesetHandled() { @@ -117,7 +150,7 @@ namespace osu.Game.Tests.Visual.Navigation { foreach (var type in requiredGameDependencies) { - if (Game.Dependencies.Get(type) == null) + if (game.Dependencies.Get(type) == null) throw new InvalidOperationException($"{type} has not been cached"); } From b190020c4b78d0dab21a33d22c9f7637a3124fbb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 21:02:25 +0900 Subject: [PATCH 309/366] Block lounge background screen from exiting --- .../Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs index 7d38e220d3..743fb1fbbf 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs @@ -5,6 +5,7 @@ using System.Linq; using osu.Framework.Bindables; +using osu.Framework.Screens; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; using PlaylistItem = osu.Game.Online.Rooms.PlaylistItem; @@ -41,5 +42,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge playlist.Clear(); } } + + public override bool OnExiting(IScreen next) + { + // This screen never exits. + return true; + } } } From 9458cd5a31476d3d1955fc5d595080f91f3a7e0c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 21:07:51 +0900 Subject: [PATCH 310/366] Make DrawableMatchRoom background load instantly --- .../OnlinePlay/Match/DrawableMatchRoom.cs | 13 +++++++- .../OnlinePlay/Match/RoomBackgroundSprite.cs | 33 ------------------- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 3 +- 3 files changed, 14 insertions(+), 35 deletions(-) delete mode 100644 osu.Game/Screens/OnlinePlay/Match/RoomBackgroundSprite.cs diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index 0924773338..e83403850f 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -6,6 +6,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Beatmaps.Drawables; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Lounge.Components; @@ -17,6 +18,7 @@ namespace osu.Game.Screens.OnlinePlay.Match { public class DrawableMatchRoom : DrawableRoom { + public readonly IBindable SelectedItem = new Bindable(); public Action OnEdit; [Resolved] @@ -28,6 +30,8 @@ namespace osu.Game.Screens.OnlinePlay.Match [CanBeNull] private Drawable editButton; + private BackgroundSprite background; + public DrawableMatchRoom(Room room, bool allowEdit = true) : base(room) { @@ -57,8 +61,15 @@ namespace osu.Game.Screens.OnlinePlay.Match if (editButton != null) host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true); + + SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.Beatmap.Value, true); } - protected override Drawable CreateBackground() => new RoomBackgroundSprite(); + protected override Drawable CreateBackground() => background = new BackgroundSprite(); + + private class BackgroundSprite : UpdateableBeatmapBackgroundSprite + { + protected override double LoadDelay => 0; + } } } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundSprite.cs deleted file mode 100644 index 97262dd229..0000000000 --- a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundSprite.cs +++ /dev/null @@ -1,33 +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.Allocation; -using osu.Framework.Graphics; -using osu.Game.Beatmaps.Drawables; - -namespace osu.Game.Screens.OnlinePlay.Match -{ - public class RoomBackgroundSprite : RoomSubScreenComposite - { - protected readonly BeatmapSetCoverType BeatmapSetCoverType; - private UpdateableBeatmapBackgroundSprite sprite; - - public RoomBackgroundSprite(BeatmapSetCoverType beatmapSetCoverType = BeatmapSetCoverType.Cover) - { - BeatmapSetCoverType = beatmapSetCoverType; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = sprite = new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - SelectedItem.BindValueChanged(item => sprite.Beatmap.Value = item.NewValue?.Beatmap.Value, true); - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 8097e91c2e..214540fe10 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -139,7 +139,8 @@ namespace osu.Game.Screens.OnlinePlay.Match { new DrawableMatchRoom(Room, allowEdit) { - OnEdit = () => settingsOverlay.Show() + OnEdit = () => settingsOverlay.Show(), + SelectedItem = { BindTarget = SelectedItem } } }, null, From b1a732b9b7928d73d76db540e2feffece095aae2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 21:28:48 +0900 Subject: [PATCH 311/366] Remove selectedRoom from OnlinePlayScreen --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 4 +--- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 11 ----------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 90e5a62d7e..e2a4f3dfdf 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -49,9 +49,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected ListingPollingComponent ListingPollingComponent { get; private set; } - [Resolved] - private Bindable selectedRoom { get; set; } - [Resolved] private MusicController music { get; set; } @@ -68,6 +65,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private LeasedBindable selectionLease; private readonly Bindable filter = new Bindable(new FilterCriteria()); + private readonly Bindable selectedRoom = new Bindable(); private readonly IBindable operationInProgress = new Bindable(); private readonly IBindable isIdle = new BindableBool(); private LoadingLayer loadingLayer; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 76815172e5..fc20b21b60 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -10,7 +10,6 @@ using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Graphics.Containers; using osu.Game.Online.API; -using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Screens.Menu; using osu.Game.Screens.OnlinePlay.Components; @@ -38,9 +37,6 @@ namespace osu.Game.Screens.OnlinePlay [Cached(Type = typeof(IRoomManager))] protected RoomManager RoomManager { get; private set; } - [Cached] - private readonly Bindable selectedRoom = new Bindable(); - [Cached] private readonly OngoingOperationTracker ongoingOperationTracker = new OngoingOperationTracker(); @@ -106,13 +102,6 @@ namespace osu.Game.Screens.OnlinePlay apiState.BindValueChanged(onlineStateChanged, true); } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new CachedModelDependencyContainer(base.CreateChildDependencies(parent)); - dependencies.Model.BindTo(selectedRoom); - return dependencies; - } - private void forcefullyExit() { // This is temporary since we don't currently have a way to force screens to be exited From 5c8ca32ea4b94387d082b8a994d261cb2a62c717 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 21:33:21 +0900 Subject: [PATCH 312/366] Simplify lounge implementation --- .../Lounge/LoungeBackgroundScreen.cs | 27 +++++++------------ .../OnlinePlay/Lounge/LoungeSubScreen.cs | 4 +-- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 5 +--- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs index 743fb1fbbf..6c00ca2e81 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs @@ -14,33 +14,24 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public class LoungeBackgroundScreen : OnlinePlayBackgroundScreen { + public readonly Bindable SelectedRoom = new Bindable(); private readonly BindableList playlist = new BindableList(); public LoungeBackgroundScreen() { + SelectedRoom.BindValueChanged(onSelectedRoomChanged); playlist.BindCollectionChanged((_, __) => PlaylistItem = playlist.FirstOrDefault()); } - private Room? selectedRoom; - - public Room? SelectedRoom + private void onSelectedRoomChanged(ValueChangedEvent room) { - get => selectedRoom; - set - { - if (selectedRoom == value) - return; + if (room.OldValue != null) + playlist.UnbindFrom(room.OldValue.Playlist); - if (selectedRoom != null) - playlist.UnbindFrom(selectedRoom.Playlist); - - selectedRoom = value; - - if (selectedRoom != null) - playlist.BindTo(selectedRoom.Playlist); - else - playlist.Clear(); - } + if (room.NewValue != null) + playlist.BindTo(room.NewValue.Playlist); + else + playlist.Clear(); } public override bool OnExiting(IScreen next) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index e2a4f3dfdf..034deba54a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public override string Title => "Lounge"; - protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen(); + protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen { SelectedRoom = { BindTarget = selectedRoom } }; protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); @@ -166,8 +166,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge var drawable = roomsContainer.Rooms.FirstOrDefault(r => r.Room == val.NewValue); if (drawable != null) scrollContainer.ScrollIntoView(drawable); - - ApplyToBackground(b => ((LoungeBackgroundScreen)b).SelectedRoom = val.NewValue); }); } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 214540fe10..36cd8c4df3 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -29,10 +29,7 @@ namespace osu.Game.Screens.OnlinePlay.Match [Cached(typeof(IBindable))] protected readonly Bindable SelectedItem = new Bindable(); - protected override BackgroundScreen CreateBackground() => new RoomBackgroundScreen - { - SelectedItem = { BindTarget = SelectedItem } - }; + protected override BackgroundScreen CreateBackground() => new RoomBackgroundScreen { SelectedItem = { BindTarget = SelectedItem } }; public override bool DisallowExternalBeatmapRulesetChanges => true; From 5192ee3b5713efe0e167d789d59b897cf894ed99 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 21:40:35 +0900 Subject: [PATCH 313/366] Fix initial display in room background --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 5 ++++- osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs | 3 ++- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 5 ++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 034deba54a..ee51b37849 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -36,7 +36,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public override string Title => "Lounge"; - protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen { SelectedRoom = { BindTarget = selectedRoom } }; + protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen + { + SelectedRoom = { BindTarget = selectedRoom } + }; protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs index cacc3864c2..2e5f25370f 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs @@ -11,8 +11,9 @@ namespace osu.Game.Screens.OnlinePlay.Match { public readonly Bindable SelectedItem = new Bindable(); - public RoomBackgroundScreen() + public RoomBackgroundScreen(PlaylistItem initialPlaylistItem) { + PlaylistItem = initialPlaylistItem; SelectedItem.BindValueChanged(item => PlaylistItem = item.NewValue); } } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 36cd8c4df3..8ab3f77888 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -29,7 +29,10 @@ namespace osu.Game.Screens.OnlinePlay.Match [Cached(typeof(IBindable))] protected readonly Bindable SelectedItem = new Bindable(); - protected override BackgroundScreen CreateBackground() => new RoomBackgroundScreen { SelectedItem = { BindTarget = SelectedItem } }; + protected override BackgroundScreen CreateBackground() => new RoomBackgroundScreen(Room.Playlist.FirstOrDefault()) + { + SelectedItem = { BindTarget = SelectedItem } + }; public override bool DisallowExternalBeatmapRulesetChanges => true; From f85d3665d82f1edc9444f6bddd5fa5ffa8c36482 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 20 Aug 2021 21:45:24 +0900 Subject: [PATCH 314/366] Cleanups --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 1 - osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 +- .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 3 --- osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs | 3 --- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index ee51b37849..7e898db584 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -235,7 +235,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge public override void OnEntering(IScreen last) { base.OnEntering(last); - onReturning(); } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 8ab3f77888..c05022a903 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -426,7 +426,7 @@ namespace osu.Game.Screens.OnlinePlay.Match /// /// Creates the room settings overlay. /// - /// + /// The room to change the settings of. protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(Room room); private class UserModSelectOverlay : LocalPlayerModSelectOverlay diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 1cb3ce0b12..06e60903aa 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -78,9 +78,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (!connected.NewValue) handleRoomLost(); }, true); - - // if (client.Room == null) - // handleRoomLost(); } protected override Drawable CreateMainContent() => new GridContainer diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index 371824577e..3411c4afb1 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -36,9 +36,7 @@ namespace osu.Game.Screens.OnlinePlay public override bool OnExiting(IScreen next) { base.OnExiting(next); - this.FadeOut(DISAPPEAR_DURATION, Easing.OutQuint); - return false; } @@ -51,7 +49,6 @@ namespace osu.Game.Screens.OnlinePlay public override void OnSuspending(IScreen next) { base.OnSuspending(next); - this.FadeOut(DISAPPEAR_DURATION, Easing.OutQuint); } From 5e234fb7468942ef724c616f893cf7a50ba0853b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 22:07:13 +0900 Subject: [PATCH 315/366] Add try catch to avoid test failures on windows --- osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs b/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs index c9f5774735..5e14af5c27 100644 --- a/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs +++ b/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs @@ -313,9 +313,13 @@ namespace osu.Game.Tests.NonVisual { base.Dispose(isDisposing); - // the storage may have changed from the initial location. - // this handles cleanup of the initial location. - InitialStorage.DeleteDirectory(string.Empty); + try + { + // the storage may have changed from the initial location. + // this handles cleanup of the initial location. + InitialStorage.DeleteDirectory(string.Empty); + } + catch { } } } } From e13b516f31e28c69c74a5bcf83c04d09787291d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 22:26:36 +0900 Subject: [PATCH 316/366] Fix excess blank lines --- osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index 48e68b03fb..b8232837b5 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -114,7 +114,6 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for load", () => game.IsLoaded); } - [Test] public void TestNullRulesetHandled() { From d3dba296d672afa4d5c4d7c97154fe68117935a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Aug 2021 23:47:35 +0900 Subject: [PATCH 317/366] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f74b5d410b..8fd761691c 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e4838dc95a..0abd9adf77 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5338ad5deb..d03985a0c2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 8745fe9e34f38132487356b0ea4fff71dab3b167 Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Fri, 20 Aug 2021 22:32:04 +0300 Subject: [PATCH 318/366] Change editor timestamp regex to not match non-editor ones --- osu.Game/Online/Chat/MessageFormatter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index ae9199c428..d72104816f 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -43,7 +43,7 @@ namespace osu.Game.Online.Chat RegexOptions.IgnoreCase); // 00:00:000 (1,2,3) - test - private static readonly Regex time_regex = new Regex(@"\d\d:\d\d:\d\d\d? [^-]*"); + private static readonly Regex time_regex = new Regex(@"\d\d:\d\d:\d\d\d? \((\d,?)+\)"); // #osu private static readonly Regex channel_regex = new Regex(@"(#[a-zA-Z]+[a-zA-Z0-9]+)"); From 058d2d2a49eaa4eb929b59c900f0b11b26f2d73a Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Fri, 20 Aug 2021 23:01:06 +0300 Subject: [PATCH 319/366] Use nekodex's regex from osu-web --- osu.Game/Online/Chat/MessageFormatter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index d72104816f..0e4ea694aa 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -43,7 +43,8 @@ namespace osu.Game.Online.Chat RegexOptions.IgnoreCase); // 00:00:000 (1,2,3) - test - private static readonly Regex time_regex = new Regex(@"\d\d:\d\d:\d\d\d? \((\d,?)+\)"); + // regex from https://github.com/ppy/osu-web/blob/651a9bac2b60d031edd7e33b8073a469bf11edaa/resources/assets/coffee/_classes/beatmap-discussion-helper.coffee#L10 + private static readonly Regex time_regex = new Regex(@"\b(((\d{2,}):([0-5]\d)[:.](\d{3}))(\s\((?:\d+[,|])*\d+\))?)"); // #osu private static readonly Regex channel_regex = new Regex(@"(#[a-zA-Z]+[a-zA-Z0-9]+)"); From 20f193c1c2eb6f85ab522884946d97423dbf0f60 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Aug 2021 04:15:54 +0300 Subject: [PATCH 320/366] Fix screen offsetting not handling scaled game instances By using `Content` instead, now the logic will get the X of the settings overlay at the `Content` space, which can be scaled in the `ScalingMode.Everything` mode. And in the case of `ScalingMode.ExcludeOverlays`, a subcontainer somewhere inside `Content` that's holding the screen stack would be scaled, but `Content` won't be affected which is what we want in that case. --- 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 0db63df69b..b9a649fda2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1019,9 +1019,9 @@ namespace osu.Game var horizontalOffset = 0f; if (Settings.IsLoaded && Settings.IsPresent) - horizontalOffset += ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SIDE_OVERLAY_OFFSET_RATIO; + horizontalOffset += Content.ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SIDE_OVERLAY_OFFSET_RATIO; if (Notifications.IsLoaded && Notifications.IsPresent) - horizontalOffset += (ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - DrawWidth) * SIDE_OVERLAY_OFFSET_RATIO; + horizontalOffset += (Content.ToLocalSpace(Notifications.ScreenSpaceDrawQuad.TopLeft).X - Content.DrawWidth) * SIDE_OVERLAY_OFFSET_RATIO; ScreenOffsetContainer.X = horizontalOffset; From 318f830cd22152eaf712cbe5f5abd7458f8c4463 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Aug 2021 04:18:03 +0300 Subject: [PATCH 321/366] Expand test coverage for different scaling modes Intentionally not using `[Values]` as the scale modes can be applied to the running game instance directly, rather than recreating it all over again. The same could be said for the notification overlay but not sure, seems like something that should be considered at an `OsuGameTestScene` level instead (whether the same game instance can be reused for further testing). --- .../Visual/Menus/TestSceneSideOverlays.cs | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs index 5230e026bc..e34ec6c46a 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -1,8 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Linq; using NUnit.Framework; using osu.Framework.Testing; +using osu.Framework.Utils; +using osu.Game.Configuration; using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Menus @@ -21,21 +25,48 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestScreenOffsettingOnSettingsOverlay() { - AddStep("open settings", () => Game.Settings.Show()); - AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == SettingsPanel.WIDTH * TestOsuGame.SIDE_OVERLAY_OFFSET_RATIO); + foreach (var scalingMode in Enum.GetValues(typeof(ScalingMode)).Cast()) + { + AddStep($"set scaling mode to {scalingMode}", () => + { + Game.LocalConfig.SetValue(OsuSetting.Scaling, scalingMode); - AddStep("hide settings", () => Game.Settings.Hide()); - AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); + if (scalingMode != ScalingMode.Off) + { + Game.LocalConfig.SetValue(OsuSetting.ScalingSizeX, 0.5f); + Game.LocalConfig.SetValue(OsuSetting.ScalingSizeY, 0.5f); + } + }); + + AddStep("open settings", () => Game.Settings.Show()); + AddUntilStep("right screen offset applied", () => Precision.AlmostEquals(Game.ScreenOffsetContainer.X, SettingsPanel.WIDTH * TestOsuGame.SIDE_OVERLAY_OFFSET_RATIO)); + + AddStep("hide settings", () => Game.Settings.Hide()); + AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); + } } [Test] public void TestScreenOffsettingOnNotificationOverlay() { - AddStep("open notifications", () => Game.Notifications.Show()); - AddUntilStep("right screen offset applied", () => Game.ScreenOffsetContainer.X == -NotificationOverlay.WIDTH * TestOsuGame.SIDE_OVERLAY_OFFSET_RATIO); + foreach (var scalingMode in Enum.GetValues(typeof(ScalingMode)).Cast()) + { + if (scalingMode != ScalingMode.Off) + { + AddStep($"set scaling mode to {scalingMode}", () => + { + Game.LocalConfig.SetValue(OsuSetting.Scaling, scalingMode); + Game.LocalConfig.SetValue(OsuSetting.ScalingSizeX, 0.5f); + Game.LocalConfig.SetValue(OsuSetting.ScalingSizeY, 0.5f); + }); + } - AddStep("hide notifications", () => Game.Notifications.Hide()); - AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); + AddStep("open notifications", () => Game.Notifications.Show()); + AddUntilStep("right screen offset applied", () => Precision.AlmostEquals(Game.ScreenOffsetContainer.X, -NotificationOverlay.WIDTH * TestOsuGame.SIDE_OVERLAY_OFFSET_RATIO)); + + AddStep("hide notifications", () => Game.Notifications.Hide()); + AddUntilStep("screen offset removed", () => Game.ScreenOffsetContainer.X == 0f); + } } } } From 36352d1de4338014c6a154ebef4157888bd9ba54 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 21 Aug 2021 14:34:35 +0900 Subject: [PATCH 322/366] Improve highlighted chat username shadow effect --- osu.Game/Overlays/Chat/ChatLine.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 01cfe9a55b..6f4f568eb2 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -110,15 +110,15 @@ namespace osu.Game.Overlays.Chat EdgeEffect = new EdgeEffectParameters { Roundness = 1, - Offset = new Vector2(0, 3), - Radius = 3, + Radius = 1, Colour = Color4.Black.Opacity(0.3f), + Offset = new Vector2(0, 1), Type = EdgeEffectType.Shadow, }, Child = new Container { AutoSizeAxes = Axes.Both, - Y = 3, + Y = 0, Masking = true, CornerRadius = 4, Children = new Drawable[] From 15d443f6b7e8e00142ec5757a8973baaf887415a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 21 Aug 2021 14:44:54 +0900 Subject: [PATCH 323/366] Use the UI mouse cursor when hovering gameplay chat in an interactive state --- osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index e2f135d436..9fe41842f3 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.Play; @@ -38,6 +39,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Textbox.FocusLost = () => expandedFromTextboxFocus.Value = false; } + protected override bool OnHover(HoverEvent e) => true; // use UI mouse cursor. + protected override void LoadComplete() { base.LoadComplete(); From ae47c5cdb3396533d324a76bee5a917e98ec9099 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 21 Aug 2021 15:08:42 +0900 Subject: [PATCH 324/366] Fix bottom area of a settings section not being clickable --- osu.Game/Overlays/Settings/SettingsSection.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 6f167bf059..2a6f3f5ed7 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -47,7 +47,6 @@ namespace osu.Game.Overlays.Settings protected SettingsSection() { - Margin = new MarginPadding { Top = margin }; AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; @@ -80,7 +79,7 @@ namespace osu.Game.Overlays.Settings Padding = new MarginPadding { Top = margin + border_size, - Bottom = 10, + Bottom = margin + 10, }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, From 1729d43cecba9ca9d33203e5f09713693fd4473b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Aug 2021 15:18:03 +0300 Subject: [PATCH 325/366] Add explanatory comment --- osu.Game/OsuGame.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b9a649fda2..b827b687a5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1018,6 +1018,8 @@ namespace osu.Game var horizontalOffset = 0f; + // Calculate the horizontal offset using Content, as it gets nested inside a ScalingMode.Everything container + // which should apply to overlays, but not get affected by modes like ScalingMode.ExcludeOverlays which shouldn't. if (Settings.IsLoaded && Settings.IsPresent) horizontalOffset += Content.ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SIDE_OVERLAY_OFFSET_RATIO; if (Notifications.IsLoaded && Notifications.IsPresent) From 9a6ff2995103596aa944aed5b746805619f9385e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Aug 2021 15:39:57 +0300 Subject: [PATCH 326/366] Reword comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/OsuGame.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b827b687a5..4d952c39c6 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1018,8 +1018,9 @@ namespace osu.Game var horizontalOffset = 0f; - // Calculate the horizontal offset using Content, as it gets nested inside a ScalingMode.Everything container - // which should apply to overlays, but not get affected by modes like ScalingMode.ExcludeOverlays which shouldn't. + // Content.ToLocalSpace() is used instead of this.ToLocalSpace() to correctly calculate the offset with scaling modes active. + // Content is a child of a scaling container with ScalingMode.Everything set, while the game itself is never scaled. + // this avoids a visible jump in the positioning of the screen offset container. if (Settings.IsLoaded && Settings.IsPresent) horizontalOffset += Content.ToLocalSpace(Settings.ScreenSpaceDrawQuad.TopRight).X * SIDE_OVERLAY_OFFSET_RATIO; if (Notifications.IsLoaded && Notifications.IsPresent) From 479401e533682635868cfcedbcb2c7b15179103f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 21 Aug 2021 15:11:08 +0200 Subject: [PATCH 327/366] Add option to set own computation function in test --- .../Beatmaps/TestSceneBeatmapDifficultyCache.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index da457c9e8f..7bbe647302 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -58,6 +58,12 @@ namespace osu.Game.Tests.Beatmaps { OsuModDoubleTime dt = null; + AddStep("set computation function", () => difficultyCache.ComputeDifficulty = lookup => + { + var modRateAdjust = (ModRateAdjust)lookup.OrderedMods.SingleOrDefault(mod => mod is ModRateAdjust); + return new StarDifficulty(BASE_STARS + modRateAdjust?.SpeedChange.Value ?? 0, 0); + }); + AddStep("change selected mod to DT", () => SelectedMods.Value = new[] { dt = new OsuModDoubleTime { SpeedChange = { Value = 1.5 } } }); AddUntilStep($"star difficulty -> {BASE_STARS + 1.5}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.5); @@ -133,13 +139,11 @@ namespace osu.Game.Tests.Beatmaps private class TestBeatmapDifficultyCache : BeatmapDifficultyCache { + public Func ComputeDifficulty { get; set; } + protected override Task ComputeValueAsync(DifficultyCacheLookup lookup, CancellationToken token = default) { - var rateAdjust = lookup.OrderedMods.OfType().SingleOrDefault(); - if (rateAdjust != null) - return Task.FromResult(new StarDifficulty(BASE_STARS + rateAdjust.SpeedChange.Value, 0)); - - return Task.FromResult(new StarDifficulty(BASE_STARS, 0)); + return Task.FromResult(ComputeDifficulty?.Invoke(lookup) ?? new StarDifficulty(BASE_STARS, 0)); } } } From f642546d6a385be54181138ce868a3df80d28950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 21 Aug 2021 15:15:13 +0200 Subject: [PATCH 328/366] Add failing test case --- .../TestSceneBeatmapDifficultyCache.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index 7bbe647302..2b4dc48fe0 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -74,6 +74,29 @@ namespace osu.Game.Tests.Beatmaps AddUntilStep($"star difficulty -> {BASE_STARS + 1.75}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.75); } + [Test] + public void TestStarDifficultyAdjustHashCodeConflict() + { + OsuModDifficultyAdjust difficultyAdjust = null; + + AddStep("set computation function", () => difficultyCache.ComputeDifficulty = lookup => + { + var modDifficultyAdjust = (ModDifficultyAdjust)lookup.OrderedMods.SingleOrDefault(mod => mod is ModDifficultyAdjust); + return new StarDifficulty(BASE_STARS * (modDifficultyAdjust?.OverallDifficulty.Value ?? 1), 0); + }); + + AddStep("change selected mod to DA", () => SelectedMods.Value = new[] { difficultyAdjust = new OsuModDifficultyAdjust() }); + AddUntilStep($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value?.Stars == BASE_STARS); + + AddStep("change DA difficulty to 0.5", () => difficultyAdjust.OverallDifficulty.Value = 0.5f); + AddUntilStep($"star difficulty -> {BASE_STARS * 0.5f}", () => starDifficultyBindable.Value?.Stars == BASE_STARS / 2); + + // hash code of 0 (the value) conflicts with the hash code of null (the initial/default value). + // it's important that the mod reference and its underlying bindable references stay the same to demonstrate this failure. + AddStep("change DA difficulty to 0", () => difficultyAdjust.OverallDifficulty.Value = 0); + AddUntilStep($"star difficulty -> 0", () => starDifficultyBindable.Value?.Stars == 0); + } + [Test] public void TestKeyEqualsWithDifferentModInstances() { From 995338029c78d000323dd6db66303042e8bdd153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 21 Aug 2021 15:39:02 +0200 Subject: [PATCH 329/366] Fix difficulty cache lookups sharing underlying mod instances `DifficultyCacheLookup`s were storing raw `Mod` instances into their `OrderedMods` field. This could cause the cache lookups to wrongly succeed in cases of mods with settings. The particular case that triggered this fix was Difficulty Adjust. Because the difficulty cache is backed by a dictionary, there are two stages to the lookup; first `GetHashCode()` is used to find the appropriate hash bucket to look in, and then items from that hash bucket are compared against the key being searched for via the implementation of `Equals()`. As it turns out, the first hashing step ended up being the saving grace in most cases, as the hash computation included the values of the mod settings. But the Difficulty Adjust failure case was triggered by the quirk that `GetHashCode(0) == GetHashCode(null) == 0`. In such a case, the `Equals()` fallback was used. But as it turns out, because the `Mod` instance stored to lookups was not cloned and therefore potentially externally mutable, it could be polluted after being stored to the dictionary, and therefore breaking the equality check. Even though all of the setting values were compared, the hash bucket didn't match the actual contents of the lookup anymore (because they were mutated externally, e.g. by the user changing the mod setting values in the mod settings overlay). To resolve, clone out the mod structure before creating all difficulty lookups. --- osu.Game/Beatmaps/BeatmapDifficultyCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index 5025e4ad4b..0aa6a6dd0b 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -310,7 +310,7 @@ namespace osu.Game.Beatmaps Beatmap = beatmap; // In the case that the user hasn't given us a ruleset, use the beatmap's default ruleset. Ruleset = ruleset ?? Beatmap.Ruleset; - OrderedMods = mods?.OrderBy(m => m.Acronym).ToArray() ?? Array.Empty(); + OrderedMods = mods?.OrderBy(m => m.Acronym).Select(mod => mod.DeepClone()).ToArray() ?? Array.Empty(); } public bool Equals(DifficultyCacheLookup other) From 43b3845970fefeb2998a3103b7caf565583feede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 21 Aug 2021 16:35:40 +0200 Subject: [PATCH 330/366] Remove redundant string interpolation --- osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index 2b4dc48fe0..dcfeea5db8 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Beatmaps // hash code of 0 (the value) conflicts with the hash code of null (the initial/default value). // it's important that the mod reference and its underlying bindable references stay the same to demonstrate this failure. AddStep("change DA difficulty to 0", () => difficultyAdjust.OverallDifficulty.Value = 0); - AddUntilStep($"star difficulty -> 0", () => starDifficultyBindable.Value?.Stars == 0); + AddUntilStep("star difficulty -> 0", () => starDifficultyBindable.Value?.Stars == 0); } [Test] From 9cd0a182f6b0267521b78f94e5852f4bc567ce35 Mon Sep 17 00:00:00 2001 From: Michael Malloy Date: Sun, 22 Aug 2021 00:26:35 -0500 Subject: [PATCH 331/366] Add null check for Android ruleset loading --- osu.Game/Rulesets/RulesetStore.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 1f12f3dfeb..4da3fc2b4f 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -30,7 +30,13 @@ namespace osu.Game.Rulesets // On android in release configuration assemblies are loaded from the apk directly into memory. // We cannot read assemblies from cwd, so should check loaded assemblies instead. loadFromAppDomain(); - loadFromDisk(); + + // This null check prevents Android from attempting to load the rulesets from disk. + // RuntimeInfo.StartupDirectory returns null on Android, and returns a path on other platforms. + if (RuntimeInfo.StartupDirectory != null) + { + loadFromDisk(); + } // the event handler contains code for resolving dependency on the game assembly for rulesets located outside the base game directory. // It needs to be attached to the assembly lookup event before the actual call to loadUserRulesets() else rulesets located out of the base game directory will fail From 956112eb103da73a89cc2895693cb050eff512b1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 22 Aug 2021 12:40:41 +0300 Subject: [PATCH 332/366] Reword comment and remove brackets --- osu.Game/Rulesets/RulesetStore.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 4da3fc2b4f..a9e04a02b5 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -31,12 +31,11 @@ namespace osu.Game.Rulesets // We cannot read assemblies from cwd, so should check loaded assemblies instead. loadFromAppDomain(); - // This null check prevents Android from attempting to load the rulesets from disk. - // RuntimeInfo.StartupDirectory returns null on Android, and returns a path on other platforms. + // This null check prevents Android from attempting to load the rulesets from disk, + // as the underlying path "AppContext.BaseDirectory", despite being non-nullable, it returns null on android. + // See https://github.com/xamarin/xamarin-android/issues/3489. if (RuntimeInfo.StartupDirectory != null) - { loadFromDisk(); - } // the event handler contains code for resolving dependency on the game assembly for rulesets located outside the base game directory. // It needs to be attached to the assembly lookup event before the actual call to loadUserRulesets() else rulesets located out of the base game directory will fail From 81e3c9d40f7aa6bc8d439a4bf45f0c605c9a38e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Aug 2021 19:13:21 +0900 Subject: [PATCH 333/366] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 8fd761691c..cae8a946a3 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0abd9adf77..bac99a098d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index d03985a0c2..f3ecc90bea 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From d164529be8cb0ab5eda29a454e96abf2174ca934 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 22 Aug 2021 15:29:24 +0300 Subject: [PATCH 334/366] Fix ruleset selector not updating to the first ruleset item until after `LoadComplete()` This fixes the whole issue behind `Ruleset.Value` being null, by updating `Current` on BDL rather than waiting for the base logic which executes at `LoadComplete`. This seems like something that should happen at the base `TabControl` class itself, by switching `Current` right after the first added tab item, rather than doing it on `LoadComplete`, but I'm not sure about changing framework logic outright, so fixing this locally until it occurs on other places. --- osu.Game/Rulesets/RulesetSelector.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs index 8e6ec556d2..e4d8f89a22 100644 --- a/osu.Game/Rulesets/RulesetSelector.cs +++ b/osu.Game/Rulesets/RulesetSelector.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Graphics.UserInterface; using osu.Framework.Allocation; @@ -18,6 +19,12 @@ namespace osu.Game.Rulesets { foreach (var r in Rulesets.AvailableRulesets) AddItem(r); + + // This is supposed to be an implicit process in the base class, but the problem is that it happens in LoadComplete. + // That can become an issue with overlays that require access to the initial ruleset value + // before the ruleset selectors reached a LoadComplete state. + // (e.g. displaying RankingsOverlay for the first time). + Current.Value = Items.First(); } } } From 45b8bd175c6ae9806f13250658383be901658f2e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 22 Aug 2021 15:29:47 +0300 Subject: [PATCH 335/366] Decouple rankings overlay's ruleset bindable from game-wide bindable --- osu.Game/Overlays/RankingsOverlay.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index a093969115..65c9c4d953 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -15,6 +15,7 @@ namespace osu.Game.Overlays { public class RankingsOverlay : TabbableOnlineOverlay { + protected Bindable Ruleset => Header.Ruleset; protected Bindable Country => Header.Country; private APIRequest lastRequest; @@ -22,9 +23,6 @@ namespace osu.Game.Overlays [Resolved] private IAPIProvider api { get; set; } - [Resolved] - private Bindable ruleset { get; set; } - public RankingsOverlay() : base(OverlayColourScheme.Green) { @@ -34,8 +32,6 @@ namespace osu.Game.Overlays { base.LoadComplete(); - Header.Ruleset.BindTo(ruleset); - Country.BindValueChanged(_ => { // if a country is requested, force performance scope. @@ -45,7 +41,7 @@ namespace osu.Game.Overlays Scheduler.AddOnce(triggerTabChanged); }); - ruleset.BindValueChanged(_ => + Ruleset.BindValueChanged(_ => { if (Header.Current.Value == RankingsScope.Spotlights) return; @@ -85,7 +81,7 @@ namespace osu.Game.Overlays { LoadDisplay(new SpotlightsLayout { - Ruleset = { BindTarget = ruleset } + Ruleset = { BindTarget = Ruleset } }); return; } @@ -110,13 +106,13 @@ namespace osu.Game.Overlays switch (Header.Current.Value) { case RankingsScope.Performance: - return new GetUserRankingsRequest(ruleset.Value, country: Country.Value?.FlagName); + return new GetUserRankingsRequest(Ruleset.Value, country: Country.Value?.FlagName); case RankingsScope.Country: - return new GetCountryRankingsRequest(ruleset.Value); + return new GetCountryRankingsRequest(Ruleset.Value); case RankingsScope.Score: - return new GetUserRankingsRequest(ruleset.Value, UserRankingsType.Score); + return new GetUserRankingsRequest(Ruleset.Value, UserRankingsType.Score); } return null; From 9816af688eb78a9181164761e170be53b9194586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 22 Aug 2021 14:26:53 +0200 Subject: [PATCH 336/366] Add basic design settings to setup screen --- osu.Game/Screens/Edit/Setup/DesignSection.cs | 58 ++++++++++++++++++++ osu.Game/Screens/Edit/Setup/SetupScreen.cs | 3 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Screens/Edit/Setup/DesignSection.cs diff --git a/osu.Game/Screens/Edit/Setup/DesignSection.cs b/osu.Game/Screens/Edit/Setup/DesignSection.cs new file mode 100644 index 0000000000..380b29b04b --- /dev/null +++ b/osu.Game/Screens/Edit/Setup/DesignSection.cs @@ -0,0 +1,58 @@ +// 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.Localisation; +using osu.Game.Graphics.UserInterfaceV2; + +namespace osu.Game.Screens.Edit.Setup +{ + internal class DesignSection : SetupSection + { + private LabelledSwitchButton widescreenSupport; + private LabelledSwitchButton epilepsyWarning; + private LabelledSwitchButton letterboxDuringBreaks; + + public override LocalisableString Title => "Design"; + + [BackgroundDependencyLoader] + private void load() + { + Children = new[] + { + widescreenSupport = new LabelledSwitchButton + { + Label = "Widescreen support", + Current = { Value = Beatmap.BeatmapInfo.WidescreenStoryboard } + }, + epilepsyWarning = new LabelledSwitchButton + { + Label = "Epilepsy warning", + Description = "Setting this is recommended if the storyboard contains scenes with rapidly flashing colours.", + Current = { Value = Beatmap.BeatmapInfo.EpilepsyWarning } + }, + letterboxDuringBreaks = new LabelledSwitchButton + { + Label = "Letterbox during breaks", + Current = { Value = Beatmap.BeatmapInfo.LetterboxInBreaks } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + widescreenSupport.Current.BindValueChanged(_ => updateBeatmap()); + epilepsyWarning.Current.BindValueChanged(_ => updateBeatmap()); + letterboxDuringBreaks.Current.BindValueChanged(_ => updateBeatmap()); + } + + private void updateBeatmap() + { + Beatmap.BeatmapInfo.WidescreenStoryboard = widescreenSupport.Current.Value; + Beatmap.BeatmapInfo.EpilepsyWarning = epilepsyWarning.Current.Value; + Beatmap.BeatmapInfo.LetterboxInBreaks = letterboxDuringBreaks.Current.Value; + } + } +} diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs index 5bbec2574f..72bf3ad67e 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreen.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs @@ -34,7 +34,8 @@ namespace osu.Game.Screens.Edit.Setup new ResourcesSection(), new MetadataSection(), new DifficultySection(), - new ColoursSection() + new ColoursSection(), + new DesignSection(), } }, }); From d602dc9d908ddcfc9470b9bda7c6c7303416bdf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 22 Aug 2021 14:28:16 +0200 Subject: [PATCH 337/366] Enable epilepsy warning setting persistence in encoder --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index f14f6ec10c..524b556ddc 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -93,8 +93,8 @@ namespace osu.Game.Beatmaps.Formats // writer.WriteLine(@"OverlayPosition: " + b.OverlayPosition); // if (!string.IsNullOrEmpty(b.SkinPreference)) // writer.WriteLine(@"SkinPreference:" + b.SkinPreference); - // if (b.EpilepsyWarning) - // writer.WriteLine(@"EpilepsyWarning: 1"); + if (beatmap.BeatmapInfo.EpilepsyWarning) + writer.WriteLine(@"EpilepsyWarning: 1"); // if (b.CountdownOffset > 0) // writer.WriteLine(@"CountdownOffset: " + b.CountdownOffset.ToString()); if (beatmap.BeatmapInfo.RulesetID == 3) From e4a8f72167e2239a0254ded972dc2b0f27b7e000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 22 Aug 2021 19:01:26 +0200 Subject: [PATCH 338/366] Add failing test case --- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 26 +++++++++++++++++++ osu.Game/Screens/Select/BeatmapInfoWedge.cs | 3 +++ 2 files changed, 29 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 2b38c4f936..9fa0eab548 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Globalization; using System.Linq; using JetBrains.Annotations; using NUnit.Framework; @@ -11,6 +12,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osu.Game.Rulesets.Catch; @@ -19,6 +21,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Select; using osuTK; @@ -141,6 +144,29 @@ namespace osu.Game.Tests.Visual.SongSelect selectBeatmap(createLongMetadata()); } + [Test] + public void TestBPMUpdates() + { + const float bpm = 120; + IBeatmap beatmap = createTestBeatmap(new OsuRuleset().RulesetInfo); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 60 * 1000 / bpm }); + + OsuModDoubleTime doubleTime = null; + + selectBeatmap(beatmap); + checkDisplayedBPM(bpm); + + AddStep("select DT", () => SelectedMods.Value = new[] { doubleTime = new OsuModDoubleTime() }); + checkDisplayedBPM(bpm * 1.5f); + + AddStep("change DT rate", () => doubleTime.SpeedChange.Value = 2); + checkDisplayedBPM(bpm * 2); + + void checkDisplayedBPM(float target) => + AddUntilStep($"displayed bpm is {target}", () => this.ChildrenOfType().Any( + label => label.Statistic.Name == "BPM" && label.Statistic.Content == target.ToString(CultureInfo.InvariantCulture))); + } + private void selectBeatmap([CanBeNull] IBeatmap b) { Container containerBefore = null; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 297a16dd1d..1769381a58 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -449,8 +449,11 @@ namespace osu.Game.Screens.Select { public LocalisableString TooltipText { get; } + internal BeatmapStatistic Statistic { get; } + public InfoLabel(BeatmapStatistic statistic) { + Statistic = statistic; TooltipText = statistic.Name; AutoSizeAxes = Axes.Both; From 9538a32b5ec0fbe7ea7fdf0a2012743b84fe877a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 22 Aug 2021 19:05:44 +0200 Subject: [PATCH 339/366] Explicitly update beatmap info wedge on mod change This used to already be the case prior to b419ea7, but in a very roundabout way. Changes to the value of the star difficulty bindable - including indirect changes via the set of active mods changing - would trigger the wedge display to regenerate and load asynchronously. b419ea7 accidentally broke this by moving down the bindable retrieval to a lower level, at which point `WedgeInfoText` would only receive the set of mods selected at the time at which a given beatmap was selected, and not receive any further updates, breaking the BPM display updating in real time (as `WedgeInfoText` could not be aware that rate-changing mods were even in effect). To resolve, explicitly reload the wedge's contents on mod changes. --- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 1769381a58..d40e21cd5e 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -71,6 +71,7 @@ namespace osu.Game.Screens.Select private void load() { ruleset.BindValueChanged(_ => updateDisplay()); + mods.BindValueChanged(_ => updateDisplay()); } private const double animation_duration = 800; From 2e80e2be5146f0f7d54c476d6c9530b2f7abf96d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 22 Aug 2021 21:47:37 +0200 Subject: [PATCH 340/366] Reword epilepsy warning description text --- osu.Game/Screens/Edit/Setup/DesignSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Setup/DesignSection.cs b/osu.Game/Screens/Edit/Setup/DesignSection.cs index 380b29b04b..ce6b4fa034 100644 --- a/osu.Game/Screens/Edit/Setup/DesignSection.cs +++ b/osu.Game/Screens/Edit/Setup/DesignSection.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Edit.Setup epilepsyWarning = new LabelledSwitchButton { Label = "Epilepsy warning", - Description = "Setting this is recommended if the storyboard contains scenes with rapidly flashing colours.", + Description = "Recommended if the storyboard contains scenes with rapidly flashing colours.", Current = { Value = Beatmap.BeatmapInfo.EpilepsyWarning } }, letterboxDuringBreaks = new LabelledSwitchButton From 4f3a5fbad5245ef37b73a6123b136f94eb61f128 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 23 Aug 2021 14:29:15 +0900 Subject: [PATCH 341/366] Fix test failure --- .../TestScenePlaylistsLoungeSubScreen.cs | 20 ++++++++++++------- .../OnlinePlay/Lounge/LoungeSubScreen.cs | 15 +++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index a4bcb4baae..dafa8300f6 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -3,10 +3,11 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Graphics.Containers; -using osu.Game.Screens.OnlinePlay.Lounge; +using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Tests.Visual.OnlinePlay; @@ -18,13 +19,13 @@ namespace osu.Game.Tests.Visual.Playlists { protected new TestRequestHandlingRoomManager RoomManager => (TestRequestHandlingRoomManager)base.RoomManager; - private LoungeSubScreen loungeScreen; + private TestLoungeSubScreen loungeScreen; public override void SetUpSteps() { base.SetUpSteps(); - AddStep("push screen", () => LoadScreen(loungeScreen = new PlaylistsLoungeSubScreen())); + AddStep("push screen", () => LoadScreen(loungeScreen = new TestLoungeSubScreen())); AddUntilStep("wait for present", () => loungeScreen.IsCurrentScreen()); } @@ -69,21 +70,26 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("add rooms", () => RoomManager.AddRooms(1)); - AddAssert("selected room is not disabled", () => !OnlinePlayDependencies.SelectedRoom.Disabled); + AddAssert("selected room is not disabled", () => !loungeScreen.SelectedRoom.Disabled); AddStep("select room", () => roomsContainer.Rooms[0].TriggerClick()); - AddAssert("selected room is non-null", () => OnlinePlayDependencies.SelectedRoom.Value != null); + AddAssert("selected room is non-null", () => loungeScreen.SelectedRoom.Value != null); AddStep("enter room", () => roomsContainer.Rooms[0].TriggerClick()); AddUntilStep("wait for match load", () => Stack.CurrentScreen is PlaylistsRoomSubScreen); - AddAssert("selected room is non-null", () => OnlinePlayDependencies.SelectedRoom.Value != null); - AddAssert("selected room is disabled", () => OnlinePlayDependencies.SelectedRoom.Disabled); + AddAssert("selected room is non-null", () => loungeScreen.SelectedRoom.Value != null); + AddAssert("selected room is disabled", () => loungeScreen.SelectedRoom.Disabled); } private bool checkRoomVisible(DrawableRoom room) => loungeScreen.ChildrenOfType().First().ScreenSpaceDrawQuad .Contains(room.ScreenSpaceDrawQuad.Centre); + + private class TestLoungeSubScreen : PlaylistsLoungeSubScreen + { + public new Bindable SelectedRoom => base.SelectedRoom; + } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 7e898db584..cf3d76a3fb 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen { - SelectedRoom = { BindTarget = selectedRoom } + SelectedRoom = { BindTarget = SelectedRoom } }; protected override UserActivity InitialActivity => new UserActivity.SearchingForLobby(); @@ -52,6 +52,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected ListingPollingComponent ListingPollingComponent { get; private set; } + protected readonly Bindable SelectedRoom = new Bindable(); + [Resolved] private MusicController music { get; set; } @@ -68,7 +70,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private LeasedBindable selectionLease; private readonly Bindable filter = new Bindable(new FilterCriteria()); - private readonly Bindable selectedRoom = new Bindable(); private readonly IBindable operationInProgress = new Bindable(); private readonly IBindable isIdle = new BindableBool(); private LoadingLayer loadingLayer; @@ -105,7 +106,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge Child = roomsContainer = new RoomsContainer { Filter = { BindTarget = filter }, - SelectedRoom = { BindTarget = selectedRoom } + SelectedRoom = { BindTarget = SelectedRoom } } }, }, @@ -164,7 +165,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge }; // scroll selected room into view on selection. - selectedRoom.BindValueChanged(val => + SelectedRoom.BindValueChanged(val => { var drawable = roomsContainer.Rooms.FirstOrDefault(r => r.Room == val.NewValue); if (drawable != null) @@ -247,8 +248,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge selectionLease.Return(); selectionLease = null; - if (selectedRoom.Value?.RoomID.Value == null) - selectedRoom.Value = new Room(); + if (SelectedRoom.Value?.RoomID.Value == null) + SelectedRoom.Value = new Room(); music?.EnsurePlayingSomething(); @@ -321,7 +322,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge protected virtual void OpenNewRoom(Room room) { - selectionLease = selectedRoom.BeginLease(false); + selectionLease = SelectedRoom.BeginLease(false); Debug.Assert(selectionLease != null); selectionLease.Value = room; From 58fb0c042bb060f7ba0769c22ccc75a2ad105aaf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Aug 2021 14:30:34 +0900 Subject: [PATCH 342/366] Remove background scale altogether I'm not sure why this is required. Seems like something which was meant to exist to handle parallax, but that is already handled elsewhere now. --- osu.Game/Screens/BackgroundScreenStack.cs | 6 ------ .../OnlinePlay/Components/OnlinePlayBackgroundScreen.cs | 8 -------- 2 files changed, 14 deletions(-) diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs index 17894d2474..294f23d2ac 100644 --- a/osu.Game/Screens/BackgroundScreenStack.cs +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -4,25 +4,19 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Screens; -using osuTK; namespace osu.Game.Screens { public class BackgroundScreenStack : ScreenStack { - public const float BACKGROUND_SCALE = 1.06f; - public BackgroundScreenStack() : base(false) { - Scale = new Vector2(BACKGROUND_SCALE); RelativeSizeAxes = Axes.Both; Anchor = Anchor.Centre; Origin = Anchor.Centre; } - //public float ParallaxAmount { set => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * value; } - public void Push(BackgroundScreen screen) { if (screen == null) diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index 5077979bf0..a282f1dacf 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -77,14 +77,6 @@ namespace osu.Game.Screens.OnlinePlay.Components AddInternal(background = newBackground); } - protected override void Update() - { - base.Update(); - - // This is a static screen, so override the scale set in base.Update(), but also the scale set by the screen stack. - Scale = new Vector2(1f / BackgroundScreenStack.BACKGROUND_SCALE); - } - public override void OnSuspending(IScreen next) { base.OnSuspending(next); From 2ba88923b624d012c69c99d40b834beab47e407e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 08:41:14 +0300 Subject: [PATCH 343/366] Select user preferred ruleset on overlay ruleset selectors initially --- osu.Game/Overlays/OverlayRulesetSelector.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 8c44157f78..74b8d0d3be 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -1,9 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Rulesets; using osuTK; @@ -16,6 +18,15 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.Both; } + [BackgroundDependencyLoader] + private void load(RulesetStore store, IAPIProvider api) + { + var preferredRuleset = store.GetRuleset(api.LocalUser.Value.PlayMode); + + if (preferredRuleset != null) + Current.Value = preferredRuleset; + } + protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer From 99bb3032a54c5a65d10bf2be009c75f3edeefc00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Aug 2021 15:26:39 +0900 Subject: [PATCH 344/366] Move gradient to be part of the background for now --- .../Components/OnlinePlayBackgroundScreen.cs | 10 ++++++++++ .../Screens/OnlinePlay/OnlinePlaySubScreenStack.cs | 14 -------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index a282f1dacf..6ce5f6a6db 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -3,10 +3,14 @@ using System.Threading; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; using osu.Game.Online.Rooms; using osuTK; +using osuTK.Graphics; #nullable enable @@ -20,6 +24,12 @@ namespace osu.Game.Screens.OnlinePlay.Components protected OnlinePlayBackgroundScreen() : base(false) { + AddInternal(new Box + { + RelativeSizeAxes = Axes.Both, + Depth = float.MinValue, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.9f), Color4.Black.Opacity(0.6f)) + }); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs index 69fa3b0916..7f2a0980c1 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs @@ -1,26 +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.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay { public class OnlinePlaySubScreenStack : OsuScreenStack { - public OnlinePlaySubScreenStack() - { - AddInternal(new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.9f), Color4.Black.Opacity(0.6f)) - }); - } - protected override void ScreenChanged(IScreen prev, IScreen next) { base.ScreenChanged(prev, next); From 1d89d757af12ca677aac1892a02256d9618b13d1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 09:56:00 +0300 Subject: [PATCH 345/366] Fix beatmap ruleset selector selecting initial ruleset --- .../BeatmapSet/BeatmapRulesetSelector.cs | 3 +++ osu.Game/Overlays/OverlayRulesetSelector.cs | 9 ++++++--- osu.Game/Rulesets/RulesetSelector.cs | 20 ++++++++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 005d21726b..c46a3966ee 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -6,11 +6,14 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Rulesets; using System.Linq; +using osu.Framework.Allocation; namespace osu.Game.Overlays.BeatmapSet { public class BeatmapRulesetSelector : OverlayRulesetSelector { + protected override bool SelectInitialRuleset => false; + private readonly Bindable beatmapSet = new Bindable(); public BeatmapSetInfo BeatmapSet diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 74b8d0d3be..60b16abd48 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -21,10 +21,13 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load(RulesetStore store, IAPIProvider api) { - var preferredRuleset = store.GetRuleset(api.LocalUser.Value.PlayMode); + if (SelectInitialRuleset) + { + var preferredRuleset = store.GetRuleset(api.LocalUser.Value.PlayMode); - if (preferredRuleset != null) - Current.Value = preferredRuleset; + if (preferredRuleset != null) + Current.Value = preferredRuleset; + } } protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs index e4d8f89a22..e5d39fa144 100644 --- a/osu.Game/Rulesets/RulesetSelector.cs +++ b/osu.Game/Rulesets/RulesetSelector.cs @@ -14,17 +14,27 @@ namespace osu.Game.Rulesets protected override Dropdown CreateDropdown() => null; + protected virtual bool SelectInitialRuleset => true; + + protected RulesetSelector() + { + SelectFirstTabByDefault = false; + } + [BackgroundDependencyLoader] private void load() { foreach (var r in Rulesets.AvailableRulesets) AddItem(r); - // This is supposed to be an implicit process in the base class, but the problem is that it happens in LoadComplete. - // That can become an issue with overlays that require access to the initial ruleset value - // before the ruleset selectors reached a LoadComplete state. - // (e.g. displaying RankingsOverlay for the first time). - Current.Value = Items.First(); + if (SelectInitialRuleset) + { + // This is supposed to be an implicit process in the base class, but the problem is that it happens in LoadComplete. + // That can become an issue with overlays that require access to the initial ruleset value + // before the ruleset selectors reached a LoadComplete state. + // (e.g. displaying RankingsOverlay for the first time). + Current.Value = Items.First(); + } } } } From f2d51200a5b53a66251aca60fc1d98a749ba94c3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Aug 2021 16:55:42 +0900 Subject: [PATCH 346/366] Update android mime types in line with new specifications --- osu.Android/OsuGameActivity.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index 063e02d349..0bcbfc4baf 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -20,8 +20,21 @@ namespace osu.Android [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.FullUser, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = false, LaunchMode = LaunchMode.SingleInstance, Exported = true)] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osz", DataHost = "*", DataMimeType = "*/*")] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osk", DataHost = "*", DataMimeType = "*/*")] - [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataMimeType = "application/x-osu-archive")] - [IntentFilter(new[] { Intent.ActionSend, Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, DataMimeTypes = new[] { "application/zip", "application/octet-stream", "application/download", "application/x-zip", "application/x-zip-compressed", "application/x-osu-archive" })] + [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataMimeType = "application/x-osu-beatmap-archive")] + [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataMimeType = "application/x-osu-skin-archive")] + [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataMimeType = "application/x-osu-replay")] + [IntentFilter(new[] { Intent.ActionSend, Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, DataMimeTypes = new[] + { + "application/zip", + "application/octet-stream", + "application/download", + "application/x-zip", + "application/x-zip-compressed", + // newer official mime types (see https://osu.ppy.sh/wiki/en/osu%21_File_Formats). + "application/x-osu-beatmap-archive", + "application/x-osu-skin-archive", + "application/x-osu-replay", + })] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, DataSchemes = new[] { "osu", "osump" })] public class OsuGameActivity : AndroidGameActivity { @@ -66,12 +79,14 @@ namespace osu.Android case Intent.ActionSendMultiple: { var uris = new List(); + for (int i = 0; i < intent.ClipData?.ItemCount; i++) { var content = intent.ClipData?.GetItemAt(i); if (content != null) uris.Add(content.Uri); } + handleImportFromUris(uris.ToArray()); break; } From cb7c2f713be7cfeb6e667df1404a843773ae83ca Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 11:09:26 +0300 Subject: [PATCH 347/366] Store default ruleset value for ability to revert --- osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs | 1 - osu.Game/Overlays/OverlayRulesetSelector.cs | 2 +- osu.Game/Rulesets/RulesetSelector.cs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index c46a3966ee..3e707fc091 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Rulesets; using System.Linq; -using osu.Framework.Allocation; namespace osu.Game.Overlays.BeatmapSet { diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 60b16abd48..3f562e933d 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays var preferredRuleset = store.GetRuleset(api.LocalUser.Value.PlayMode); if (preferredRuleset != null) - Current.Value = preferredRuleset; + Current.Value = Current.Default = preferredRuleset; } } diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs index e5d39fa144..998948140e 100644 --- a/osu.Game/Rulesets/RulesetSelector.cs +++ b/osu.Game/Rulesets/RulesetSelector.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets // That can become an issue with overlays that require access to the initial ruleset value // before the ruleset selectors reached a LoadComplete state. // (e.g. displaying RankingsOverlay for the first time). - Current.Value = Items.First(); + Current.Value = Current.Default = Items.First(); } } } From 9fa39cd34e867be4d1258b52f427cfb5eb0cbb6b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 11:11:06 +0300 Subject: [PATCH 348/366] Revert ruleset when not applied filters (includes scope change) --- osu.Game/Overlays/RankingsOverlay.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 65c9c4d953..9ddcaa589e 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -18,6 +18,8 @@ namespace osu.Game.Overlays protected Bindable Ruleset => Header.Ruleset; protected Bindable Country => Header.Country; + private bool requiresRulesetRevert; + private APIRequest lastRequest; [Resolved] @@ -50,6 +52,25 @@ namespace osu.Game.Overlays }); } + protected override void PopIn() + { + base.PopIn(); + + if (requiresRulesetRevert) + { + Ruleset.SetDefault(); + requiresRulesetRevert = false; + } + } + + protected override void PopOutComplete() + { + base.PopOutComplete(); + + if (Header.Current.Value == default && Country.Value == null) + requiresRulesetRevert = true; + } + protected override void OnTabChanged(RankingsScope tab) { // country filtering is only valid for performance scope. From 391c4e529c4fa847385c5052e6788b1968348ef6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 11:11:15 +0300 Subject: [PATCH 349/366] Add test coverage for all added features --- .../Visual/Online/TestSceneRankingsOverlay.cs | 42 +++++++++++++++++++ .../TestSceneOverlayRulesetSelector.cs | 22 ++++++++++ 2 files changed, 64 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index aff510dd95..74b8cbdfe5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -1,12 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Game.Overlays; using NUnit.Framework; using osu.Game.Users; using osu.Framework.Bindables; +using osu.Framework.Testing; using osu.Game.Overlays.Rankings; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Taiko; namespace osu.Game.Tests.Visual.Online { @@ -35,6 +39,44 @@ namespace osu.Game.Tests.Visual.Online AddStep("Show", rankingsOverlay.Show); } + [Test] + public void TestRulesetResetsOnNoFilters() + { + AddStep("Set different ruleset", () => rankingsOverlay.ChildrenOfType().Single().SwitchTab(1)); + AddAssert("Ruleset not default", () => !rankingsOverlay.Header.Ruleset.IsDefault); + AddStep("Hide overlay", () => rankingsOverlay.Hide()); + AddUntilStep("Wait for hide", () => !rankingsOverlay.IsPresent); + + AddStep("Show overlay again", () => rankingsOverlay.Show()); + AddAssert("Ruleset reverted", () => rankingsOverlay.Header.Ruleset.IsDefault); + } + + [Test] + public void TestRulesetDoesntResetOnCountryFilter() + { + AddStep("Set different ruleset", () => rankingsOverlay.ChildrenOfType().Single().SwitchTab(1)); + AddAssert("Ruleset not default", () => !rankingsOverlay.Header.Ruleset.IsDefault); + AddStep("Set country filter", () => countryBindable.Value = us_country); + AddStep("Hide overlay", () => rankingsOverlay.Hide()); + AddUntilStep("Wait for hide", () => !rankingsOverlay.IsPresent); + + AddStep("Show overlay again", () => rankingsOverlay.Show()); + AddAssert("Ruleset not reverted", () => !rankingsOverlay.Header.Ruleset.IsDefault); + } + + [Test] + public void TestRulesetDoesntResetOnScopeChange() + { + AddStep("Set ruleset to osu!taiko", () => rankingsOverlay.Header.Ruleset.Value = new TaikoRuleset().RulesetInfo); + AddAssert("Ruleset not default", () => !rankingsOverlay.Header.Ruleset.IsDefault); + AddStep("Set different scope", () => scope.Value = RankingsScope.Score); + AddStep("Hide overlay", () => rankingsOverlay.Hide()); + AddUntilStep("Wait for hide", () => !rankingsOverlay.IsPresent); + + AddStep("Show overlay again", () => rankingsOverlay.Show()); + AddAssert("Ruleset not reverted", () => !rankingsOverlay.Header.Ruleset.IsDefault); + } + [Test] public void TestFlagScopeDependency() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index f4fa41a3b7..ceec8b2e58 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -70,5 +70,27 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Select catch", () => ruleset.Value = new CatchRuleset().RulesetInfo); AddAssert("Check catch selected", () => selector.Current.Value.Equals(new CatchRuleset().RulesetInfo)); } + + [Test] + public void TestUserPreferredRuleset() + { + OverlayRulesetSelector localSelector = null; + + AddStep("Set osu! preferred ruleset", () => API.LocalUser.Value.PlayMode = OsuRuleset.SHORT_NAME); + AddStep("load overlay ruleset selector", () => Child = localSelector = new OverlayRulesetSelector()); + AddAssert("Check osu! selected", () => localSelector.Current.Value.Equals(new OsuRuleset().RulesetInfo)); + + AddStep("Set osu!taiko preferred ruleset", () => API.LocalUser.Value.PlayMode = TaikoRuleset.SHORT_NAME); + AddStep("load overlay ruleset selector", () => Child = localSelector = new OverlayRulesetSelector()); + AddAssert("Check osu!taiko selected", () => localSelector.Current.Value.Equals(new TaikoRuleset().RulesetInfo)); + + AddStep("Set osu!catch preferred ruleset", () => API.LocalUser.Value.PlayMode = CatchRuleset.SHORT_NAME); + AddStep("load overlay ruleset selector", () => Child = localSelector = new OverlayRulesetSelector()); + AddAssert("Check osu!catch selected", () => localSelector.Current.Value.Equals(new CatchRuleset().RulesetInfo)); + + AddStep("Set osu!mania preferred ruleset", () => API.LocalUser.Value.PlayMode = ManiaRuleset.SHORT_NAME); + AddStep("load overlay ruleset selector", () => Child = localSelector = new OverlayRulesetSelector()); + AddAssert("Check osu!mania selected", () => localSelector.Current.Value.Equals(new ManiaRuleset().RulesetInfo)); + } } } From 1de84e1c9806beb54eaae23b415cc2279c8a38be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Aug 2021 17:34:19 +0900 Subject: [PATCH 350/366] Change description to include mention of video Co-authored-by: Joseph Madamba --- osu.Game/Screens/Edit/Setup/DesignSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Setup/DesignSection.cs b/osu.Game/Screens/Edit/Setup/DesignSection.cs index ce6b4fa034..3f54ba9c9b 100644 --- a/osu.Game/Screens/Edit/Setup/DesignSection.cs +++ b/osu.Game/Screens/Edit/Setup/DesignSection.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Edit.Setup epilepsyWarning = new LabelledSwitchButton { Label = "Epilepsy warning", - Description = "Recommended if the storyboard contains scenes with rapidly flashing colours.", + Description = "Recommended if the storyboard or video contain scenes with rapidly flashing colours.", Current = { Value = Beatmap.BeatmapInfo.EpilepsyWarning } }, letterboxDuringBreaks = new LabelledSwitchButton From d17f7b5c8bab129ac3d1e219177b63e5dfe6b248 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Aug 2021 17:40:41 +0900 Subject: [PATCH 351/366] Side `WidescreenStoryboard` to on by default for new beatmaps --- osu.Game/Beatmaps/BeatmapManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 241649062e..27aa874dc9 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -128,6 +128,7 @@ namespace osu.Game.Beatmaps BaseDifficulty = new BeatmapDifficulty(), Ruleset = ruleset, Metadata = metadata, + WidescreenStoryboard = true, } } }; From 2f6b95da39129c6bfcfa74b34a69ec9611bcf43c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Aug 2021 17:41:03 +0900 Subject: [PATCH 352/366] Add descriptions for the remaining settings --- osu.Game/Screens/Edit/Setup/DesignSection.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Setup/DesignSection.cs b/osu.Game/Screens/Edit/Setup/DesignSection.cs index 3f54ba9c9b..68aaf3dd76 100644 --- a/osu.Game/Screens/Edit/Setup/DesignSection.cs +++ b/osu.Game/Screens/Edit/Setup/DesignSection.cs @@ -23,6 +23,7 @@ namespace osu.Game.Screens.Edit.Setup widescreenSupport = new LabelledSwitchButton { Label = "Widescreen support", + Description = "Allows storyboards to use the full screen space, rather than be confined to a 4:3 area.", Current = { Value = Beatmap.BeatmapInfo.WidescreenStoryboard } }, epilepsyWarning = new LabelledSwitchButton @@ -34,6 +35,7 @@ namespace osu.Game.Screens.Edit.Setup letterboxDuringBreaks = new LabelledSwitchButton { Label = "Letterbox during breaks", + Description = "Adds horizontal letterboxing to give a cinematic look during breaks.", Current = { Value = Beatmap.BeatmapInfo.LetterboxInBreaks } } }; From 79aea1fb7834a4513f7153bc8e6f9b8359bfe518 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 11:44:50 +0300 Subject: [PATCH 353/366] Fix test overlay ruleset selectors not surrounded with overlay colour providers --- .../UserInterface/TestSceneOverlayRulesetSelector.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index ceec8b2e58..de55914fa8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -77,19 +77,19 @@ namespace osu.Game.Tests.Visual.UserInterface OverlayRulesetSelector localSelector = null; AddStep("Set osu! preferred ruleset", () => API.LocalUser.Value.PlayMode = OsuRuleset.SHORT_NAME); - AddStep("load overlay ruleset selector", () => Child = localSelector = new OverlayRulesetSelector()); + AddStep("load overlay ruleset selector", () => Child = new ColourProvidedContainer(OverlayColourScheme.Red, localSelector = new OverlayRulesetSelector())); AddAssert("Check osu! selected", () => localSelector.Current.Value.Equals(new OsuRuleset().RulesetInfo)); AddStep("Set osu!taiko preferred ruleset", () => API.LocalUser.Value.PlayMode = TaikoRuleset.SHORT_NAME); - AddStep("load overlay ruleset selector", () => Child = localSelector = new OverlayRulesetSelector()); + AddStep("load overlay ruleset selector", () => Child = new ColourProvidedContainer(OverlayColourScheme.Red, localSelector = new OverlayRulesetSelector())); AddAssert("Check osu!taiko selected", () => localSelector.Current.Value.Equals(new TaikoRuleset().RulesetInfo)); AddStep("Set osu!catch preferred ruleset", () => API.LocalUser.Value.PlayMode = CatchRuleset.SHORT_NAME); - AddStep("load overlay ruleset selector", () => Child = localSelector = new OverlayRulesetSelector()); + AddStep("load overlay ruleset selector", () => Child = new ColourProvidedContainer(OverlayColourScheme.Red, localSelector = new OverlayRulesetSelector())); AddAssert("Check osu!catch selected", () => localSelector.Current.Value.Equals(new CatchRuleset().RulesetInfo)); AddStep("Set osu!mania preferred ruleset", () => API.LocalUser.Value.PlayMode = ManiaRuleset.SHORT_NAME); - AddStep("load overlay ruleset selector", () => Child = localSelector = new OverlayRulesetSelector()); + AddStep("load overlay ruleset selector", () => Child = new ColourProvidedContainer(OverlayColourScheme.Red, localSelector = new OverlayRulesetSelector())); AddAssert("Check osu!mania selected", () => localSelector.Current.Value.Equals(new ManiaRuleset().RulesetInfo)); } } From c2c9a93e2c721b16947e5fa797e41a84a2584845 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Aug 2021 18:12:35 +0900 Subject: [PATCH 354/366] Show editor file choosers in a popover rather than inline Supersedes and closes #14370. Closes #14367. --- .../Edit/Setup/FileChooserLabelledTextBox.cs | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs index 69c27702f8..e68e581942 100644 --- a/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs @@ -8,22 +8,27 @@ using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Database; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; +using osuTK; namespace osu.Game.Screens.Edit.Setup { /// /// A labelled textbox which reveals an inline file chooser when clicked. /// - internal class FileChooserLabelledTextBox : LabelledTextBox, ICanAcceptFiles + internal class FileChooserLabelledTextBox : LabelledTextBox, ICanAcceptFiles, IHasPopover { private readonly string[] handledExtensions; + public IEnumerable HandledExtensions => handledExtensions; /// @@ -51,23 +56,9 @@ namespace osu.Game.Screens.Edit.Setup Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, CornerRadius = CORNER_RADIUS, - OnFocused = DisplayFileChooser + OnFocused = this.ShowPopover }; - public void DisplayFileChooser() - { - OsuFileSelector fileSelector; - - Target.Child = fileSelector = new OsuFileSelector(currentFile.Value?.DirectoryName, handledExtensions) - { - RelativeSizeAxes = Axes.X, - Height = 400, - CurrentFile = { BindTarget = currentFile } - }; - - sectionsContainer.ScrollTo(fileSelector); - } - protected override void LoadComplete() { base.LoadComplete(); @@ -111,5 +102,23 @@ namespace osu.Game.Screens.Edit.Setup GetContainingInputManager().TriggerFocusContention(this); } } + + public Popover GetPopover() => new FileChooserPopover(handledExtensions, currentFile); + + private class FileChooserPopover : OsuPopover + { + public FileChooserPopover(string[] handledExtensions, Bindable currentFile) + { + Child = new Container + { + Size = new Vector2(600, 400), + Child = new OsuFileSelector(currentFile.Value?.DirectoryName, handledExtensions) + { + RelativeSizeAxes = Axes.Both, + CurrentFile = { BindTarget = currentFile } + }, + }; + } + } } } From eeeaefbd7d0c87baeb65c0b08fa1c3364ea88c5c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 12:38:24 +0300 Subject: [PATCH 355/366] Revert "Store default ruleset value for ability to revert" This reverts commit cb7c2f713be7cfeb6e667df1404a843773ae83ca. --- osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs | 1 + osu.Game/Overlays/OverlayRulesetSelector.cs | 2 +- osu.Game/Rulesets/RulesetSelector.cs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 3e707fc091..c46a3966ee 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Rulesets; using System.Linq; +using osu.Framework.Allocation; namespace osu.Game.Overlays.BeatmapSet { diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 3f562e933d..60b16abd48 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays var preferredRuleset = store.GetRuleset(api.LocalUser.Value.PlayMode); if (preferredRuleset != null) - Current.Value = Current.Default = preferredRuleset; + Current.Value = preferredRuleset; } } diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs index 998948140e..e5d39fa144 100644 --- a/osu.Game/Rulesets/RulesetSelector.cs +++ b/osu.Game/Rulesets/RulesetSelector.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets // That can become an issue with overlays that require access to the initial ruleset value // before the ruleset selectors reached a LoadComplete state. // (e.g. displaying RankingsOverlay for the first time). - Current.Value = Current.Default = Items.First(); + Current.Value = Items.First(); } } } From 257934a14415a014d8c5bfd1703064965f70886e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 12:38:30 +0300 Subject: [PATCH 356/366] Revert "Revert ruleset when not applied filters (includes scope change)" This reverts commit 9fa39cd34e867be4d1258b52f427cfb5eb0cbb6b. --- osu.Game/Overlays/RankingsOverlay.cs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 9ddcaa589e..65c9c4d953 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -18,8 +18,6 @@ namespace osu.Game.Overlays protected Bindable Ruleset => Header.Ruleset; protected Bindable Country => Header.Country; - private bool requiresRulesetRevert; - private APIRequest lastRequest; [Resolved] @@ -52,25 +50,6 @@ namespace osu.Game.Overlays }); } - protected override void PopIn() - { - base.PopIn(); - - if (requiresRulesetRevert) - { - Ruleset.SetDefault(); - requiresRulesetRevert = false; - } - } - - protected override void PopOutComplete() - { - base.PopOutComplete(); - - if (Header.Current.Value == default && Country.Value == null) - requiresRulesetRevert = true; - } - protected override void OnTabChanged(RankingsScope tab) { // country filtering is only valid for performance scope. From 6931721864bfba25469f2647caf5b1e1b8b6476b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 12:39:27 +0300 Subject: [PATCH 357/366] Revert test coverage --- .../Visual/Online/TestSceneRankingsOverlay.cs | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index 74b8cbdfe5..aff510dd95 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -1,16 +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.Linq; using osu.Framework.Allocation; using osu.Game.Overlays; using NUnit.Framework; using osu.Game.Users; using osu.Framework.Bindables; -using osu.Framework.Testing; using osu.Game.Overlays.Rankings; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Taiko; namespace osu.Game.Tests.Visual.Online { @@ -39,44 +35,6 @@ namespace osu.Game.Tests.Visual.Online AddStep("Show", rankingsOverlay.Show); } - [Test] - public void TestRulesetResetsOnNoFilters() - { - AddStep("Set different ruleset", () => rankingsOverlay.ChildrenOfType().Single().SwitchTab(1)); - AddAssert("Ruleset not default", () => !rankingsOverlay.Header.Ruleset.IsDefault); - AddStep("Hide overlay", () => rankingsOverlay.Hide()); - AddUntilStep("Wait for hide", () => !rankingsOverlay.IsPresent); - - AddStep("Show overlay again", () => rankingsOverlay.Show()); - AddAssert("Ruleset reverted", () => rankingsOverlay.Header.Ruleset.IsDefault); - } - - [Test] - public void TestRulesetDoesntResetOnCountryFilter() - { - AddStep("Set different ruleset", () => rankingsOverlay.ChildrenOfType().Single().SwitchTab(1)); - AddAssert("Ruleset not default", () => !rankingsOverlay.Header.Ruleset.IsDefault); - AddStep("Set country filter", () => countryBindable.Value = us_country); - AddStep("Hide overlay", () => rankingsOverlay.Hide()); - AddUntilStep("Wait for hide", () => !rankingsOverlay.IsPresent); - - AddStep("Show overlay again", () => rankingsOverlay.Show()); - AddAssert("Ruleset not reverted", () => !rankingsOverlay.Header.Ruleset.IsDefault); - } - - [Test] - public void TestRulesetDoesntResetOnScopeChange() - { - AddStep("Set ruleset to osu!taiko", () => rankingsOverlay.Header.Ruleset.Value = new TaikoRuleset().RulesetInfo); - AddAssert("Ruleset not default", () => !rankingsOverlay.Header.Ruleset.IsDefault); - AddStep("Set different scope", () => scope.Value = RankingsScope.Score); - AddStep("Hide overlay", () => rankingsOverlay.Hide()); - AddUntilStep("Wait for hide", () => !rankingsOverlay.IsPresent); - - AddStep("Show overlay again", () => rankingsOverlay.Show()); - AddAssert("Ruleset not reverted", () => !rankingsOverlay.Header.Ruleset.IsDefault); - } - [Test] public void TestFlagScopeDependency() { From f4b69ceb8ae23ba438fd3230738b3b6e5469e0a1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 12:40:20 +0300 Subject: [PATCH 358/366] Remove unused using embedded in reverted changes --- osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index c46a3966ee..3e707fc091 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Rulesets; using System.Linq; -using osu.Framework.Allocation; namespace osu.Game.Overlays.BeatmapSet { From d3958eb3fbc518f7fc2e273e19da90924b22e897 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 13:23:57 +0300 Subject: [PATCH 359/366] Revert initial ruleset value logic --- .../BeatmapSet/BeatmapRulesetSelector.cs | 2 -- osu.Game/Overlays/OverlayRulesetSelector.cs | 14 -------------- osu.Game/Rulesets/RulesetSelector.cs | 17 ----------------- 3 files changed, 33 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 3e707fc091..005d21726b 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -11,8 +11,6 @@ namespace osu.Game.Overlays.BeatmapSet { public class BeatmapRulesetSelector : OverlayRulesetSelector { - protected override bool SelectInitialRuleset => false; - private readonly Bindable beatmapSet = new Bindable(); public BeatmapSetInfo BeatmapSet diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 60b16abd48..8c44157f78 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; -using osu.Game.Online.API; using osu.Game.Rulesets; using osuTK; @@ -18,18 +16,6 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.Both; } - [BackgroundDependencyLoader] - private void load(RulesetStore store, IAPIProvider api) - { - if (SelectInitialRuleset) - { - var preferredRuleset = store.GetRuleset(api.LocalUser.Value.PlayMode); - - if (preferredRuleset != null) - Current.Value = preferredRuleset; - } - } - protected override TabItem CreateTabItem(RulesetInfo value) => new OverlayRulesetTabItem(value); protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs index e5d39fa144..8e6ec556d2 100644 --- a/osu.Game/Rulesets/RulesetSelector.cs +++ b/osu.Game/Rulesets/RulesetSelector.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.Linq; using osu.Framework.Graphics.UserInterface; using osu.Framework.Allocation; @@ -14,27 +13,11 @@ namespace osu.Game.Rulesets protected override Dropdown CreateDropdown() => null; - protected virtual bool SelectInitialRuleset => true; - - protected RulesetSelector() - { - SelectFirstTabByDefault = false; - } - [BackgroundDependencyLoader] private void load() { foreach (var r in Rulesets.AvailableRulesets) AddItem(r); - - if (SelectInitialRuleset) - { - // This is supposed to be an implicit process in the base class, but the problem is that it happens in LoadComplete. - // That can become an issue with overlays that require access to the initial ruleset value - // before the ruleset selectors reached a LoadComplete state. - // (e.g. displaying RankingsOverlay for the first time). - Current.Value = Items.First(); - } } } } From f8a7e0bdb6bd21af2e83c483e1bff07a33da2a27 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 13:50:39 +0300 Subject: [PATCH 360/366] Update rankings overlay ruleset bindable with parent on initial display --- osu.Game/Overlays/RankingsOverlay.cs | 32 ++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 65c9c4d953..b8bdef925e 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -15,7 +15,6 @@ namespace osu.Game.Overlays { public class RankingsOverlay : TabbableOnlineOverlay { - protected Bindable Ruleset => Header.Ruleset; protected Bindable Country => Header.Country; private APIRequest lastRequest; @@ -23,6 +22,12 @@ namespace osu.Game.Overlays [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private IBindable parentRuleset { get; set; } + + [Cached] + private readonly Bindable ruleset = new Bindable(); + public RankingsOverlay() : base(OverlayColourScheme.Green) { @@ -32,6 +37,8 @@ namespace osu.Game.Overlays { base.LoadComplete(); + Header.Ruleset.BindTo(ruleset); + Country.BindValueChanged(_ => { // if a country is requested, force performance scope. @@ -41,7 +48,7 @@ namespace osu.Game.Overlays Scheduler.AddOnce(triggerTabChanged); }); - Ruleset.BindValueChanged(_ => + ruleset.BindValueChanged(_ => { if (Header.Current.Value == RankingsScope.Spotlights) return; @@ -50,6 +57,19 @@ namespace osu.Game.Overlays }); } + private bool requiresRulesetUpdate = true; + + protected override void PopIn() + { + if (requiresRulesetUpdate) + { + ruleset.Value = parentRuleset.Value; + requiresRulesetUpdate = false; + } + + base.PopIn(); + } + protected override void OnTabChanged(RankingsScope tab) { // country filtering is only valid for performance scope. @@ -81,7 +101,7 @@ namespace osu.Game.Overlays { LoadDisplay(new SpotlightsLayout { - Ruleset = { BindTarget = Ruleset } + Ruleset = { BindTarget = ruleset } }); return; } @@ -106,13 +126,13 @@ namespace osu.Game.Overlays switch (Header.Current.Value) { case RankingsScope.Performance: - return new GetUserRankingsRequest(Ruleset.Value, country: Country.Value?.FlagName); + return new GetUserRankingsRequest(ruleset.Value, country: Country.Value?.FlagName); case RankingsScope.Country: - return new GetCountryRankingsRequest(Ruleset.Value); + return new GetCountryRankingsRequest(ruleset.Value); case RankingsScope.Score: - return new GetUserRankingsRequest(Ruleset.Value, UserRankingsType.Score); + return new GetUserRankingsRequest(ruleset.Value, UserRankingsType.Score); } return null; From e33c3fcdbf9940e864ebdd53f70f812021b0e76f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 13:53:03 +0300 Subject: [PATCH 361/366] Add test coverage for new changes --- .../Visual/Online/TestSceneRankingsOverlay.cs | 36 +++++++++---------- .../TestSceneOverlayRulesetSelector.cs | 22 ------------ 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index aff510dd95..342ae76377 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -1,12 +1,13 @@ // 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.Overlays; using NUnit.Framework; -using osu.Game.Users; using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays; using osu.Game.Overlays.Rankings; +using osu.Game.Rulesets.Catch; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { @@ -14,25 +15,20 @@ namespace osu.Game.Tests.Visual.Online { protected override bool UseOnlineAPI => true; - [Cached(typeof(RankingsOverlay))] - private readonly RankingsOverlay rankingsOverlay; + private TestRankingsOverlay rankingsOverlay; private readonly Bindable countryBindable = new Bindable(); private readonly Bindable scope = new Bindable(); - public TestSceneRankingsOverlay() - { - Add(rankingsOverlay = new TestRankingsOverlay - { - Country = { BindTarget = countryBindable }, - Header = { Current = { BindTarget = scope } }, - }); - } + [SetUp] + public void SetUp() => Schedule(loadRankingsOverlay); [Test] - public void TestShow() + public void TestParentRulesetCopiedOnInitialShow() { - AddStep("Show", rankingsOverlay.Show); + AddStep("set ruleset", () => Ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("reload rankings overlay", loadRankingsOverlay); + AddAssert("catch ruleset selected", () => Ruleset.Value.Equals(new CatchRuleset().RulesetInfo)); } [Test] @@ -50,10 +46,14 @@ namespace osu.Game.Tests.Visual.Online AddStep("Show US", () => rankingsOverlay.ShowCountry(us_country)); } - [Test] - public void TestHide() + private void loadRankingsOverlay() { - AddStep("Hide", rankingsOverlay.Hide); + Child = rankingsOverlay = new TestRankingsOverlay + { + Country = { BindTarget = countryBindable }, + Header = { Current = { BindTarget = scope } }, + State = { Value = Visibility.Visible }, + }; } private static readonly Country us_country = new Country diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index de55914fa8..f4fa41a3b7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -70,27 +70,5 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Select catch", () => ruleset.Value = new CatchRuleset().RulesetInfo); AddAssert("Check catch selected", () => selector.Current.Value.Equals(new CatchRuleset().RulesetInfo)); } - - [Test] - public void TestUserPreferredRuleset() - { - OverlayRulesetSelector localSelector = null; - - AddStep("Set osu! preferred ruleset", () => API.LocalUser.Value.PlayMode = OsuRuleset.SHORT_NAME); - AddStep("load overlay ruleset selector", () => Child = new ColourProvidedContainer(OverlayColourScheme.Red, localSelector = new OverlayRulesetSelector())); - AddAssert("Check osu! selected", () => localSelector.Current.Value.Equals(new OsuRuleset().RulesetInfo)); - - AddStep("Set osu!taiko preferred ruleset", () => API.LocalUser.Value.PlayMode = TaikoRuleset.SHORT_NAME); - AddStep("load overlay ruleset selector", () => Child = new ColourProvidedContainer(OverlayColourScheme.Red, localSelector = new OverlayRulesetSelector())); - AddAssert("Check osu!taiko selected", () => localSelector.Current.Value.Equals(new TaikoRuleset().RulesetInfo)); - - AddStep("Set osu!catch preferred ruleset", () => API.LocalUser.Value.PlayMode = CatchRuleset.SHORT_NAME); - AddStep("load overlay ruleset selector", () => Child = new ColourProvidedContainer(OverlayColourScheme.Red, localSelector = new OverlayRulesetSelector())); - AddAssert("Check osu!catch selected", () => localSelector.Current.Value.Equals(new CatchRuleset().RulesetInfo)); - - AddStep("Set osu!mania preferred ruleset", () => API.LocalUser.Value.PlayMode = ManiaRuleset.SHORT_NAME); - AddStep("load overlay ruleset selector", () => Child = new ColourProvidedContainer(OverlayColourScheme.Red, localSelector = new OverlayRulesetSelector())); - AddAssert("Check osu!mania selected", () => localSelector.Current.Value.Equals(new ManiaRuleset().RulesetInfo)); - } } } From bd42d7aada02c787cd3d32396decb36f836c2683 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 18:01:01 +0300 Subject: [PATCH 362/366] Hide popover on file selection --- .../Edit/Setup/FileChooserLabelledTextBox.cs | 7 +-- .../Screens/Edit/Setup/ResourcesSection.cs | 59 ++++--------------- 2 files changed, 14 insertions(+), 52 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs index e68e581942..fd43349793 100644 --- a/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs @@ -31,11 +31,6 @@ namespace osu.Game.Screens.Edit.Setup public IEnumerable HandledExtensions => handledExtensions; - /// - /// The target container to display the file chooser in. - /// - public Container Target; - private readonly Bindable currentFile = new Bindable(); [Resolved] @@ -72,7 +67,7 @@ namespace osu.Game.Screens.Edit.Setup if (file.NewValue == null) return; - Target.Clear(); + this.HidePopover(); Current.Value = file.NewValue.FullName; } diff --git a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs index ba22c82ecc..8e739a786f 100644 --- a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs +++ b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterfaceV2; @@ -39,62 +38,30 @@ namespace osu.Game.Screens.Edit.Setup [BackgroundDependencyLoader] private void load() { - Container audioTrackFileChooserContainer = createFileChooserContainer(); - Container backgroundFileChooserContainer = createFileChooserContainer(); - Children = new Drawable[] { - new FillFlowContainer + backgroundTextBox = new FileChooserLabelledTextBox(".jpg", ".jpeg", ".png") { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - backgroundTextBox = new FileChooserLabelledTextBox(".jpg", ".jpeg", ".png") - { - Label = "Background", - FixedLabelWidth = LABEL_WIDTH, - PlaceholderText = "Click to select a background image", - Current = { Value = working.Value.Metadata.BackgroundFile }, - Target = backgroundFileChooserContainer, - TabbableContentContainer = this - }, - backgroundFileChooserContainer, - } + Label = "Background", + FixedLabelWidth = LABEL_WIDTH, + PlaceholderText = "Click to select a background image", + Current = { Value = working.Value.Metadata.BackgroundFile }, + TabbableContentContainer = this }, - new FillFlowContainer + audioTrackTextBox = new FileChooserLabelledTextBox(".mp3", ".ogg") { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - audioTrackTextBox = new FileChooserLabelledTextBox(".mp3", ".ogg") - { - Label = "Audio Track", - FixedLabelWidth = LABEL_WIDTH, - PlaceholderText = "Click to select a track", - Current = { Value = working.Value.Metadata.AudioFile }, - Target = audioTrackFileChooserContainer, - TabbableContentContainer = this - }, - audioTrackFileChooserContainer, - } - } + Label = "Audio Track", + FixedLabelWidth = LABEL_WIDTH, + PlaceholderText = "Click to select a track", + Current = { Value = working.Value.Metadata.AudioFile }, + TabbableContentContainer = this + }, }; backgroundTextBox.Current.BindValueChanged(backgroundChanged); audioTrackTextBox.Current.BindValueChanged(audioTrackChanged); } - private static Container createFileChooserContainer() => - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }; - public bool ChangeBackgroundImage(string path) { var info = new FileInfo(path); From 9a507ed2736c4c79d7382024e535bcec78cda5b5 Mon Sep 17 00:00:00 2001 From: Davran Dilshat Date: Mon, 23 Aug 2021 16:27:29 +0100 Subject: [PATCH 363/366] update selected section on children count change --- osu.Game/Graphics/Containers/SectionsContainer.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 76492cab55..00c55bdd57 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -202,6 +202,8 @@ namespace osu.Game.Graphics.Containers }); } + private int lastKnownChildrenCount = 0; + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -220,10 +222,12 @@ namespace osu.Game.Graphics.Containers } float currentScroll = scrollContainer.Current; + var presentChildren = Children.Where(c => c.IsPresent); - if (currentScroll != lastKnownScroll) + if (currentScroll != lastKnownScroll || presentChildren.Count() != lastKnownChildrenCount) { lastKnownScroll = currentScroll; + lastKnownChildrenCount = presentChildren.Count(); // reset last clicked section because user started scrolling themselves if (scrollContainer.UserScrolling) @@ -249,8 +253,6 @@ namespace osu.Game.Graphics.Containers float scrollCentre = fixedHeaderSize + scrollContainer.DisplayableContent * scroll_y_centre + selectionLenienceAboveSection; - var presentChildren = Children.Where(c => c.IsPresent); - if (lastClickedSection != null) SelectedSection.Value = lastClickedSection; else if (Precision.AlmostBigger(0, scrollContainer.Current)) From 20222f09c463a8a443b9def3c5b207f478b20d69 Mon Sep 17 00:00:00 2001 From: Davran Dilshat Date: Mon, 23 Aug 2021 16:55:31 +0100 Subject: [PATCH 364/366] oops redundant default value --- osu.Game/Graphics/Containers/SectionsContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 00c55bdd57..cd6d0a9432 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -202,7 +202,7 @@ namespace osu.Game.Graphics.Containers }); } - private int lastKnownChildrenCount = 0; + private int lastKnownChildrenCount; protected override void UpdateAfterChildren() { From 6bea744e345696926b0e0e4159b3796fa1cf6dbc Mon Sep 17 00:00:00 2001 From: Davran Dilshat Date: Mon, 23 Aug 2021 17:13:25 +0100 Subject: [PATCH 365/366] invalidate scroll position --- osu.Game/Graphics/Containers/SectionsContainer.cs | 8 +++----- osu.Game/Overlays/SettingsPanel.cs | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index cd6d0a9432..76492cab55 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -202,8 +202,6 @@ namespace osu.Game.Graphics.Containers }); } - private int lastKnownChildrenCount; - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -222,12 +220,10 @@ namespace osu.Game.Graphics.Containers } float currentScroll = scrollContainer.Current; - var presentChildren = Children.Where(c => c.IsPresent); - if (currentScroll != lastKnownScroll || presentChildren.Count() != lastKnownChildrenCount) + if (currentScroll != lastKnownScroll) { lastKnownScroll = currentScroll; - lastKnownChildrenCount = presentChildren.Count(); // reset last clicked section because user started scrolling themselves if (scrollContainer.UserScrolling) @@ -253,6 +249,8 @@ namespace osu.Game.Graphics.Containers float scrollCentre = fixedHeaderSize + scrollContainer.DisplayableContent * scroll_y_centre + selectionLenienceAboveSection; + var presentChildren = Children.Where(c => c.IsPresent); + if (lastClickedSection != null) SelectedSection.Value = lastClickedSection; else if (Precision.AlmostBigger(0, scrollContainer.Current)) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index e4e76592d8..5589786169 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -211,7 +211,7 @@ namespace osu.Game.Overlays loading.Hide(); - searchTextBox.Current.BindValueChanged(term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue, true); + searchTextBox.Current.BindValueChanged(term => SectionsContainer.SearchTerm = term.NewValue, true); searchTextBox.TakeFocus(); loadSidebarButtons(); From 9d807656f26e6bc3882d38630b83269da670c1ff Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 23 Aug 2021 21:08:59 +0300 Subject: [PATCH 366/366] Add more complete test coverage of decoupling --- .../Visual/Online/TestSceneRankingsOverlay.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index 342ae76377..027f17fff4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -7,6 +7,8 @@ using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Overlays.Rankings; using osu.Game.Rulesets.Catch; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Osu; using osu.Game.Users; namespace osu.Game.Tests.Visual.Online @@ -24,11 +26,20 @@ namespace osu.Game.Tests.Visual.Online public void SetUp() => Schedule(loadRankingsOverlay); [Test] - public void TestParentRulesetCopiedOnInitialShow() + public void TestParentRulesetDecoupledAfterInitialShow() { - AddStep("set ruleset", () => Ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("enable global ruleset", () => Ruleset.Disabled = false); + AddStep("set global ruleset to osu!catch", () => Ruleset.Value = new CatchRuleset().RulesetInfo); AddStep("reload rankings overlay", loadRankingsOverlay); - AddAssert("catch ruleset selected", () => Ruleset.Value.Equals(new CatchRuleset().RulesetInfo)); + AddAssert("rankings ruleset set to osu!catch", () => rankingsOverlay.Header.Ruleset.Value.ShortName == CatchRuleset.SHORT_NAME); + + AddStep("set global ruleset to osu!", () => Ruleset.Value = new OsuRuleset().RulesetInfo); + AddAssert("rankings ruleset still osu!catch", () => rankingsOverlay.Header.Ruleset.Value.ShortName == CatchRuleset.SHORT_NAME); + + AddStep("disable global ruleset", () => Ruleset.Disabled = true); + AddAssert("rankings ruleset still enabled", () => rankingsOverlay.Header.Ruleset.Disabled == false); + AddStep("set rankings ruleset to osu!mania", () => rankingsOverlay.Header.Ruleset.Value = new ManiaRuleset().RulesetInfo); + AddAssert("rankings ruleset set to osu!mania", () => rankingsOverlay.Header.Ruleset.Value.ShortName == ManiaRuleset.SHORT_NAME); } [Test]