From 2484ccd50c325ae9545f84e4ef3ecb9035a1d5d4 Mon Sep 17 00:00:00 2001 From: Robin Avery Date: Tue, 8 Jun 2021 11:49:25 -0400 Subject: [PATCH 01/69] Ensure scale x or y does not go below zero in SkinSelectionHandler.HandleScale --- osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 9cca0ba2c7..2d790eed5b 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -95,8 +95,8 @@ namespace osu.Game.Skinning.Editor // scale adjust applied to each individual item should match that of the quad itself. var scaledDelta = new Vector2( - adjustedRect.Width / selectionRect.Width, - adjustedRect.Height / selectionRect.Height + MathF.Max(adjustedRect.Width / selectionRect.Width, 0), + MathF.Max(adjustedRect.Height / selectionRect.Height, 0) ); foreach (var b in SelectedBlueprints) From ab977d91f0458c406c3b44db1fe21c664d3c4721 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 20:40:22 +0700 Subject: [PATCH 02/69] fix image test not load looks like forgot to change this after `CurrentPath` shenanigan --- .../Online/TestSceneWikiMarkdownContainer.cs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index b6dce2c398..ec43ee2be3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -102,7 +102,7 @@ needs_cleanup: true { AddStep("Add absolute image", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; + markdownContainer.CurrentPath = "https://dev.ppy.sh"; markdownContainer.Text = "![intro](/wiki/Interface/img/intro-screen.jpg)"; }); } @@ -112,8 +112,7 @@ needs_cleanup: true { AddStep("Add relative image", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; - markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/"; + markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/Interface/"; markdownContainer.Text = "![intro](img/intro-screen.jpg)"; }); } @@ -123,8 +122,7 @@ needs_cleanup: true { AddStep("Add paragraph with block image", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; - markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/"; + markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/Interface/"; markdownContainer.Text = @"Line before image ![play menu](img/play-menu.jpg ""Main Menu in osu!"") @@ -138,7 +136,7 @@ Line after image"; { AddStep("Add inline image", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; + markdownContainer.CurrentPath = "https://dev.ppy.sh"; markdownContainer.Text = "![osu! mode icon](/wiki/shared/mode/osu.png) osu!"; }); } @@ -148,7 +146,7 @@ Line after image"; { AddStep("Add Table", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; + markdownContainer.CurrentPath = "https://dev.ppy.sh"; markdownContainer.Text = @" | Image | Name | Effect | | :-: | :-: | :-- | @@ -166,11 +164,6 @@ Line after image"; { public LinkInline Link; - public new string DocumentUrl - { - set => base.DocumentUrl = value; - } - public override MarkdownTextFlowContainer CreateTextFlow() => new TestMarkdownTextFlowContainer { UrlAdded = link => Link = link, From 0e29ae037b8773ce4c88318ca6063998f2979c30 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 20:50:29 +0700 Subject: [PATCH 03/69] add wide image test --- .../Online/TestSceneWikiMarkdownContainer.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index ec43ee2be3..69caa2896b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -160,6 +160,20 @@ Line after image"; }); } + [Test] + public void TestWideImageNotExceedContainer() + { + AddStep("Add image", () => + { + markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/osu!_Program_Files/"; + markdownContainer.Text = "![](img/file_structure.jpg \"The file structure of osu!'s installation folder, on Windows and macOS\")"; + }); + AddStep("Change container width", () => + { + markdownContainer.Width = 0.5f; + }); + } + private class TestMarkdownContainer : WikiMarkdownContainer { public LinkInline Link; From 1c074ff0182c90f56b370d37f7511c942bedeaea Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 20:55:40 +0700 Subject: [PATCH 04/69] add `BlockMarkdownImage` change from AutoSize Both to AutoSize Y and RelativeSize X --- .../Wiki/Markdown/WikiMarkdownImageBlock.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 179762103a..fbc0b8ee67 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -32,11 +32,7 @@ namespace osu.Game.Overlays.Wiki.Markdown { Children = new Drawable[] { - new WikiMarkdownImage(linkInline) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }, + new BlockMarkdownImage(linkInline), parentTextComponent.CreateSpriteText().With(t => { t.Text = linkInline.Title; @@ -45,5 +41,15 @@ namespace osu.Game.Overlays.Wiki.Markdown }), }; } + + private class BlockMarkdownImage : WikiMarkdownImage + { + public BlockMarkdownImage(LinkInline linkInline) + : base(linkInline) + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + } + } } } From 2b8d41c0452e94cb9577f64771e08e9b18161f0c Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 21:04:56 +0700 Subject: [PATCH 05/69] add `BlockImageContainer` change from AutoSize Both to AutoSize Y and RelativeSize X --- .../Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index fbc0b8ee67..b321cf328e 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -50,6 +50,18 @@ namespace osu.Game.Overlays.Wiki.Markdown AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; } + + protected override ImageContainer CreateImageContainer(string url) => new BlockImageContainer(url); + + private class BlockImageContainer : ImageContainer + { + public BlockImageContainer(string url) + : base(url) + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + } + } } } } From e58f690210037ed9ddcfa3c3651fc3910442f7fa Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 21:09:00 +0700 Subject: [PATCH 06/69] centering image sprite --- osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index b321cf328e..8d2eca9d5d 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Sprites; using osuTK; namespace osu.Game.Overlays.Wiki.Markdown @@ -61,6 +62,12 @@ namespace osu.Game.Overlays.Wiki.Markdown AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; } + + protected override Sprite CreateSpriteImage() => base.CreateSpriteImage().With(s => + { + s.Anchor = Anchor.TopCentre; + s.Origin = Anchor.TopCentre; + }); } } } From 006cc331c8991e28fefae250824249bf3f0d569b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 18:51:43 +0300 Subject: [PATCH 07/69] Separate `IMutateApproachCircles` to requiring and hiding --- ...teApproachCircles.cs => IHidesApproachCircles.cs} | 4 ++-- .../Mods/IRequiresApproachCircles.cs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) rename osu.Game.Rulesets.Osu/Mods/{IMutateApproachCircles.cs => IHidesApproachCircles.cs} (57%) create mode 100644 osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs diff --git a/osu.Game.Rulesets.Osu/Mods/IMutateApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs similarity index 57% rename from osu.Game.Rulesets.Osu/Mods/IMutateApproachCircles.cs rename to osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs index 60a5825241..07ca93126d 100644 --- a/osu.Game.Rulesets.Osu/Mods/IMutateApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs @@ -4,9 +4,9 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Any mod which affects the animation or visibility of approach circles. Should be used for incompatibility purposes. + /// Any mod which completely hides the approach circles. Used for incompatibility with . /// - public interface IMutateApproachCircles + public interface IHidesApproachCircles { } } diff --git a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs new file mode 100644 index 0000000000..f2bd836835 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Osu.Mods +{ + /// + /// Any mod which requires the approach circles to be visible. Used for incompatibility with . + /// + public interface IRequiresApproachCircles + { + } +} From 6a67a6736a5c248efbeab3e2b151838069950038 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 18:52:39 +0300 Subject: [PATCH 08/69] Mark `IRequireApproachCircles` mods as incompatible with `IHidesApproachCircles` --- osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs index 526e29ad53..d832411104 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModApproachDifferent : Mod, IApplicableToDrawableHitObject, IMutateApproachCircles + public class OsuModApproachDifferent : Mod, IApplicableToDrawableHitObject, IRequiresApproachCircles { public override string Name => "Approach Different"; public override string Acronym => "AD"; @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; public override IconUsage? Icon { get; } = FontAwesome.Regular.Circle; - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IHidesApproachCircles) }; [SettingSource("Initial size", "Change the initial size of the approach circle, relative to hit circles.", 0)] public BindableFloat Scale { get; } = new BindableFloat(4) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 84263221a7..a05e4dea03 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Osu.Skinning.Default; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModTraceable : ModWithVisibilityAdjustment, IMutateApproachCircles + public class OsuModTraceable : ModWithVisibilityAdjustment, IRequiresApproachCircles { public override string Name => "Traceable"; public override string Acronym => "TC"; @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IHidesApproachCircles) }; protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { From baf736026b1e58578ee10f3fb269ade776a3c35e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 18:54:21 +0300 Subject: [PATCH 09/69] Mark `IHidesApproachCircles` mods as incompatible with `IRequiresApproachCircles` --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 16b38cd0b1..ee591465cd 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -15,12 +15,12 @@ using osu.Game.Rulesets.Osu.Skinning; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModHidden : ModHidden, IMutateApproachCircles + public class OsuModHidden : ModHidden, IHidesApproachCircles { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs index 6dfabed0df..9aafb02fa2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Mods /// /// Adjusts the size of hit objects during their fade in animation. /// - public abstract class OsuModObjectScaleTween : ModWithVisibilityAdjustment, IMutateApproachCircles + public abstract class OsuModObjectScaleTween : ModWithVisibilityAdjustment, IHidesApproachCircles { public override ModType Type => ModType.Fun; @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods protected virtual float EndScale => 1; - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index d3ca2973f0..1854c20aef 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModSpinIn : ModWithVisibilityAdjustment, IMutateApproachCircles + public class OsuModSpinIn : ModWithVisibilityAdjustment, IHidesApproachCircles { public override string Name => "Spin In"; public override string Acronym => "SI"; @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; // todo: this mod should be able to be compatible with hidden with a bit of further implementation. - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; private const int rotate_offset = 360; private const float rotate_starting_width = 2; From 69dac018c7c7b7a62dc3aeb08fa08e4956c39051 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 18:55:24 +0300 Subject: [PATCH 10/69] Make `OsuModSpinIn` as incompatible with other `IHidesApproachCircles` mods Respecting the TODO comment above it, mark `OsuModSpinIn` as incompatible with other `IHidesApproachCircles` mods as well. --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index ee591465cd..9c7784a00a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; - public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModSpinIn) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs index 9aafb02fa2..778447e444 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods protected virtual float EndScale => 1; - public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModSpinIn) }; protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 1854c20aef..47a771c2f1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; // todo: this mod should be able to be compatible with hidden with a bit of further implementation. - public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(IHidesApproachCircles) }; private const int rotate_offset = 360; private const float rotate_starting_width = 2; From d88d2644918bba27389c2e6ea5308ab965c2f736 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 29 Jun 2021 09:49:45 +0700 Subject: [PATCH 11/69] prevent image sprite exceed its parent width --- .../Wiki/Markdown/WikiMarkdownImageBlock.cs | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 8d2eca9d5d..4b0490d034 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -63,11 +63,28 @@ namespace osu.Game.Overlays.Wiki.Markdown RelativeSizeAxes = Axes.X; } - protected override Sprite CreateSpriteImage() => base.CreateSpriteImage().With(s => + protected override Sprite CreateSpriteImage() => new ImageSprite(); + + private class ImageSprite : Sprite { - s.Anchor = Anchor.TopCentre; - s.Origin = Anchor.TopCentre; - }); + public ImageSprite() + { + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + } + + protected override void Update() + { + base.Update(); + + if (Width > Parent.DrawWidth) + { + float ratio = Height / Width; + Width = Parent.DrawWidth; + Height = ratio * Width; + } + } + } } } } From a1fe9df378d88cd5edca44331fb867c59f35d94d Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 29 Jun 2021 10:14:51 +0700 Subject: [PATCH 12/69] add test to check sprite image width --- .../Visual/Online/TestSceneWikiMarkdownContainer.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index 69caa2896b..af2e4fc91a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using Markdig.Syntax.Inlines; using NUnit.Framework; using osu.Framework.Allocation; @@ -9,6 +10,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Graphics.Containers.Markdown; using osu.Game.Overlays; using osu.Game.Overlays.Wiki.Markdown; @@ -168,10 +172,19 @@ Line after image"; markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/osu!_Program_Files/"; markdownContainer.Text = "![](img/file_structure.jpg \"The file structure of osu!'s installation folder, on Windows and macOS\")"; }); + + AddUntilStep("Wait image to load", () => markdownContainer.ChildrenOfType().First().DelayedLoadCompleted); + AddStep("Change container width", () => { markdownContainer.Width = 0.5f; }); + + AddAssert("Image not exceed container width", () => + { + var spriteImage = markdownContainer.ChildrenOfType().First(); + return Precision.DefinitelyBigger(markdownContainer.DrawWidth, spriteImage.DrawWidth); + }); } private class TestMarkdownContainer : WikiMarkdownContainer From 7997d570308d39ea6c3e1c95beba03c59f119976 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 29 Jun 2021 11:25:35 +0300 Subject: [PATCH 13/69] Mention interfaces being "markers" for the time being --- osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs | 2 +- osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs index 07ca93126d..fe0abc453d 100644 --- a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs @@ -4,7 +4,7 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Any mod which completely hides the approach circles. Used for incompatibility with . + /// Marker interface for any mod which completely hides the approach circles. Used for incompatibility with . /// public interface IHidesApproachCircles { diff --git a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs index f2bd836835..3220ebf378 100644 --- a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs @@ -4,7 +4,7 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Any mod which requires the approach circles to be visible. Used for incompatibility with . + /// Marker interface for any mod which requires the approach circles to be visible. Used for incompatibility with . /// public interface IRequiresApproachCircles { From dbe3150f88465c25dbba23c2111e97968e50b26a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 29 Jun 2021 11:37:03 +0300 Subject: [PATCH 14/69] Mention about marker interfaces even more explicitly --- osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs | 6 +++++- osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs index fe0abc453d..4a3b187e83 100644 --- a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs @@ -4,8 +4,12 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Marker interface for any mod which completely hides the approach circles. Used for incompatibility with . + /// Marker interface for any mod which completely hides the approach circles. + /// Used for incompatibility with . /// + /// + /// Note that this is only a marker interface for incompatibility purposes, it does not change any gameplay behaviour. + /// public interface IHidesApproachCircles { } diff --git a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs index 3220ebf378..1458abfe05 100644 --- a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs @@ -4,8 +4,12 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Marker interface for any mod which requires the approach circles to be visible. Used for incompatibility with . + /// Marker interface for any mod which requires the approach circles to be visible. + /// Used for incompatibility with . /// + /// + /// Note that this is only a marker interface for incompatibility purposes, it does not change any gameplay behaviour. + /// public interface IRequiresApproachCircles { } From 3a002e357a63caa42578c39c8cf6cf8082c43cb9 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 29 Jun 2021 19:28:21 +0700 Subject: [PATCH 15/69] rename method --- osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 4b0490d034..1a4f6087c7 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -63,7 +63,7 @@ namespace osu.Game.Overlays.Wiki.Markdown RelativeSizeAxes = Axes.X; } - protected override Sprite CreateSpriteImage() => new ImageSprite(); + protected override Sprite CreateImageSprite() => new ImageSprite(); private class ImageSprite : Sprite { From e3344c33ea27d2269d60e06aaab6933f10763e1b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 30 Jun 2021 09:57:15 +0300 Subject: [PATCH 16/69] Better convey reason of "Spin In" incompatibility with "Hidden" --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 47a771c2f1..7b2a0c6e0f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -21,8 +21,9 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Circles spin in. No approach circles."; public override double ScoreMultiplier => 1; - // todo: this mod should be able to be compatible with hidden with a bit of further implementation. - public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(IHidesApproachCircles) }; + // todo: this mod needs to be incompatible with "hidden" due to forcing the circle to remain opaque, + // further implementation will be required for supporting that. + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModObjectScaleTween), typeof(OsuModHidden) }; private const int rotate_offset = 360; private const float rotate_starting_width = 2; @@ -49,10 +50,6 @@ namespace osu.Game.Rulesets.Osu.Mods circle.RotateTo(rotate_offset).Then().RotateTo(0, h.TimePreempt, Easing.InOutSine); circle.ScaleTo(new Vector2(rotate_starting_width, 0)).Then().ScaleTo(1, h.TimePreempt, Easing.InOutSine); - - // bypass fade in. - if (state == ArmedState.Idle) - circle.FadeIn(); } break; From 4b56d94a9806b11e9017ed919cf05cf5a8620c08 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 30 Jun 2021 10:26:27 +0300 Subject: [PATCH 17/69] Revert accidentally pushed part of change --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 7b2a0c6e0f..56c246953e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -50,6 +50,10 @@ namespace osu.Game.Rulesets.Osu.Mods circle.RotateTo(rotate_offset).Then().RotateTo(0, h.TimePreempt, Easing.InOutSine); circle.ScaleTo(new Vector2(rotate_starting_width, 0)).Then().ScaleTo(1, h.TimePreempt, Easing.InOutSine); + + // bypass fade in. + if (state == ArmedState.Idle) + circle.FadeIn(); } break; From 4a54e7cdb83db4eb7f86d9af3f2e077d7668088f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Jun 2021 18:30:12 +0900 Subject: [PATCH 18/69] Add tests covering score preparation flow --- .../TestScenePlayerScorePreparation.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs new file mode 100644 index 0000000000..8ea5f3f9ee --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.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.Threading.Tasks; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Rulesets; +using osu.Game.Scoring; +using osu.Game.Screens.Ranking; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestScenePlayerScorePreparation : OsuPlayerTestScene + { + protected override bool AllowFail => false; + + protected new PreparingPlayer Player => (PreparingPlayer)base.Player; + + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + // Ensure track has actually running before attempting to seek + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + } + + [Test] + public void TestPreparationOnResults() + { + AddUntilStep("wait for preparation", () => Player.PreparationCompleted); + } + + [Test] + public void TestPreparationOnExit() + { + AddStep("exit", () => Player.Exit()); + AddUntilStep("wait for preparation", () => Player.PreparationCompleted); + } + + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PreparingPlayer(); + + public class PreparingPlayer : TestPlayer + { + public bool PreparationCompleted { get; private set; } + + public bool ResultsCreated { get; private set; } + + public PreparingPlayer() + : base(true, true) + { + } + + protected override ResultsScreen CreateResults(ScoreInfo score) + { + var results = base.CreateResults(score); + ResultsCreated = true; + return results; + } + + protected override Task PrepareScoreForResultsAsync(Score score) + { + PreparationCompleted = true; + return base.PrepareScoreForResultsAsync(score); + } + } + } +} From 00d3baef1191f67dc062ee5205804372e1bf4ca5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Jun 2021 20:23:48 +0900 Subject: [PATCH 19/69] Exit handling flow --- osu.Game/Screens/Play/SubmittingPlayer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index b843915a7c..2ee116a6a3 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -102,6 +102,11 @@ namespace osu.Game.Screens.Play /// Whether gameplay should be immediately exited as a result. Returning false allows the gameplay session to continue. Defaults to true. protected virtual bool HandleTokenRetrievalFailure(Exception exception) => true; + public override bool OnExiting(IScreen next) + { + return base.OnExiting(next); + } + protected override async Task PrepareScoreForResultsAsync(Score score) { await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false); From 285c49be7ec8ac465081d91294bada9b83ba97d0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 30 Jun 2021 20:28:27 +0200 Subject: [PATCH 20/69] Localise dashboard overlay header. --- .../Dashboard/DashboardOverlayHeader.cs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 3314ed957a..ce4ec27225 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard { @@ -13,13 +16,14 @@ namespace osu.Game.Overlays.Dashboard { public DashboardTitle() { - Title = "dashboard"; + Title = HomeStrings.UserTitle; Description = "view your friends and other information"; IconTexture = "Icons/Hexacons/social"; } } } + [LocalisableEnum(typeof(DashboardOverlayTabsEnumLocalisationMapper))] public enum DashboardOverlayTabs { Friends, @@ -27,4 +31,22 @@ namespace osu.Game.Overlays.Dashboard [Description("Currently Playing")] CurrentlyPlaying } + + public class DashboardOverlayTabsEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(DashboardOverlayTabs value) + { + switch (value) + { + case DashboardOverlayTabs.Friends: + return FriendsStrings.TitleCompact; + + case DashboardOverlayTabs.CurrentlyPlaying: + return @"Currently Playing"; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } From f2287ba0224badf454d491370d3ad49a894eeecf Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 30 Jun 2021 21:16:21 +0200 Subject: [PATCH 21/69] Localise friends online status stream control. --- .../Changelog/ChangelogUpdateStreamItem.cs | 7 ++--- .../Friends/FriendsOnlineStatusItem.cs | 6 +++-- .../Dashboard/Friends/OnlineStatus.cs | 26 +++++++++++++++++++ osu.Game/Overlays/OverlayStreamItem.cs | 7 ++--- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs index f8e1ac0c84..cb144defbf 100644 --- a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs +++ b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using Humanizer; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using osuTK.Graphics; @@ -17,11 +18,11 @@ namespace osu.Game.Overlays.Changelog Width *= 2; } - protected override string MainText => Value.DisplayName; + protected override LocalisableString MainText => Value.DisplayName; - protected override string AdditionalText => Value.LatestBuild.DisplayVersion; + protected override LocalisableString AdditionalText => Value.LatestBuild.DisplayVersion; - protected override string InfoText => Value.LatestBuild.Users > 0 ? $"{"user".ToQuantity(Value.LatestBuild.Users, "N0")} online" : null; + protected override LocalisableString InfoText => Value.LatestBuild.Users > 0 ? $"{"user".ToQuantity(Value.LatestBuild.Users, "N0")} online" : null; protected override Color4 GetBarColour(OsuColour colours) => Value.Colour; } diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs index 7e902203f8..11dcb93e6f 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Extensions; +using osu.Framework.Localisation; using osu.Game.Graphics; using osuTK.Graphics; @@ -14,9 +16,9 @@ namespace osu.Game.Overlays.Dashboard.Friends { } - protected override string MainText => Value.Status.ToString(); + protected override LocalisableString MainText => Value.Status.GetLocalisableDescription(); - protected override string AdditionalText => Value.Count.ToString(); + protected override LocalisableString AdditionalText => Value.Count.ToString(); protected override Color4 GetBarColour(OsuColour colours) { diff --git a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs index 6f2f55a6ed..4b5a7ef066 100644 --- a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs +++ b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs @@ -1,12 +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; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; + namespace osu.Game.Overlays.Dashboard.Friends { + [LocalisableEnum(typeof(OnlineStatusEnumLocalisationMapper))] public enum OnlineStatus { All, Online, Offline } + + public class OnlineStatusEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(OnlineStatus value) + { + switch (value) + { + case OnlineStatus.All: + return SortStrings.All; + + case OnlineStatus.Online: + return UsersStrings.StatusOnline; + + case OnlineStatus.Offline: + return UsersStrings.StatusOffline; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } diff --git a/osu.Game/Overlays/OverlayStreamItem.cs b/osu.Game/Overlays/OverlayStreamItem.cs index cd1391a3d8..56502ff70f 100644 --- a/osu.Game/Overlays/OverlayStreamItem.cs +++ b/osu.Game/Overlays/OverlayStreamItem.cs @@ -12,6 +12,7 @@ using osu.Framework.Allocation; using osu.Game.Graphics.Sprites; using osu.Game.Graphics; using osuTK.Graphics; +using osu.Framework.Localisation; namespace osu.Game.Overlays { @@ -88,11 +89,11 @@ namespace osu.Game.Overlays SelectedItem.BindValueChanged(_ => updateState(), true); } - protected abstract string MainText { get; } + protected abstract LocalisableString MainText { get; } - protected abstract string AdditionalText { get; } + protected abstract LocalisableString AdditionalText { get; } - protected virtual string InfoText => string.Empty; + protected virtual LocalisableString InfoText => string.Empty; protected abstract Color4 GetBarColour(OsuColour colours); From 8da6ecf6a9dd40ee211d349dd9dba6f64e1a6501 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 30 Jun 2021 21:28:07 +0200 Subject: [PATCH 22/69] Localise OverlayPanelDisplayStyle tab control. --- .../Dashboard/Friends/UserSortTabControl.cs | 25 +++++++++++++++++ .../OverlayPanelDisplayStyleControl.cs | 27 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs index 3a5f65212d..dc756e2957 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard.Friends { @@ -9,6 +12,7 @@ namespace osu.Game.Overlays.Dashboard.Friends { } + [LocalisableEnum(typeof(UserSortCriteriaEnumLocalisationMappper))] public enum UserSortCriteria { [Description(@"Recently Active")] @@ -16,4 +20,25 @@ namespace osu.Game.Overlays.Dashboard.Friends Rank, Username } + + public class UserSortCriteriaEnumLocalisationMappper : EnumLocalisationMapper + { + public override LocalisableString Map(UserSortCriteria value) + { + switch (value) + { + case UserSortCriteria.LastVisit: + return SortStrings.LastVisit; + + case UserSortCriteria.Rank: + return SortStrings.Rank; + + case UserSortCriteria.Username: + return SortStrings.Username; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } diff --git a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs index 0ece96b56c..c2268ff43c 100644 --- a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs +++ b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs @@ -12,6 +12,9 @@ using osu.Framework.Allocation; using osuTK.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; +using System; +using osu.Game.Resources.Localisation.Web; +using osu.Framework.Extensions; namespace osu.Game.Overlays { @@ -57,7 +60,7 @@ namespace osu.Game.Overlays [Resolved] private OverlayColourProvider colourProvider { get; set; } - public LocalisableString TooltipText => $@"{Value} view"; + public LocalisableString TooltipText => Value.GetLocalisableDescription(); private readonly SpriteIcon icon; @@ -98,10 +101,32 @@ namespace osu.Game.Overlays } } + [LocalisableEnum(typeof(OverlayPanelDisplayStyleEnumLocalisationMapper))] public enum OverlayPanelDisplayStyle { Card, List, Brick } + + public class OverlayPanelDisplayStyleEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(OverlayPanelDisplayStyle value) + { + switch (value) + { + case OverlayPanelDisplayStyle.Card: + return UsersStrings.ViewModeCard; + + case OverlayPanelDisplayStyle.List: + return UsersStrings.ViewModeList; + + case OverlayPanelDisplayStyle.Brick: + return UsersStrings.ViewModeBrick; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } From 939b2baafecde49976175bd30f977618ef52c1e5 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 30 Jun 2021 22:19:04 +0200 Subject: [PATCH 23/69] Localise overlay "Scroll to top" button. --- osu.Game/Overlays/OverlayScrollContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index c5b4cc3645..ca5fc90027 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -118,7 +119,7 @@ namespace osu.Game.Overlays } }); - TooltipText = "Scroll to top"; + TooltipText = CommonStrings.ButtonsBackToTop; } [BackgroundDependencyLoader] From 583242d96d343bb342f524e3bc0275d111d945af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Jun 2021 13:05:26 +0200 Subject: [PATCH 24/69] Add osu!-styled colour picker control --- .../UserInterface/TestSceneColourPicker.cs | 82 +++++++++++++ .../UserInterfaceV2/OsuColourPicker.cs | 19 +++ .../UserInterfaceV2/OsuHSVColourPicker.cs | 109 ++++++++++++++++++ .../UserInterfaceV2/OsuHexColourPicker.cs | 57 +++++++++ 4 files changed, 267 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs create mode 100644 osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs create mode 100644 osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs create mode 100644 osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs new file mode 100644 index 0000000000..634e45e7a9 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.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. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneColourPicker : OsuTestScene + { + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create pickers", () => Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension() + }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = @"No OverlayColourProvider", + Font = OsuFont.Default.With(size: 40) + }, + new OsuColourPicker + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + } + }, + new ColourProvidingContainer(OverlayColourScheme.Blue) + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = @"With blue OverlayColourProvider", + Font = OsuFont.Default.With(size: 40) + }, + new OsuColourPicker + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + } + } + } + } + }); + } + + private class ColourProvidingContainer : Container + { + [Cached] + private OverlayColourProvider provider { get; } + + public ColourProvidingContainer(OverlayColourScheme colourScheme) + { + provider = new OverlayColourProvider(colourScheme); + } + } + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs new file mode 100644 index 0000000000..5394e5d0aa --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.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.Graphics.UserInterface; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public class OsuColourPicker : ColourPicker + { + public OsuColourPicker() + { + CornerRadius = 10; + Masking = true; + } + + protected override HSVColourPicker CreateHSVColourPicker() => new OsuHSVColourPicker(); + protected override HexColourPicker CreateHexColourPicker() => new OsuHexColourPicker(); + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs new file mode 100644 index 0000000000..2a399cfaf8 --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -0,0 +1,109 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Overlays; +using osuTK; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public class OsuHSVColourPicker : HSVColourPicker + { + protected override HueSelector CreateHueSelector() => new OsuHueSelector(); + protected override SaturationValueSelector CreateSaturationValueSelector() => new OsuSaturationValueSelector(); + + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour osuColour) + { + Background.Colour = colourProvider?.Dark5 ?? osuColour.GreySeafoamDark; + + Content.Padding = new MarginPadding(10); + Content.Spacing = new Vector2(0, 10); + } + + private class OsuHueSelector : HueSelector + { + public OsuHueSelector() + { + Margin = new MarginPadding + { + Bottom = 15 + }; + + SliderBar.CornerRadius = SliderBar.Height / 2; + SliderBar.Masking = true; + } + + protected override Drawable CreateSliderNub() => new SliderNub(); + + private class SliderNub : CompositeDrawable + { + public SliderNub() + { + InternalChild = new Triangle + { + Width = 20, + Height = 15, + Anchor = Anchor.BottomCentre, + Origin = Anchor.TopCentre + }; + } + } + } + + private class OsuSaturationValueSelector : SaturationValueSelector + { + public OsuSaturationValueSelector() + { + SelectionArea.CornerRadius = 10; + SelectionArea.Masking = true; + // purposefully use hard non-AA'd masking to avoid edge artifacts. + SelectionArea.MaskingSmoothness = 0; + } + + protected override Marker CreateMarker() => new OsuMarker(); + + private class OsuMarker : Marker + { + private readonly Box previewBox; + + public OsuMarker() + { + AutoSizeAxes = Axes.Both; + + InternalChild = new CircularContainer + { + Size = new Vector2(20), + Masking = true, + BorderColour = Colour4.White, + BorderThickness = 3, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0, 1), + Radius = 3, + Colour = Colour4.Black.Opacity(0.3f) + }, + Child = previewBox = new Box + { + RelativeSizeAxes = Axes.Both + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(colour => previewBox.Colour = colour.NewValue, true); + } + } + } + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs new file mode 100644 index 0000000000..331a1b67c9 --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs @@ -0,0 +1,57 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public class OsuHexColourPicker : HexColourPicker + { + public OsuHexColourPicker() + { + Padding = new MarginPadding(20); + Spacing = 20; + } + + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] OverlayColourProvider overlayColourProvider, OsuColour osuColour) + { + Background.Colour = overlayColourProvider?.Dark6 ?? osuColour.GreySeafoamDarker; + } + + protected override TextBox CreateHexCodeTextBox() => new OsuTextBox(); + protected override ColourPreview CreateColourPreview() => new OsuColourPreview(); + + private class OsuColourPreview : ColourPreview + { + private readonly Box preview; + + public OsuColourPreview() + { + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = preview = new Box + { + RelativeSizeAxes = Axes.Both + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(colour => preview.Colour = colour.NewValue, true); + } + } + } +} From 30a7b034be65e7c7c83ad85518004cd3372d0583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 1 Jul 2021 00:30:43 +0200 Subject: [PATCH 25/69] Add HSV abbreviation to team-shared collection --- osu.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 62751cebb1..d2c5b1223c 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -308,6 +308,7 @@ GL GLSL HID + HSV HTML HUD ID From 719852435f1bc52381f6e4e6ca03e97b6e05460e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 15:10:19 +0900 Subject: [PATCH 26/69] Fix intermittent `PerformFromScreen` test failures due to incorrect screen sequence These tests were manually pushing the `PlayerLoader` / `Player` instances to `SongSelect`, which bypasses safeties in place which avoid the exact issue that came up in https://github.com/ppy/osu/runs/2951759236 (see `AllowSelection` flag specifically). --- .../Visual/Navigation/TestScenePerformFromScreen.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs index 3cedaf9d45..92152bce18 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs @@ -11,6 +11,7 @@ using osu.Game.Overlays; using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps.IO; using osuTK.Input; using static osu.Game.Tests.Visual.Navigation.TestSceneScreenNavigation; @@ -57,8 +58,11 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestPerformAtSongSelectFromPlayerLoader() { + AddStep("import beatmap", () => ImportBeatmapTest.LoadQuickOszIntoOsu(Game).Wait()); PushAndConfirm(() => new TestPlaySongSelect()); - PushAndConfirm(() => new PlayerLoader(() => new SoloPlayer())); + + AddStep("Press enter", () => InputManager.Key(Key.Enter)); + AddUntilStep("Wait for new screen", () => Game.ScreenStack.CurrentScreen is PlayerLoader); AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(TestPlaySongSelect) })); AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is TestPlaySongSelect); @@ -68,8 +72,11 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestPerformAtMenuFromPlayerLoader() { + AddStep("import beatmap", () => ImportBeatmapTest.LoadQuickOszIntoOsu(Game).Wait()); PushAndConfirm(() => new TestPlaySongSelect()); - PushAndConfirm(() => new PlayerLoader(() => new SoloPlayer())); + + AddStep("Press enter", () => InputManager.Key(Key.Enter)); + AddUntilStep("Wait for new screen", () => Game.ScreenStack.CurrentScreen is PlayerLoader); AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true)); AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is MainMenu); From 5bc970af0d5d26f655391ed43275e9869dbc15c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 16:55:33 +0900 Subject: [PATCH 27/69] Make `TestPlayer` inherit from `SoloPlayer` for more flexibility in testing --- osu.Game/Screens/Play/SoloPlayer.cs | 10 ++++++++++ osu.Game/Tests/Visual/TestPlayer.cs | 23 ++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index d0ef4131dc..0099b4c87c 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -12,6 +12,16 @@ namespace osu.Game.Screens.Play { public class SoloPlayer : SubmittingPlayer { + public SoloPlayer() + : this(null) + { + } + + protected SoloPlayer(PlayerConfiguration configuration = null) + : base(configuration) + { + } + protected override APIRequest CreateTokenRequest() { if (!(Beatmap.Value.BeatmapInfo.OnlineBeatmapID is int beatmapId)) diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index 09da4db952..52eb06bdc6 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -1,14 +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 System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Game.Online.API; +using osu.Game.Online.Rooms; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual @@ -16,7 +20,7 @@ namespace osu.Game.Tests.Visual /// /// A player that exposes many components that would otherwise not be available, for testing purposes. /// - public class TestPlayer : Player + public class TestPlayer : SoloPlayer { protected override bool PauseOnFocusLost { get; } @@ -35,6 +39,9 @@ namespace osu.Game.Tests.Visual public new HealthProcessor HealthProcessor => base.HealthProcessor; + public bool TokenCreationRequested { get; private set; } + public bool SubmissionRequested { get; private set; } + public new bool PauseCooldownActive => base.PauseCooldownActive; public readonly List Results = new List(); @@ -49,6 +56,20 @@ namespace osu.Game.Tests.Visual PauseOnFocusLost = pauseOnFocusLost; } + protected override bool HandleTokenRetrievalFailure(Exception exception) => false; + + protected override APIRequest CreateTokenRequest() + { + TokenCreationRequested = true; + return base.CreateTokenRequest(); + } + + protected override APIRequest CreateSubmissionRequest(Score score, long token) + { + SubmissionRequested = true; + return base.CreateSubmissionRequest(score, token); + } + protected override void PrepareReplay() { // Generally, replay generation is handled by whatever is constructing the player. From 397d2491b3e2b1f74b99bab0549c17ba96a2664d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 16:55:44 +0900 Subject: [PATCH 28/69] Update test scenes to actually cover submission logic --- .../TestScenePlayerScorePreparation.cs | 69 ----------------- .../TestScenePlayerScoreSubmission.cs | 74 +++++++++++++++++++ 2 files changed, 74 insertions(+), 69 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs create mode 100644 osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs deleted file mode 100644 index 8ea5f3f9ee..0000000000 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs +++ /dev/null @@ -1,69 +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.Threading.Tasks; -using NUnit.Framework; -using osu.Framework.Screens; -using osu.Framework.Testing; -using osu.Game.Rulesets; -using osu.Game.Scoring; -using osu.Game.Screens.Ranking; - -namespace osu.Game.Tests.Visual.Gameplay -{ - public class TestScenePlayerScorePreparation : OsuPlayerTestScene - { - protected override bool AllowFail => false; - - protected new PreparingPlayer Player => (PreparingPlayer)base.Player; - - [SetUpSteps] - public override void SetUpSteps() - { - base.SetUpSteps(); - - // Ensure track has actually running before attempting to seek - AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); - } - - [Test] - public void TestPreparationOnResults() - { - AddUntilStep("wait for preparation", () => Player.PreparationCompleted); - } - - [Test] - public void TestPreparationOnExit() - { - AddStep("exit", () => Player.Exit()); - AddUntilStep("wait for preparation", () => Player.PreparationCompleted); - } - - protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PreparingPlayer(); - - public class PreparingPlayer : TestPlayer - { - public bool PreparationCompleted { get; private set; } - - public bool ResultsCreated { get; private set; } - - public PreparingPlayer() - : base(true, true) - { - } - - protected override ResultsScreen CreateResults(ScoreInfo score) - { - var results = base.CreateResults(score); - ResultsCreated = true; - return results; - } - - protected override Task PrepareScoreForResultsAsync(Score score) - { - PreparationCompleted = true; - return base.PrepareScoreForResultsAsync(score); - } - } - } -} diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs new file mode 100644 index 0000000000..24f8227148 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.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 System.Linq; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Online.API; +using osu.Game.Online.Rooms; +using osu.Game.Online.Solo; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Screens.Ranking; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestScenePlayerScoreSubmission : OsuPlayerTestScene + { + protected override bool AllowFail => false; + + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + + protected override TestPlayer CreatePlayer(Ruleset ruleset) + { + SelectedMods.Value = new[] { ruleset.GetAllMods().OfType().First() }; + return new TestPlayer(false); + } + + [SetUpSteps] + public override void SetUpSteps() + { + AddStep("Prepare test API", () => + { + dummyAPI.HandleRequest = request => + { + switch (request) + { + case CreateSoloScoreRequest tokenRequest: + tokenRequest.TriggerSuccess(new APIScoreToken { ID = 1234 }); + return true; + } + + return false; + }; + }); + + base.SetUpSteps(); + + // Ensure track has actually running before attempting to seek + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + } + + [Test] + public void TestSubmissionOnResults() + { + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + + AddUntilStep("wait for submission", () => Player.SubmissionRequested); + } + + [Test] + public void TestSubmissionOnExit() + { + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + AddStep("exit", () => Player.Exit()); + AddUntilStep("wait for submission", () => Player.SubmissionRequested); + } + } +} From 04b874bb009a85b67c5783f30aa4a6f2bfb6862a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:02:33 +0900 Subject: [PATCH 29/69] Add flow for submitting score on exiting `SubmittingPlayer` --- osu.Game/Screens/Play/SubmittingPlayer.cs | 60 ++++++++++++++--------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index 2ee116a6a3..bbb6a21f39 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -27,6 +27,8 @@ namespace osu.Game.Screens.Play [Resolved] private IAPIProvider api { get; set; } + private TaskCompletionSource scoreSubmissionSource; + protected SubmittingPlayer(PlayerConfiguration configuration = null) : base(configuration) { @@ -102,36 +104,18 @@ namespace osu.Game.Screens.Play /// Whether gameplay should be immediately exited as a result. Returning false allows the gameplay session to continue. Defaults to true. protected virtual bool HandleTokenRetrievalFailure(Exception exception) => true; - public override bool OnExiting(IScreen next) - { - return base.OnExiting(next); - } - protected override async Task PrepareScoreForResultsAsync(Score score) { await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false); - // token may be null if the request failed but gameplay was still allowed (see HandleTokenRetrievalFailure). - if (token == null) - return; + await submitScore(score).ConfigureAwait(false); + } - var tcs = new TaskCompletionSource(); - var request = CreateSubmissionRequest(score, token.Value); + public override bool OnExiting(IScreen next) + { + submitScore(Score); - request.Success += s => - { - score.ScoreInfo.OnlineScoreID = s.ID; - tcs.SetResult(true); - }; - - request.Failure += e => - { - Logger.Error(e, "Failed to submit score"); - tcs.SetResult(false); - }; - - api.Queue(request); - await tcs.Task.ConfigureAwait(false); + return base.OnExiting(next); } /// @@ -148,5 +132,33 @@ namespace osu.Game.Screens.Play /// The score to be submitted. /// The submission token. protected abstract APIRequest CreateSubmissionRequest(Score score, long token); + + private Task submitScore(Score score) + { + // token may be null if the request failed but gameplay was still allowed (see HandleTokenRetrievalFailure). + if (token == null) + return Task.CompletedTask; + + if (scoreSubmissionSource != null) + return scoreSubmissionSource.Task; + + scoreSubmissionSource = new TaskCompletionSource(); + var request = CreateSubmissionRequest(score, token.Value); + + request.Success += s => + { + score.ScoreInfo.OnlineScoreID = s.ID; + scoreSubmissionSource.SetResult(true); + }; + + request.Failure += e => + { + Logger.Error(e, "Failed to submit score"); + scoreSubmissionSource.SetResult(false); + }; + + api.Queue(request); + return scoreSubmissionSource.Task; + } } } From 6e8d4e382ebf3597181cee171b20ed175dab9fc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:20:40 +0900 Subject: [PATCH 30/69] Add test coverage of token failure scenarios --- .../TestScenePlayerScoreSubmission.cs | 96 +++++++++++++------ 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 24f8227148..4088fc855d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -1,10 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using NUnit.Framework; using osu.Framework.Screens; -using osu.Framework.Testing; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Online.Solo; @@ -21,14 +21,74 @@ namespace osu.Game.Tests.Visual.Gameplay private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + protected override bool HasCustomSteps => true; + protected override TestPlayer CreatePlayer(Ruleset ruleset) { SelectedMods.Value = new[] { ruleset.GetAllMods().OfType().First() }; return new TestPlayer(false); } - [SetUpSteps] - public override void SetUpSteps() + [Test] + public void TestNoSubmissionOnResultsWithNoToken() + { + prepareTokenResponse(false); + + CreateTest(() => { }); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + + AddAssert("ensure no submission", () => !Player.SubmissionRequested); + } + + [Test] + public void TestSubmissionOnResults() + { + prepareTokenResponse(true); + + CreateTest(() => { }); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + + AddAssert("ensure submission", () => Player.SubmissionRequested); + } + + [Test] + public void TestNoSubmissionOnExitWithNoToken() + { + prepareTokenResponse(false); + + CreateTest(() => { }); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + AddStep("exit", () => Player.Exit()); + + AddAssert("ensure no submission", () => !Player.SubmissionRequested); + } + + [Test] + public void TestSubmissionOnExit() + { + prepareTokenResponse(true); + + CreateTest(() => { }); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + AddStep("exit", () => Player.Exit()); + AddUntilStep("wait for submission", () => Player.SubmissionRequested); + } + + private void prepareTokenResponse(bool validToken) { AddStep("Prepare test API", () => { @@ -37,38 +97,16 @@ namespace osu.Game.Tests.Visual.Gameplay switch (request) { case CreateSoloScoreRequest tokenRequest: - tokenRequest.TriggerSuccess(new APIScoreToken { ID = 1234 }); + if (validToken) + tokenRequest.TriggerSuccess(new APIScoreToken { ID = 1234 }); + else + tokenRequest.TriggerFailure(new Exception()); return true; } return false; }; }); - - base.SetUpSteps(); - - // Ensure track has actually running before attempting to seek - AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); - } - - [Test] - public void TestSubmissionOnResults() - { - AddUntilStep("wait for token request", () => Player.TokenCreationRequested); - - AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); - - AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); - - AddUntilStep("wait for submission", () => Player.SubmissionRequested); - } - - [Test] - public void TestSubmissionOnExit() - { - AddUntilStep("wait for token request", () => Player.TokenCreationRequested); - AddStep("exit", () => Player.Exit()); - AddUntilStep("wait for submission", () => Player.SubmissionRequested); } } } From b00ee67895cba2bdbe64c49c9b698f87413bb2fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:25:47 +0900 Subject: [PATCH 31/69] Remove excess whitespace --- osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index ce4ec27225..056d4ad6f7 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Dashboard switch (value) { case DashboardOverlayTabs.Friends: - return FriendsStrings.TitleCompact; + return FriendsStrings.TitleCompact; case DashboardOverlayTabs.CurrentlyPlaying: return @"Currently Playing"; From 74c63e15bef6d50aa8e4a43a44a7f8a449d0984c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:38:28 +0900 Subject: [PATCH 32/69] Mark score failed on fail and exit --- .../TestScenePlayerScoreSubmission.cs | 38 ++++++++++++++----- osu.Game/Screens/Play/Player.cs | 5 +++ osu.Game/Screens/Play/SubmittingPlayer.cs | 4 +- osu.Game/Tests/Visual/TestPlayer.cs | 5 ++- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 4088fc855d..ada50fbcf4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -23,9 +23,14 @@ namespace osu.Game.Tests.Visual.Gameplay protected override bool HasCustomSteps => true; + private bool allowFail; + protected override TestPlayer CreatePlayer(Ruleset ruleset) { - SelectedMods.Value = new[] { ruleset.GetAllMods().OfType().First() }; + SelectedMods.Value = !allowFail + ? new[] { ruleset.GetAllMods().OfType().First() } + : Array.Empty(); + return new TestPlayer(false); } @@ -34,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(false); - CreateTest(() => { }); + CreateTest(() => allowFail = false); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); @@ -43,7 +48,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); - AddAssert("ensure no submission", () => !Player.SubmissionRequested); + AddAssert("ensure no submission", () => Player.SubmittedScore == null); } [Test] @@ -51,7 +56,7 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(true); - CreateTest(() => { }); + CreateTest(() => allowFail = false); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); @@ -59,8 +64,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); - - AddAssert("ensure submission", () => Player.SubmissionRequested); + AddAssert("ensure passing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == true); } [Test] @@ -68,12 +72,26 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(false); - CreateTest(() => { }); + CreateTest(() => allowFail = false); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddStep("exit", () => Player.Exit()); + AddAssert("ensure no submission", () => Player.SubmittedScore == null); + } + + [Test] + public void TestSubmissionOnFail() + { + prepareTokenResponse(true); + + CreateTest(() => allowFail = true); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + AddUntilStep("wait for fail", () => Player.HasFailed); AddStep("exit", () => Player.Exit()); - AddAssert("ensure no submission", () => !Player.SubmissionRequested); + AddAssert("ensure failing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == false); } [Test] @@ -81,11 +99,11 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(true); - CreateTest(() => { }); + CreateTest(() => allowFail = false); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); AddStep("exit", () => Player.Exit()); - AddUntilStep("wait for submission", () => Player.SubmissionRequested); + AddAssert("ensure failing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == false); } private void prepareTokenResponse(bool validToken) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 58f60d14cf..97854ee12f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -768,6 +768,7 @@ namespace osu.Game.Screens.Play return false; HasFailed = true; + Score.ScoreInfo.Passed = false; // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // could process an extra frame after the GameplayClock is stopped. @@ -950,6 +951,10 @@ namespace osu.Game.Screens.Play { screenSuspension?.Expire(); + // if arriving here and the results screen preparation task hasn't run, it's safe to say the user has not completed the beatmap. + if (prepareScoreForDisplayTask == null) + Score.ScoreInfo.Passed = false; + // EndPlaying() is typically called from ReplayRecorder.Dispose(). Disposal is currently asynchronous. // To resolve test failures, forcefully end playing synchronously when this screen exits. // Todo: Replace this with a more permanent solution once osu-framework has a synchronous cleanup method. diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index bbb6a21f39..7c5a06707d 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -113,9 +113,11 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { + var exiting = base.OnExiting(next); + submitScore(Score); - return base.OnExiting(next); + return exiting; } /// diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index 52eb06bdc6..5e5f20b307 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -40,7 +40,8 @@ namespace osu.Game.Tests.Visual public new HealthProcessor HealthProcessor => base.HealthProcessor; public bool TokenCreationRequested { get; private set; } - public bool SubmissionRequested { get; private set; } + + public Score SubmittedScore { get; private set; } public new bool PauseCooldownActive => base.PauseCooldownActive; @@ -66,7 +67,7 @@ namespace osu.Game.Tests.Visual protected override APIRequest CreateSubmissionRequest(Score score, long token) { - SubmissionRequested = true; + SubmittedScore = score; return base.CreateSubmissionRequest(score, token); } From a6323b7d87fba2a0adad4a750a9155fcde16bf49 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:54:59 +0900 Subject: [PATCH 33/69] Use `APIException` --- .../Visual/Gameplay/TestScenePlayerScoreSubmission.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index ada50fbcf4..27f9fc85cf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -118,7 +118,7 @@ namespace osu.Game.Tests.Visual.Gameplay if (validToken) tokenRequest.TriggerSuccess(new APIScoreToken { ID = 1234 }); else - tokenRequest.TriggerFailure(new Exception()); + tokenRequest.TriggerFailure(new APIException("something went wrong!", null)); return true; } From 3816c486d5fb5f13c226f8b1cd72f457cef4a51c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 19:03:55 +0900 Subject: [PATCH 34/69] Guard against a potential startup crash if user's preferred ruleset has a compatibility issue Resolves this issue seen at https://github.com/ppy/osu/issues/13722#issuecomment-872088071. --- osu.Game/OsuGame.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 32136b8789..14309e2296 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -223,7 +223,20 @@ namespace osu.Game // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); - Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); + + var preferredRuleset = RulesetStore.GetRuleset(configRuleset.Value); + + try + { + Ruleset.Value = preferredRuleset ?? RulesetStore.AvailableRulesets.First(); + } + catch (Exception e) + { + // on startup, a ruleset may be selected which has compatibility issues. + Logger.Error(e, $@"Failed to switch to preferred ruleset {preferredRuleset}."); + Ruleset.Value = RulesetStore.AvailableRulesets.First(); + } + Ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ID ?? 0; // bind config int to database SkinInfo From a78d1b4c2ee283e8e83f9013bc4bacd762bbacea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Jul 2021 19:37:21 +0900 Subject: [PATCH 35/69] Update SR colours to match osu-web --- osu.Game/Graphics/OsuColour.cs | 4 ++-- osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 15967c37c2..a44c28eaa6 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -32,10 +32,10 @@ namespace osu.Game.Graphics return Pink; case DifficultyRating.Expert: - return useLighterColour ? PurpleLight : Purple; + return PurpleLight; case DifficultyRating.ExpertPlus: - return useLighterColour ? Gray9 : Gray0; + return useLighterColour ? Gray9 : Color4Extensions.FromHex("#121415"); } } diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 7aba699216..e59a0de316 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -4,9 +4,7 @@ using System.Globalization; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; @@ -111,12 +109,9 @@ namespace osu.Game.Screens.Ranking.Expanded var rating = Current.Value.DifficultyRating; - background.Colour = rating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(rating); + background.Colour = colours.ForDifficultyRating(rating, true); textFlow.Clear(); - textFlow.AddText($"{wholePart}", s => { s.Colour = Color4.Black; From 4c1b8bc42726a9cd352a57388ffdd3c15dee99ce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 20:23:12 +0900 Subject: [PATCH 36/69] Update disclaimer --- osu.Game/Screens/Menu/Disclaimer.cs | 63 ++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 72eb9c7c0c..78dda05a19 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.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 osu.Framework.Allocation; using osu.Framework.Bindables; @@ -36,6 +37,8 @@ namespace osu.Game.Screens.Menu private readonly Bindable currentUser = new Bindable(); private FillFlowContainer fill; + private readonly List expendableText = new List(); + public Disclaimer(OsuScreen nextScreen = null) { this.nextScreen = nextScreen; @@ -54,7 +57,7 @@ namespace osu.Game.Screens.Menu { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Icon = FontAwesome.Solid.Flask, + Icon = OsuIcon.Logo, Size = new Vector2(icon_size), Y = icon_y, }, @@ -76,37 +79,53 @@ namespace osu.Game.Screens.Menu Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Spacing = new Vector2(0, 2), - LayoutDuration = 2000, - LayoutEasing = Easing.OutQuint - }, - supportFlow = new LinkFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - TextAnchor = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Alpha = 0, - Spacing = new Vector2(0, 2), }, } - } + }, + supportFlow = new LinkFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + TextAnchor = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Padding = new MarginPadding(20), + Alpha = 0, + Spacing = new Vector2(0, 2), + }, }; - textFlow.AddText("This project is an ongoing ", t => t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.Light)); - textFlow.AddText("work in progress", t => t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.SemiBold)); + textFlow.AddText("This is osu!", t => t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.Regular)); + + expendableText.AddRange(textFlow.AddText("(lazer)", t => + { + t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.Regular); + t.Colour = colours.PinkLight; + })); textFlow.NewParagraph(); - static void format(SpriteText t) => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold); + textFlow.AddText("the next ", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular)); + textFlow.AddText("major update", t => + { + t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.SemiBold); + t.Colour = colours.Pink; + }); + expendableText.AddRange(textFlow.AddText(" coming to osu!", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular))); + textFlow.AddText(".", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular)); - textFlow.AddParagraph(getRandomTip(), t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.SemiBold)); + textFlow.NewParagraph(); + + textFlow.AddParagraph("Today's Tip: ", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.SemiBold)); + textFlow.AddText(getRandomTip(), t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular)); textFlow.NewParagraph(); textFlow.NewParagraph(); iconColour = colours.Yellow; + static void format(SpriteText t) => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold); + // manually transfer the user once, but only do the final bind in LoadComplete to avoid thread woes (API scheduler could run while this screen is still loading). // the manual transfer is here to ensure all text content is loaded ahead of time as this is very early in the game load process and we want to avoid stutters. currentUser.Value = api.LocalUser.Value; @@ -122,7 +141,7 @@ namespace osu.Game.Screens.Menu { supportFlow.AddText("Consider becoming an ", format); supportFlow.AddLink("osu!supporter", "https://osu.ppy.sh/home/support", creationParameters: format); - supportFlow.AddText(" to help support the game", format); + supportFlow.AddText(" to help support osu!'s development", format); } heart = supportFlow.AddIcon(FontAwesome.Solid.Heart, t => @@ -169,7 +188,11 @@ namespace osu.Game.Screens.Menu .MoveToY(icon_y, 160, Easing.InQuart) .FadeColour(Color4.White, 160); - fill.Delay(520 + 160).MoveToOffset(new Vector2(0, 15), 160, Easing.OutQuart); + using (BeginDelayedSequence(520 + 160)) + { + fill.MoveToOffset(new Vector2(0, 15), 160, Easing.OutQuart); + Schedule(() => expendableText.ForEach(t => t.Expire())); + } } supportFlow.FadeOut().Delay(2000).FadeIn(500); From 4c95af4b16a961743639de95451104cd604b8de8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Jul 2021 20:35:31 +0900 Subject: [PATCH 37/69] Add star rating range display --- .../TestSceneStarRatingRangeDisplay.cs | 40 ++++++++ .../Components/StarRatingRangeDisplay.cs | 93 +++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs create mode 100644 osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs new file mode 100644 index 0000000000..cdeafdc9a3 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Tests.Visual.OnlinePlay; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneStarRatingRangeDisplay : OnlinePlayTestScene + { + [SetUp] + public new void Setup() => Schedule(() => + { + SelectedRoom.Value = new Room(); + + Child = new StarRatingRangeDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + }); + + [Test] + public void TestRange([Values(0, 2, 3, 4, 6, 7)] double min, [Values(0, 2, 3, 4, 6, 7)] double max) + { + AddStep("set playlist", () => + { + SelectedRoom.Value.Playlist.AddRange(new[] + { + new PlaylistItem { Beatmap = { Value = new BeatmapInfo { StarDifficulty = min } } }, + new PlaylistItem { Beatmap = { Value = new BeatmapInfo { StarDifficulty = max } } }, + }); + }); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs new file mode 100644 index 0000000000..b2e35d7020 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -0,0 +1,93 @@ +// 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.Specialized; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Screens.Ranking.Expanded; +using osuTK; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + public class StarRatingRangeDisplay : OnlinePlayComposite + { + [Resolved] + private OsuColour colours { get; set; } + + private StarRatingDisplay minDisplay; + private Drawable minBackground; + private StarRatingDisplay maxDisplay; + private Drawable maxBackground; + + public StarRatingRangeDisplay() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 1, + Children = new[] + { + minBackground = new Box + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + maxBackground = new Box + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + minDisplay = new StarRatingDisplay(default), + maxDisplay = new StarRatingDisplay(default) + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Playlist.BindCollectionChanged(updateRange, true); + } + + private void updateRange(object sender, NotifyCollectionChangedEventArgs e) + { + var orderedDifficulties = Playlist.Select(p => p.Beatmap.Value).OrderBy(b => b.StarDifficulty).ToArray(); + + StarDifficulty minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarDifficulty : 0, 0); + StarDifficulty maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarDifficulty : 0, 0); + + minDisplay.Current.Value = minDifficulty; + maxDisplay.Current.Value = maxDifficulty; + + minBackground.Colour = colours.ForDifficultyRating(minDifficulty.DifficultyRating, true); + maxBackground.Colour = colours.ForDifficultyRating(maxDifficulty.DifficultyRating, true); + } + } +} From 68c5e6a4311080716624c1114e1b63a90c2dd74f Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Thu, 1 Jul 2021 20:41:30 +0900 Subject: [PATCH 38/69] Add audio feedback to changing volume --- osu.Game/Overlays/Volume/VolumeMeter.cs | 35 ++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index a15076581e..2251be03c6 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -4,6 +4,8 @@ using System; using System.Globalization; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -36,6 +38,10 @@ namespace osu.Game.Overlays.Volume private OsuSpriteText text; private BufferedContainer maxGlow; + private bool firstUpdate = true; + private Sample sample; + private double sampleLastPlaybackTime; + public VolumeMeter(string name, float circleSize, Color4 meterColour) { this.circleSize = circleSize; @@ -46,8 +52,11 @@ namespace osu.Game.Overlays.Volume } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, AudioManager audio) { + sample = audio.Samples.Get(@"UI/notch-tick"); + sampleLastPlaybackTime = Time.Current; + Color4 backgroundColour = colours.Gray1; CircularProgress bgProgress; @@ -202,6 +211,7 @@ namespace osu.Game.Overlays.Volume get => displayVolume; set { + bool displayVolumeChanged = Math.Round(displayVolume * 100) != Math.Round(value * 100); displayVolume = value; if (displayVolume >= 0.995f) @@ -217,6 +227,29 @@ namespace osu.Game.Overlays.Volume volumeCircle.Current.Value = displayVolume * 0.75f; volumeCircleGlow.Current.Value = displayVolume * 0.75f; + + Schedule(() => + { + const int sfx_debounce_time = 30; + + if (firstUpdate || + !displayVolumeChanged || + Time.Current - sampleLastPlaybackTime <= sfx_debounce_time) + { + firstUpdate = false; + return; + } + + var channel = sample.Play(); + + channel.Frequency.Value = 1 + displayVolume * 0.1f + RNG.NextDouble(0.02f); + if (displayVolume < 0.005f) + channel.Frequency.Value -= 0.5f; + else if (displayVolume > 0.995f) + channel.Frequency.Value -= 0.5f; + + sampleLastPlaybackTime = Time.Current; + }); } } From dad28b28265ddec8f6c478041b8aee4317f43c22 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Thu, 1 Jul 2021 20:45:29 +0900 Subject: [PATCH 39/69] Update OsuSliderBar to use new notch-tick sample and tweak pitch ramping --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index ae16169123..1433f0c38b 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Localisation; +using osu.Framework.Utils; namespace osu.Game.Graphics.UserInterface { @@ -99,7 +100,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) { - sample = audio.Samples.Get(@"UI/sliderbar-notch"); + sample = audio.Samples.Get(@"UI/notch-tick"); AccentColour = colours.Pink; } @@ -149,7 +150,7 @@ namespace osu.Game.Graphics.UserInterface private void playSample(T value) { - if (Clock == null || Clock.CurrentTime - lastSampleTime <= 50) + if (Clock == null || Clock.CurrentTime - lastSampleTime <= 30) return; if (value.Equals(lastSampleValue)) @@ -160,11 +161,11 @@ namespace osu.Game.Graphics.UserInterface var channel = sample.Play(); - channel.Frequency.Value = 1 + NormalizedValue * 0.2f; + channel.Frequency.Value = 1 + NormalizedValue * 0.2f + RNG.NextDouble(0.02f); if (NormalizedValue == 0) - channel.Frequency.Value -= 0.4f; + channel.Frequency.Value -= 0.5f; else if (NormalizedValue == 1) - channel.Frequency.Value += 0.4f; + channel.Frequency.Value -= 0.5f; } private void updateTooltipText(T value) From f1c11243e92be087d5977bbd5e8a10d2a19a42b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 22:06:59 +0900 Subject: [PATCH 40/69] 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 481ddc118f..b2b48f5de8 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 589afb86be..42eb2ad1d8 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 a8bf0e4ab2..67993049f2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 8ab9ea992635622ed9e3b043e23ca7934f418ad3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:03 +0000 Subject: [PATCH 41/69] Bump Realm from 10.2.0 to 10.2.1 Bumps [Realm](https://github.com/realm/realm-dotnet) from 10.2.0 to 10.2.1. - [Release notes](https://github.com/realm/realm-dotnet/releases) - [Changelog](https://github.com/realm/realm-dotnet/blob/master/CHANGELOG.md) - [Commits](https://github.com/realm/realm-dotnet/compare/10.2.0...10.2.1) --- updated-dependencies: - dependency-name: Realm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- 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 481ddc118f..2e388b8626 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -56,6 +56,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..24779fc4d1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -35,7 +35,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index a8bf0e4ab2..33ea2261ca 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -99,6 +99,6 @@ - + From c976854e2449b8f659cebe2be22e2ec9da0bc45c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:08 +0000 Subject: [PATCH 42/69] Bump Sentry from 3.4.0 to 3.6.0 Bumps [Sentry](https://github.com/getsentry/sentry-dotnet) from 3.4.0 to 3.6.0. - [Release notes](https://github.com/getsentry/sentry-dotnet/releases) - [Changelog](https://github.com/getsentry/sentry-dotnet/blob/main/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-dotnet/compare/3.4.0...3.6.0) --- updated-dependencies: - dependency-name: Sentry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..0ab6bb9ba6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -38,7 +38,7 @@ - + From e5e468e38787da508cd291a205e7ce406c34be3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:11 +0000 Subject: [PATCH 43/69] Bump SharpCompress from 0.28.2 to 0.28.3 Bumps [SharpCompress](https://github.com/adamhathcock/sharpcompress) from 0.28.2 to 0.28.3. - [Release notes](https://github.com/adamhathcock/sharpcompress/releases) - [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.28.2...0.28.3) --- updated-dependencies: - dependency-name: SharpCompress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..f857d155ec 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -39,7 +39,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a8bf0e4ab2..f1ee770688 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -94,7 +94,7 @@ - + From 71867337b6c4e00310d3232b3ca88ccaebc9f3d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:15 +0000 Subject: [PATCH 44/69] Bump HtmlAgilityPack from 1.11.33 to 1.11.34 Bumps [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) from 1.11.33 to 1.11.34. - [Release notes](https://github.com/zzzprojects/html-agility-pack/releases) - [Commits](https://github.com/zzzprojects/html-agility-pack/compare/v1.11.33...v1.11.34) --- updated-dependencies: - dependency-name: HtmlAgilityPack dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..f5838f5109 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -20,7 +20,7 @@ - + From 0d3de488de65aeb6310d924fadc67e8433b0151c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:17 +0000 Subject: [PATCH 45/69] Bump NUnit3TestAdapter from 3.17.0 to 4.0.0 Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 3.17.0 to 4.0.0. - [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases) - [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V3.17...V4.0.0) --- updated-dependencies: - dependency-name: NUnit3TestAdapter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .../osu.Game.Rulesets.EmptyFreeform.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- .../osu.Game.Rulesets.EmptyScrolling.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index 5eb5efa54c..3dd6be7307 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index d7c116411a..0c4bfe0ed7 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index 89b551286b..bb0a487274 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index d7c116411a..0c4bfe0ed7 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 7a74563b2b..da8a0540f4 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -9,7 +9,7 @@ - + diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 83d0744588..484da8e22e 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index b2a0912d19..6df555617b 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 1efd19f49d..68be34d153 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 8fb167ba10..532fdc5cb0 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 35d3c7f202..161e248d96 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 2084be765a..ba096abd36 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe From b320528eb59b72b50a53bf33e1706f7c6a428525 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:22 +0000 Subject: [PATCH 46/69] Bump Humanizer from 2.10.1 to 2.11.10 Bumps [Humanizer](https://github.com/Humanizr/Humanizer) from 2.10.1 to 2.11.10. - [Release notes](https://github.com/Humanizr/Humanizer/releases) - [Changelog](https://github.com/Humanizr/Humanizer/blob/main/release_notes.md) - [Commits](https://github.com/Humanizr/Humanizer/compare/v2.10.1...v2.11.10) --- updated-dependencies: - dependency-name: Humanizer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..74ed0b8299 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,7 +21,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a8bf0e4ab2..8226d23e0a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -89,7 +89,7 @@ - + From e7c7b8512ac012bb77852603c079893a9471a147 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:25 +0000 Subject: [PATCH 47/69] Bump Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson Bumps [Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson](https://github.com/dotnet/aspnetcore) from 5.0.6 to 5.0.7. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Commits](https://github.com/dotnet/aspnetcore/compare/v5.0.6...v5.0.7) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..2709f25bb4 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -25,7 +25,7 @@ - + From fb2d08b9ee2a18501464c9c3583c71a349e969d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:29 +0000 Subject: [PATCH 48/69] Bump ppy.LocalisationAnalyser from 2021.608.0 to 2021.614.0 Bumps [ppy.LocalisationAnalyser](https://github.com/ppy/osu-localisation-analyser) from 2021.608.0 to 2021.614.0. - [Release notes](https://github.com/ppy/osu-localisation-analyser/releases) - [Commits](https://github.com/ppy/osu-localisation-analyser/compare/2021.608.0...2021.614.0) --- updated-dependencies: - dependency-name: ppy.LocalisationAnalyser dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..b8502216f3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -31,7 +31,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From f6234864cc8cfe11d678d2a4ed3226003ff06ff9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:33 +0000 Subject: [PATCH 49/69] Bump Microsoft.AspNetCore.SignalR.Client from 5.0.6 to 5.0.7 Bumps [Microsoft.AspNetCore.SignalR.Client](https://github.com/dotnet/aspnetcore) from 5.0.6 to 5.0.7. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Commits](https://github.com/dotnet/aspnetcore/compare/v5.0.6...v5.0.7) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.SignalR.Client dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..44e7a00839 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + From d0ae946cb6d70a81e4b4b453db31fc480fa16f2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:38 +0000 Subject: [PATCH 50/69] Bump Microsoft.AspNetCore.SignalR.Protocols.MessagePack Bumps [Microsoft.AspNetCore.SignalR.Protocols.MessagePack](https://github.com/dotnet/aspnetcore) from 5.0.6 to 5.0.7. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Commits](https://github.com/dotnet/aspnetcore/compare/v5.0.6...v5.0.7) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.MessagePack dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..470f7f48d9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + From 9b0fa6d3fcb66536b1b2b8fe62c54aa005cc773f Mon Sep 17 00:00:00 2001 From: aitani9 <55509723+aitani9@users.noreply.github.com> Date: Thu, 1 Jul 2021 15:38:38 -0700 Subject: [PATCH 51/69] Make flipping reflect across the axes of the selection box --- osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 23f36ffe5b..7a35c8600d 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -127,6 +127,7 @@ namespace osu.Game.Skinning.Editor public override bool HandleFlip(Direction direction) { var selectionQuad = getSelectionQuad(); + Vector2 scaleFactor = direction == Direction.Horizontal ? new Vector2(-1, 1) : new Vector2(1, -1); foreach (var b in SelectedBlueprints) { @@ -136,10 +137,8 @@ namespace osu.Game.Skinning.Editor updateDrawablePosition(drawableItem, flippedPosition); - drawableItem.Scale *= new Vector2( - direction == Direction.Horizontal ? -1 : 1, - direction == Direction.Vertical ? -1 : 1 - ); + drawableItem.Scale *= scaleFactor; + drawableItem.Rotation -= drawableItem.Rotation % 180 * 2; } return true; From 083e463afd8065f19d082e9e158ab6ad31afdae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Jul 2021 01:02:36 +0200 Subject: [PATCH 52/69] Use alternative hue slider nub design --- .../UserInterfaceV2/OsuHSVColourPicker.cs | 68 ++++++++++++------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs index 2a399cfaf8..06056f239b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; @@ -15,6 +16,10 @@ namespace osu.Game.Graphics.UserInterfaceV2 { public class OsuHSVColourPicker : HSVColourPicker { + private const float spacing = 10; + private const float corner_radius = 10; + private const float control_border_thickness = 3; + protected override HueSelector CreateHueSelector() => new OsuHueSelector(); protected override SaturationValueSelector CreateSaturationValueSelector() => new OsuSaturationValueSelector(); @@ -23,37 +28,58 @@ namespace osu.Game.Graphics.UserInterfaceV2 { Background.Colour = colourProvider?.Dark5 ?? osuColour.GreySeafoamDark; - Content.Padding = new MarginPadding(10); - Content.Spacing = new Vector2(0, 10); + Content.Padding = new MarginPadding(spacing); + Content.Spacing = new Vector2(0, spacing); } + private static EdgeEffectParameters createShadowParameters() => new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0, 1), + Radius = 3, + Colour = Colour4.Black.Opacity(0.3f) + }; + private class OsuHueSelector : HueSelector { public OsuHueSelector() { - Margin = new MarginPadding - { - Bottom = 15 - }; - - SliderBar.CornerRadius = SliderBar.Height / 2; + SliderBar.CornerRadius = corner_radius; SliderBar.Masking = true; } - protected override Drawable CreateSliderNub() => new SliderNub(); + protected override Drawable CreateSliderNub() => new SliderNub(this); private class SliderNub : CompositeDrawable { - public SliderNub() + private readonly Bindable hue; + private readonly Box fill; + + public SliderNub(OsuHueSelector osuHueSelector) { - InternalChild = new Triangle + hue = osuHueSelector.Hue.GetBoundCopy(); + + InternalChild = new CircularContainer { - Width = 20, - Height = 15, - Anchor = Anchor.BottomCentre, - Origin = Anchor.TopCentre + Height = 35, + Width = 10, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Masking = true, + BorderColour = Colour4.White, + BorderThickness = control_border_thickness, + EdgeEffect = createShadowParameters(), + Child = fill = new Box + { + RelativeSizeAxes = Axes.Both + } }; } + + protected override void LoadComplete() + { + hue.BindValueChanged(h => fill.Colour = Colour4.FromHSV(h.NewValue, 1, 1), true); + } } } @@ -61,7 +87,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { public OsuSaturationValueSelector() { - SelectionArea.CornerRadius = 10; + SelectionArea.CornerRadius = corner_radius; SelectionArea.Masking = true; // purposefully use hard non-AA'd masking to avoid edge artifacts. SelectionArea.MaskingSmoothness = 0; @@ -82,14 +108,8 @@ namespace osu.Game.Graphics.UserInterfaceV2 Size = new Vector2(20), Masking = true, BorderColour = Colour4.White, - BorderThickness = 3, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Offset = new Vector2(0, 1), - Radius = 3, - Colour = Colour4.Black.Opacity(0.3f) - }, + BorderThickness = control_border_thickness, + EdgeEffect = createShadowParameters(), Child = previewBox = new Box { RelativeSizeAxes = Axes.Both From a1eaf396453b770712b645d096e52e90330f571f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 12:15:16 +0900 Subject: [PATCH 53/69] Slightly change wording to hopefully read better --- osu.Game/Screens/Menu/Disclaimer.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 78dda05a19..6ae7142814 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -95,9 +95,9 @@ namespace osu.Game.Screens.Menu }, }; - textFlow.AddText("This is osu!", t => t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.Regular)); + textFlow.AddText("this is osu!", t => t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.Regular)); - expendableText.AddRange(textFlow.AddText("(lazer)", t => + expendableText.AddRange(textFlow.AddText("lazer", t => { t.Font = t.Font.With(Typeface.Torus, 30, FontWeight.Regular); t.Colour = colours.PinkLight; @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Menu textFlow.NewParagraph(); - textFlow.AddParagraph("Today's Tip: ", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.SemiBold)); + textFlow.AddParagraph("today's tip: ", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.SemiBold)); textFlow.AddText(getRandomTip(), t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular)); textFlow.NewParagraph(); @@ -191,7 +191,11 @@ namespace osu.Game.Screens.Menu using (BeginDelayedSequence(520 + 160)) { fill.MoveToOffset(new Vector2(0, 15), 160, Easing.OutQuart); - Schedule(() => expendableText.ForEach(t => t.Expire())); + Schedule(() => expendableText.ForEach(t => + { + t.FadeOut(100); + t.ScaleTo(new Vector2(0, 1), 100, Easing.OutQuart); + })); } } From f0727a63bebe1c581db6da303f34c46dd043aa57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 12:16:45 +0900 Subject: [PATCH 54/69] Reduce usable width --- osu.Game/Screens/Menu/Disclaimer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 6ae7142814..59f0f26b94 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Menu { textFlow = new LinkFlowContainer { - RelativeSizeAxes = Axes.X, + Width = 680, AutoSizeAxes = Axes.Y, TextAnchor = Anchor.TopCentre, Anchor = Anchor.TopCentre, From 62c125d7a2d76cab5f756a4b57336158dea4a31a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 12:21:28 +0900 Subject: [PATCH 55/69] Tidy up font formatting methods --- osu.Game/Screens/Menu/Disclaimer.cs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 59f0f26b94..b0a2fad813 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -103,29 +103,31 @@ namespace osu.Game.Screens.Menu t.Colour = colours.PinkLight; })); + static void formatRegular(SpriteText t) => t.Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular); + static void formatSemiBold(SpriteText t) => t.Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold); + textFlow.NewParagraph(); - textFlow.AddText("the next ", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular)); + textFlow.AddText("the next ", formatRegular); textFlow.AddText("major update", t => { t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.SemiBold); t.Colour = colours.Pink; }); - expendableText.AddRange(textFlow.AddText(" coming to osu!", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular))); - textFlow.AddText(".", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular)); + expendableText.AddRange(textFlow.AddText(" coming to osu!", formatRegular)); + textFlow.AddText(".", formatRegular); + textFlow.NewParagraph(); textFlow.NewParagraph(); - textFlow.AddParagraph("today's tip: ", t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.SemiBold)); - textFlow.AddText(getRandomTip(), t => t.Font = t.Font.With(Typeface.Torus, 20, FontWeight.Regular)); + textFlow.AddParagraph("today's tip:", formatSemiBold); + textFlow.AddParagraph(getRandomTip(), formatRegular); textFlow.NewParagraph(); textFlow.NewParagraph(); iconColour = colours.Yellow; - static void format(SpriteText t) => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold); - // manually transfer the user once, but only do the final bind in LoadComplete to avoid thread woes (API scheduler could run while this screen is still loading). // the manual transfer is here to ensure all text content is loaded ahead of time as this is very early in the game load process and we want to avoid stutters. currentUser.Value = api.LocalUser.Value; @@ -135,19 +137,19 @@ namespace osu.Game.Screens.Menu if (e.NewValue.IsSupporter) { - supportFlow.AddText("Eternal thanks to you for supporting osu!", format); + supportFlow.AddText("Eternal thanks to you for supporting osu!", formatSemiBold); } else { - supportFlow.AddText("Consider becoming an ", format); - supportFlow.AddLink("osu!supporter", "https://osu.ppy.sh/home/support", creationParameters: format); - supportFlow.AddText(" to help support osu!'s development", format); + supportFlow.AddText("Consider becoming an ", formatSemiBold); + supportFlow.AddLink("osu!supporter", "https://osu.ppy.sh/home/support", formatSemiBold); + supportFlow.AddText(" to help support osu!'s development", formatSemiBold); } heart = supportFlow.AddIcon(FontAwesome.Solid.Heart, t => { t.Padding = new MarginPadding { Left = 5, Top = 3 }; - t.Font = t.Font.With(size: 12); + t.Font = t.Font.With(size: 20); t.Origin = Anchor.Centre; t.Colour = colours.Pink; }).First(); From 0396a03bbc7f9e041a7d0feb10aa906b2f614355 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 12:50:53 +0900 Subject: [PATCH 56/69] Rename `Mod.Ranked` back to avoid breaking ruleset API --- osu.Game/Rulesets/Mods/Mod.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 79d16013e3..40c3761768 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Mods public virtual bool UserPlayable => true; [Obsolete("Going forward, the concept of \"ranked\" doesn't exist. The only exceptions are automation mods, which should now override and set UserPlayable to true.")] // Can be removed 20211009 - public virtual bool IsRanked => false; + public virtual bool Ranked => false; /// /// Whether this mod requires configuration to apply changes to the game. From 30467191b2137534aa3aaacb4973938bf20104be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 14:21:48 +0900 Subject: [PATCH 57/69] Remove local handling of `NoFail` addition --- .../Gameplay/TestScenePlayerScoreSubmission.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 27f9fc85cf..d80fbfe309 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Linq; using NUnit.Framework; using osu.Framework.Screens; @@ -9,7 +8,6 @@ using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Online.Solo; using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Ranking; @@ -17,22 +15,15 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestScenePlayerScoreSubmission : OsuPlayerTestScene { - protected override bool AllowFail => false; + protected override bool AllowFail => allowFail; + + private bool allowFail; private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; protected override bool HasCustomSteps => true; - private bool allowFail; - - protected override TestPlayer CreatePlayer(Ruleset ruleset) - { - SelectedMods.Value = !allowFail - ? new[] { ruleset.GetAllMods().OfType().First() } - : Array.Empty(); - - return new TestPlayer(false); - } + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false); [Test] public void TestNoSubmissionOnResultsWithNoToken() From f689e788c9d363136dfc0900acd179a801754b6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 14:24:27 +0900 Subject: [PATCH 58/69] Avoid using game-wide beatmap during score submission --- osu.Game/Screens/Play/SoloPlayer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index 0099b4c87c..ef1087dd62 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -37,9 +37,11 @@ namespace osu.Game.Screens.Play protected override APIRequest CreateSubmissionRequest(Score score, long token) { - Debug.Assert(Beatmap.Value.BeatmapInfo.OnlineBeatmapID != null); + var beatmap = score.ScoreInfo.Beatmap; - int beatmapId = Beatmap.Value.BeatmapInfo.OnlineBeatmapID.Value; + Debug.Assert(beatmap.OnlineBeatmapID != null); + + int beatmapId = beatmap.OnlineBeatmapID.Value; return new SubmitSoloScoreRequest(beatmapId, token, score.ScoreInfo); } From f2d9d78455d2de5495c522cde54b6209dcbbd446 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 14:43:48 +0900 Subject: [PATCH 59/69] Fix some incorrectly invoked `async` calls --- osu.Desktop/Updater/SquirrelUpdateManager.cs | 4 ++-- .../Multiplayer/TestSceneMultiplayerReadyButton.cs | 5 +++-- .../Multiplayer/TestSceneMultiplayerSpectateButton.cs | 9 +++++---- osu.Game/OsuGame.cs | 4 ++++ 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 47cd39dc5a..58d67c11d9 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -116,7 +116,7 @@ namespace osu.Desktop.Updater if (scheduleRecheck) { // check again in 30 minutes. - Scheduler.AddDelayed(async () => await checkForUpdateAsync().ConfigureAwait(false), 60000 * 30); + Scheduler.AddDelayed(() => Task.Run(async () => await checkForUpdateAsync().ConfigureAwait(false)), 60000 * 30); } } @@ -141,7 +141,7 @@ namespace osu.Desktop.Updater Activated = () => { updateManager.PrepareUpdateAsync() - .ContinueWith(_ => updateManager.Schedule(() => game.GracefullyExit())); + .ContinueWith(_ => updateManager.Schedule(() => game?.GracefullyExit())); return true; }; } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs index 4f2ca34fb0..fd9aa922b0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -65,7 +66,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnReadyClick = async () => + OnReadyClick = () => Task.Run(async () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); @@ -77,7 +78,7 @@ namespace osu.Game.Tests.Visual.Multiplayer await Client.ToggleReady(); readyClickOperation.Dispose(); - } + }) }); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs index 070158f552..a4b0195b00 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -69,19 +70,19 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnSpectateClick = async () => + OnSpectateClick = () => Task.Run(async () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); await Client.ToggleSpectate(); readyClickOperation.Dispose(); - } + }) }, readyButton = new MultiplayerReadyButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnReadyClick = async () => + OnReadyClick = () => Task.Run(async () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); @@ -93,7 +94,7 @@ namespace osu.Game.Tests.Visual.Multiplayer await Client.ToggleReady(); readyClickOperation.Dispose(); - } + }) } } }; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 14309e2296..dcd2d68b43 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -491,6 +491,10 @@ namespace osu.Game public override Task Import(params ImportTask[] imports) { // encapsulate task as we don't want to begin the import process until in a ready state. + + // ReSharper disable once AsyncVoidLambda + // TODO: This is bad because `new Task` doesn't have a Func override. + // Only used for android imports and a bit of a mess. Probably needs rethinking overall. var importTask = new Task(async () => await base.Import(imports).ConfigureAwait(false)); waitForReady(() => this, _ => importTask.Start()); From 69b13477304ce77d9003cbceac394cf3f571dd88 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 15:29:51 +0900 Subject: [PATCH 60/69] Tidy up weird bind logic --- osu.Game/Overlays/Volume/VolumeMeter.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 2251be03c6..6a26de204c 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -187,13 +187,7 @@ namespace osu.Game.Overlays.Volume } }; - Bindable.ValueChanged += volume => - { - this.TransformTo("DisplayVolume", - volume.NewValue, - 400, - Easing.OutQuint); - }; + Bindable.ValueChanged += volume => { this.TransformTo(nameof(DisplayVolume), volume.NewValue, 400, Easing.OutQuint); }; bgProgress.Current.Value = 0.75f; } From 13254d51fc93a33dbe67921d4a62b112bd4ae2ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 15:44:35 +0900 Subject: [PATCH 61/69] Remove usage of `bool` for initial playback Also refactors the whole method to generally clean things up. One more important fix is setting the frequency on the channel before starting playback, so avoid the frequency potentially being adjusted after the playback is already started. --- osu.Game/Overlays/Volume/VolumeMeter.cs | 63 +++++++++++++------------ 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 6a26de204c..3321dcf329 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -38,7 +38,6 @@ namespace osu.Game.Overlays.Volume private OsuSpriteText text; private BufferedContainer maxGlow; - private bool firstUpdate = true; private Sample sample; private double sampleLastPlaybackTime; @@ -187,16 +186,12 @@ namespace osu.Game.Overlays.Volume } }; - Bindable.ValueChanged += volume => { this.TransformTo(nameof(DisplayVolume), volume.NewValue, 400, Easing.OutQuint); }; + Bindable.BindValueChanged(volume => { this.TransformTo(nameof(DisplayVolume), volume.NewValue, 400, Easing.OutQuint); }, true); bgProgress.Current.Value = 0.75f; } - protected override void LoadComplete() - { - base.LoadComplete(); - Bindable.TriggerChange(); - } + private int displayVolumeInt; private double displayVolume; @@ -205,9 +200,16 @@ namespace osu.Game.Overlays.Volume get => displayVolume; set { - bool displayVolumeChanged = Math.Round(displayVolume * 100) != Math.Round(value * 100); + if (value == displayVolume) + return; + displayVolume = value; + int intValue = (int)Math.Round(displayVolume * 100); + bool intVolumeChanged = intValue != displayVolumeInt; + + displayVolumeInt = intValue; + if (displayVolume >= 0.995f) { text.Text = "MAX"; @@ -216,37 +218,36 @@ namespace osu.Game.Overlays.Volume else { maxGlow.EffectColour = Color4.Transparent; - text.Text = Math.Round(displayVolume * 100).ToString(CultureInfo.CurrentCulture); + text.Text = displayVolumeInt.ToString(CultureInfo.CurrentCulture); } volumeCircle.Current.Value = displayVolume * 0.75f; volumeCircleGlow.Current.Value = displayVolume * 0.75f; - Schedule(() => - { - const int sfx_debounce_time = 30; - - if (firstUpdate || - !displayVolumeChanged || - Time.Current - sampleLastPlaybackTime <= sfx_debounce_time) - { - firstUpdate = false; - return; - } - - var channel = sample.Play(); - - channel.Frequency.Value = 1 + displayVolume * 0.1f + RNG.NextDouble(0.02f); - if (displayVolume < 0.005f) - channel.Frequency.Value -= 0.5f; - else if (displayVolume > 0.995f) - channel.Frequency.Value -= 0.5f; - - sampleLastPlaybackTime = Time.Current; - }); + if (intVolumeChanged && IsLoaded) + Scheduler.AddOnce(playTickSound); } } + private void playTickSound() + { + const int tick_debounce_time = 30; + + if (Time.Current - sampleLastPlaybackTime <= tick_debounce_time) + return; + + var channel = sample.GetChannel(); + + channel.Frequency.Value = 1 + displayVolume * 0.1f + RNG.NextDouble(0.02f); + + if (displayVolumeInt == 0) + channel.Frequency.Value -= 0.5f; + else if (displayVolumeInt == 100) channel.Frequency.Value -= 0.5f; + + channel.Play(); + sampleLastPlaybackTime = Time.Current; + } + public double Volume { get => Bindable.Value; From bd6664d5414532a384563128581f81a46663d64d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 15:45:50 +0900 Subject: [PATCH 62/69] Add note about intentional downward pitch, against expectations --- osu.Game/Overlays/Volume/VolumeMeter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 3321dcf329..7428c6a7f6 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -242,7 +242,9 @@ namespace osu.Game.Overlays.Volume if (displayVolumeInt == 0) channel.Frequency.Value -= 0.5f; - else if (displayVolumeInt == 100) channel.Frequency.Value -= 0.5f; + else if (displayVolumeInt == 100) + // intentionally pitched down, even when hitting max. + channel.Frequency.Value -= 0.5f; channel.Play(); sampleLastPlaybackTime = Time.Current; From 910fe3e9f8bde8135cb7f8caabad32b0511bca48 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 2 Jul 2021 15:39:43 +0900 Subject: [PATCH 63/69] Center pitch randomisation around base pitch --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 7 +++---- osu.Game/Overlays/Volume/VolumeMeter.cs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 1433f0c38b..386e081e6f 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -161,10 +161,9 @@ namespace osu.Game.Graphics.UserInterface var channel = sample.Play(); - channel.Frequency.Value = 1 + NormalizedValue * 0.2f + RNG.NextDouble(0.02f); - if (NormalizedValue == 0) - channel.Frequency.Value -= 0.5f; - else if (NormalizedValue == 1) + channel.Frequency.Value = 0.99f + RNG.NextDouble(0.02f) + NormalizedValue * 0.2f; + + if (NormalizedValue == 0 || NormalizedValue == 1) channel.Frequency.Value -= 0.5f; } diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 7428c6a7f6..3300d8ee17 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -238,7 +238,7 @@ namespace osu.Game.Overlays.Volume var channel = sample.GetChannel(); - channel.Frequency.Value = 1 + displayVolume * 0.1f + RNG.NextDouble(0.02f); + channel.Frequency.Value = 0.99f + RNG.NextDouble(0.02f) + displayVolume * 0.1f; if (displayVolumeInt == 0) channel.Frequency.Value -= 0.5f; From 63d2ac66d2e3a20863a2d60761d49f357b257f54 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 15:52:20 +0900 Subject: [PATCH 64/69] Fix one more instance of incorrect playback/frequency set order --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 386e081e6f..0ae77071fb 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -159,12 +159,14 @@ namespace osu.Game.Graphics.UserInterface lastSampleValue = value; lastSampleTime = Clock.CurrentTime; - var channel = sample.Play(); + var channel = sample.GetChannel(); channel.Frequency.Value = 0.99f + RNG.NextDouble(0.02f) + NormalizedValue * 0.2f; if (NormalizedValue == 0 || NormalizedValue == 1) channel.Frequency.Value -= 0.5f; + + channel.Play(); } private void updateTooltipText(T value) From 35f79669223a8f6564589fa1069b3ee4a5b9ca29 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 15:55:20 +0900 Subject: [PATCH 65/69] Merge conditionals in line with other case of same logic --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 1 + osu.Game/Overlays/Volume/VolumeMeter.cs | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 0ae77071fb..f85f9327fa 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -163,6 +163,7 @@ namespace osu.Game.Graphics.UserInterface channel.Frequency.Value = 0.99f + RNG.NextDouble(0.02f) + NormalizedValue * 0.2f; + // intentionally pitched down, even when hitting max. if (NormalizedValue == 0 || NormalizedValue == 1) channel.Frequency.Value -= 0.5f; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 3300d8ee17..532b0f4a81 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -240,10 +240,8 @@ namespace osu.Game.Overlays.Volume channel.Frequency.Value = 0.99f + RNG.NextDouble(0.02f) + displayVolume * 0.1f; - if (displayVolumeInt == 0) - channel.Frequency.Value -= 0.5f; - else if (displayVolumeInt == 100) - // intentionally pitched down, even when hitting max. + // intentionally pitched down, even when hitting max. + if (displayVolumeInt == 0 || displayVolumeInt == 100) channel.Frequency.Value -= 0.5f; channel.Play(); From 7b0f970e7db162bf356b33b2977f22c638be15db Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 16:04:51 +0900 Subject: [PATCH 66/69] Fix ongoing operation being begun in an async context --- .../TestSceneMultiplayerReadyButton.cs | 20 +++++++----- .../TestSceneMultiplayerSpectateButton.cs | 32 ++++++++++++------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs index fd9aa922b0..0e036e8868 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs @@ -66,19 +66,23 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnReadyClick = () => Task.Run(async () => + OnReadyClick = () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); - if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + Task.Run(async () => { - await Client.StartMatch(); - return; - } + if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + { + await Client.StartMatch(); + return; + } - await Client.ToggleReady(); - readyClickOperation.Dispose(); - }) + await Client.ToggleReady(); + + readyClickOperation.Dispose(); + }); + } }); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs index a4b0195b00..4966dfbe50 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs @@ -70,31 +70,39 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnSpectateClick = () => Task.Run(async () => + OnSpectateClick = () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); - await Client.ToggleSpectate(); - readyClickOperation.Dispose(); - }) + + Task.Run(async () => + { + await Client.ToggleSpectate(); + readyClickOperation.Dispose(); + }); + } }, readyButton = new MultiplayerReadyButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnReadyClick = () => Task.Run(async () => + OnReadyClick = () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); - if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + Task.Run(async () => { - await Client.StartMatch(); - return; - } + if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + { + await Client.StartMatch(); + return; + } - await Client.ToggleReady(); - readyClickOperation.Dispose(); - }) + await Client.ToggleReady(); + + readyClickOperation.Dispose(); + }); + } } } }; From 6a0c5b54c316899168d39f69db1659dc706a0104 Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Fri, 2 Jul 2021 15:55:25 +0800 Subject: [PATCH 67/69] Fix obsolete message in `Mod.Ranked` --- osu.Game/Rulesets/Mods/Mod.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 40c3761768..6f00bb6c75 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Mods [JsonIgnore] public virtual bool UserPlayable => true; - [Obsolete("Going forward, the concept of \"ranked\" doesn't exist. The only exceptions are automation mods, which should now override and set UserPlayable to true.")] // Can be removed 20211009 + [Obsolete("Going forward, the concept of \"ranked\" doesn't exist. The only exceptions are automation mods, which should now override and set UserPlayable to false.")] // Can be removed 20211009 public virtual bool Ranked => false; /// From d67fc87dcbc27fd0be7a3fd61faf174099fd9e68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 17:24:15 +0900 Subject: [PATCH 68/69] Add some basic testability of external colour setting --- .../Visual/UserInterface/TestSceneColourPicker.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs index 634e45e7a9..fa9179443d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; @@ -14,6 +15,8 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneColourPicker : OsuTestScene { + private readonly Bindable colour = new Bindable(Colour4.Aquamarine); + [SetUpSteps] public void SetUpSteps() { @@ -42,7 +45,8 @@ namespace osu.Game.Tests.Visual.UserInterface new OsuColourPicker { Anchor = Anchor.Centre, - Origin = Anchor.Centre + Origin = Anchor.Centre, + Current = { BindTarget = colour }, } } }, @@ -59,13 +63,18 @@ namespace osu.Game.Tests.Visual.UserInterface new OsuColourPicker { Anchor = Anchor.Centre, - Origin = Anchor.Centre + Origin = Anchor.Centre, + Current = { BindTarget = colour }, } } } } } }); + + AddStep("set green", () => colour.Value = Colour4.LimeGreen); + AddStep("set white", () => colour.Value = Colour4.White); + AddStep("set red", () => colour.Value = Colour4.Red); } private class ColourProvidingContainer : Container From 8847915c6a4322d83562e5cb7f2cf65004f33d01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 18:51:14 +0900 Subject: [PATCH 69/69] 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 2e388b8626..591e00fb27 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 c44857a77d..14efcd516e 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 4772d700da..0ab0b26430 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - +