From 0ec7c11a90f6ec343752ea786a5adf4078c06f7c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 May 2019 19:44:22 +0200 Subject: [PATCH 001/110] implement CatchModRelax --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 0454bc969d..47e32b1292 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -1,12 +1,48 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; +using osuTK; +using System; -namespace osu.Game.Rulesets.Catch.Mods -{ - public class CatchModRelax : ModRelax - { +namespace osu.Game.Rulesets.Catch.Mods { + public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset { public override string Description => @"Use the mouse to control the catcher."; + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) => + (drawableRuleset.Playfield.Parent as Container).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); + + private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { + private CatcherArea.Catcher catcher; + + public CatchModRelaxHelper(CatchPlayfield catchPlayfield) { + catcher = catchPlayfield.CatcherArea.MovableCatcher; + RelativeSizeAxes = Axes.Both; + } + + //disable keyboard controls + public bool OnPressed(CatchAction action) => true; + public bool OnReleased(CatchAction action) => true; + + protected override bool OnMouseMove(MouseMoveEvent e) { + //lock catcher to mouse position horizontally + catcher.X = e.MousePosition.X / DrawSize.X; + + //make Yuzu face the direction he's moving + var direction = Math.Sign(e.Delta.X); + if (direction != 0) + catcher.Scale = new Vector2(Math.Abs(catcher.Scale.X) * direction, catcher.Scale.Y); + + return base.OnMouseMove(e); + } + } } } From 6739238a0dd3620805943806f99637210f9138ca Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 May 2019 10:03:59 +0200 Subject: [PATCH 002/110] formatting --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 47e32b1292..5fa22f8bdb 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -13,17 +13,21 @@ using osu.Game.Rulesets.UI; using osuTK; using System; -namespace osu.Game.Rulesets.Catch.Mods { - public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset { +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset + { public override string Description => @"Use the mouse to control the catcher."; public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) => (drawableRuleset.Playfield.Parent as Container).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); - private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { + private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition + { private CatcherArea.Catcher catcher; - public CatchModRelaxHelper(CatchPlayfield catchPlayfield) { + public CatchModRelaxHelper(CatchPlayfield catchPlayfield) + { catcher = catchPlayfield.CatcherArea.MovableCatcher; RelativeSizeAxes = Axes.Both; } @@ -32,7 +36,8 @@ namespace osu.Game.Rulesets.Catch.Mods { public bool OnPressed(CatchAction action) => true; public bool OnReleased(CatchAction action) => true; - protected override bool OnMouseMove(MouseMoveEvent e) { + protected override bool OnMouseMove(MouseMoveEvent e) + { //lock catcher to mouse position horizontally catcher.X = e.MousePosition.X / DrawSize.X; From cf192c84a8d528f23c949aa70210e1c300fa53e2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 May 2019 10:26:24 +0200 Subject: [PATCH 003/110] make catcher field readonly --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 5fa22f8bdb..9852e753c5 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Mods private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { - private CatcherArea.Catcher catcher; + private readonly CatcherArea.Catcher catcher; public CatchModRelaxHelper(CatchPlayfield catchPlayfield) { From b87478f6e2c3f245c34a5c11e714a74d4c90e9e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 May 2019 11:25:29 +0200 Subject: [PATCH 004/110] replace 'as' with direct cast to avoid possible nullref --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 9852e753c5..062c0f8b26 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Mods public override string Description => @"Use the mouse to control the catcher."; public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) => - (drawableRuleset.Playfield.Parent as Container).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); + ((Container)drawableRuleset.Playfield.Parent).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { From b3a95cac84e2f30bcc4acfb5eb8e4b030f9ad7d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 20:20:11 +0200 Subject: [PATCH 005/110] add invisible cursor for ctb --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 14 ++++++++++++++ osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs new file mode 100644 index 0000000000..073f2e05b2 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -0,0 +1,14 @@ +using osu.Framework.Graphics; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Catch.UI { + class CatchCursorContainer : GameplayCursorContainer + { + protected override Drawable CreateCursor() => new InvisibleCursor(); + + private class InvisibleCursor : Drawable + { + + } + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index b6d8cf9cbe..7741096da2 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.UI internal readonly CatcherArea CatcherArea; + protected override GameplayCursorContainer CreateCursor() => new CatchCursorContainer(); + public CatchPlayfield(BeatmapDifficulty difficulty, Func> createDrawableRepresentation) { Container explodingFruitContainer; From 9079d7a7d83962ae058e33ad75f4ba19bab02f53 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 21:01:51 +0200 Subject: [PATCH 006/110] add license header --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index 073f2e05b2..072c5d4fdf 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -1,4 +1,7 @@ -using osu.Framework.Graphics; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.UI { From cadf0eb228d41b1ed941aef9d6ec11963a625639 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 21:14:27 +0200 Subject: [PATCH 007/110] formatting --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index 072c5d4fdf..642e0bb9de 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -4,7 +4,8 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.UI; -namespace osu.Game.Rulesets.Catch.UI { +namespace osu.Game.Rulesets.Catch.UI +{ class CatchCursorContainer : GameplayCursorContainer { protected override Drawable CreateCursor() => new InvisibleCursor(); From 3aa95f216284ddcc3f39c31dac000aba559903d8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 21:17:06 +0200 Subject: [PATCH 008/110] add missing access modifier --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index 642e0bb9de..d4ac4b2f2e 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.UI { - class CatchCursorContainer : GameplayCursorContainer + public class CatchCursorContainer : GameplayCursorContainer { protected override Drawable CreateCursor() => new InvisibleCursor(); From 69f9d003829c98fd858f9dc0ac458dc64e7c3697 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 21:23:59 +0200 Subject: [PATCH 009/110] more formatting --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index d4ac4b2f2e..03bfad7e8c 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -10,9 +10,6 @@ namespace osu.Game.Rulesets.Catch.UI { protected override Drawable CreateCursor() => new InvisibleCursor(); - private class InvisibleCursor : Drawable - { - - } + private class InvisibleCursor : Drawable { } } } From 2a395956aa4278f7eca532049c88947599f8171e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Sep 2019 19:00:17 +0300 Subject: [PATCH 010/110] Merge dependencies --- .../UserInterface/TestSceneMetricNumbers.cs | 58 +++++++++++++++++++ .../API/Requests/GetCountryRankingsRequest.cs | 18 ++++++ .../Online/API/Requests/GetRankingsRequest.cs | 34 +++++++++++ .../API/Requests/GetUserRankingsRequest.cs | 40 +++++++++++++ .../Requests/Responses/APICountryRankings.cs | 14 +++++ .../API/Requests/Responses/APIUserRankings.cs | 14 +++++ osu.Game/Users/CountryStatistics.cs | 25 ++++++++ osu.Game/Utils/HumanizerUtils.cs | 27 +++++++++ 8 files changed, 230 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs create mode 100644 osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs create mode 100644 osu.Game/Online/API/Requests/GetRankingsRequest.cs create mode 100644 osu.Game/Online/API/Requests/GetUserRankingsRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APICountryRankings.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIUserRankings.cs create mode 100644 osu.Game/Users/CountryStatistics.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs new file mode 100644 index 0000000000..74470f22fc --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Game.Utils; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneMetricNumbers : OsuTestScene + { + public TestSceneMetricNumbers() + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new DrawableNumber(0), + new DrawableNumber(1001), + new DrawableNumber(999_999), + new DrawableNumber(1_000_000), + new DrawableNumber(845_006_456), + new DrawableNumber(999_999_999), + new DrawableNumber(1_000_000_000), + new DrawableNumber(7_875_454_545), + new DrawableNumber(999_999_999_999), + new DrawableNumber(1_000_000_000_000), + new DrawableNumber(687_545_454_554_545), + new DrawableNumber(999_999_999_999_999), + new DrawableNumber(1_000_000_000_000_000), + new DrawableNumber(587_545_454_554_545_455), + new DrawableNumber(999_999_999_999_999_999), + new DrawableNumber(1_000_000_000_000_000_000), + new DrawableNumber(long.MaxValue), + } + }; + } + + private class DrawableNumber : SpriteText, IHasTooltip + { + public string TooltipText => value.ToString("F0"); + + private readonly long value; + + public DrawableNumber(long value) + { + this.value = value; + Text = HumanizerUtils.ToMetric(value); + } + } + } +} diff --git a/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs new file mode 100644 index 0000000000..3bd772732f --- /dev/null +++ b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; + +namespace osu.Game.Online.API.Requests +{ + public class GetCountryRankingsRequest : GetRankingsRequest + { + public GetCountryRankingsRequest(RulesetInfo ruleset, int page = 1) + : base(ruleset, page) + { + } + + protected override string TargetPostfix() => "country"; + } +} diff --git a/osu.Game/Online/API/Requests/GetRankingsRequest.cs b/osu.Game/Online/API/Requests/GetRankingsRequest.cs new file mode 100644 index 0000000000..efaaa2cb40 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetRankingsRequest.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.IO.Network; +using osu.Game.Rulesets; +using System.Collections.Generic; + +namespace osu.Game.Online.API.Requests +{ + public abstract class GetRankingsRequest : APIRequest> + { + private readonly RulesetInfo ruleset; + private readonly int page; + + protected GetRankingsRequest(RulesetInfo ruleset, int page = 1) + { + this.ruleset = ruleset; + this.page = page; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.AddParameter("page", page.ToString()); + + return req; + } + + protected override string Target => $"rankings/{ruleset.ShortName}/{TargetPostfix()}"; + + protected abstract string TargetPostfix(); + } +} diff --git a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs new file mode 100644 index 0000000000..bbba6a210d --- /dev/null +++ b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs @@ -0,0 +1,40 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.IO.Network; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; + +namespace osu.Game.Online.API.Requests +{ + public class GetUserRankingsRequest : GetRankingsRequest + { + private readonly string country; + private readonly UserRankingsType type; + + public GetUserRankingsRequest(RulesetInfo ruleset, UserRankingsType type = UserRankingsType.Performance, int page = 1, string country = null) + : base(ruleset, page) + { + this.type = type; + this.country = country; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + if (country != null) + req.AddParameter("country", country); + + return req; + } + + protected override string TargetPostfix() => type.ToString().ToLowerInvariant(); + } + + public enum UserRankingsType + { + Performance, + Score + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs b/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs new file mode 100644 index 0000000000..91086876a9 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APICountryRankings : CountryStatistics + { + [JsonProperty] + public Country Country; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs b/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs new file mode 100644 index 0000000000..1cdb6ecb8c --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIUserRankings : UserStatistics + { + [JsonProperty] + public User User; + } +} diff --git a/osu.Game/Users/CountryStatistics.cs b/osu.Game/Users/CountryStatistics.cs new file mode 100644 index 0000000000..53fa70f0d4 --- /dev/null +++ b/osu.Game/Users/CountryStatistics.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; + +namespace osu.Game.Users +{ + public class CountryStatistics + { + [JsonProperty(@"code")] + public string FlagName; + + [JsonProperty(@"active_users")] + public long ActiveUsers; + + [JsonProperty(@"play_count")] + public long PlayCount; + + [JsonProperty(@"ranked_score")] + public long RankedScore; + + [JsonProperty(@"performance")] + public long Performance; + } +} diff --git a/osu.Game/Utils/HumanizerUtils.cs b/osu.Game/Utils/HumanizerUtils.cs index 5b7c3630d9..ee6f6f95a3 100644 --- a/osu.Game/Utils/HumanizerUtils.cs +++ b/osu.Game/Utils/HumanizerUtils.cs @@ -26,5 +26,32 @@ namespace osu.Game.Utils return input.Humanize(culture: new CultureInfo("en-US")); } } + + /// + /// Turns the current or provided big number into a readable string. + /// + /// The number to be humanized. + /// Simplified number with a suffix. + public static string ToMetric(long input) + { + const int k = 1000; + + if (input < k) + return input.ToString(); + + int i = (int)Math.Floor(Math.Round(Math.Log(input, k))); + return $"{input / Math.Pow(k, i):F} {suffixes[i]}"; + } + + private static readonly string[] suffixes = new[] + { + "", + "k", + "million", + "billion", + "trillion", + "quadrillion", + "quintillion", + }; } } From bbaf21a69d0d025019e8cd9035485e473e0006d4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 27 Sep 2019 19:33:52 +0300 Subject: [PATCH 011/110] Tables implementation --- .../Visual/Online/TestSceneRankingsTables.cs | 148 ++++++++++++++++++ .../Rankings/Tables/CountriesTable.cs | 88 +++++++++++ .../Rankings/Tables/PerformanceTable.cs | 102 ++++++++++++ .../Overlays/Rankings/Tables/RankingsTable.cs | 128 +++++++++++++++ .../Overlays/Rankings/Tables/ScoresTable.cs | 108 +++++++++++++ .../Rankings/Tables/TableRowBackground.cs | 56 +++++++ 6 files changed, 630 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs create mode 100644 osu.Game/Overlays/Rankings/Tables/CountriesTable.cs create mode 100644 osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs create mode 100644 osu.Game/Overlays/Rankings/Tables/RankingsTable.cs create mode 100644 osu.Game/Overlays/Rankings/Tables/ScoresTable.cs create mode 100644 osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs new file mode 100644 index 0000000000..08a6da734f --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs @@ -0,0 +1,148 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays.Rankings.Tables; +using osu.Framework.Graphics; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; +using osu.Game.Graphics.UserInterface; +using System.Threading; +using osu.Game.Online.API; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; +using osu.Framework.Allocation; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsTables : OsuTestScene + { + protected override bool UseOnlineAPI => true; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(PerformanceTable), + typeof(ScoresTable), + typeof(CountriesTable), + typeof(TableRowBackground), + }; + + [Resolved] + private IAPIProvider api { get; set; } + + private readonly BasicScrollContainer scrollFlow; + private readonly DimmedLoadingLayer loading; + private CancellationTokenSource cancellationToken; + private APIRequest request; + + public TestSceneRankingsTables() + { + Children = new Drawable[] + { + scrollFlow = new BasicScrollContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Width = 0.8f, + }, + loading = new DimmedLoadingLayer(), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + AddStep("Osu performance", () => createPerformanceTable(new OsuRuleset().RulesetInfo, null)); + AddStep("Mania scores", () => createScoreTable(new ManiaRuleset().RulesetInfo)); + AddStep("Taiko country scores", () => createCountryTable(new TaikoRuleset().RulesetInfo)); + AddStep("Catch US performance page 10", () => createPerformanceTable(new CatchRuleset().RulesetInfo, "US", 10)); + } + + private void createCountryTable(RulesetInfo ruleset, int page = 1) + { + loading.Show(); + + request?.Cancel(); + cancellationToken?.Cancel(); + cancellationToken = new CancellationTokenSource(); + + request = new GetCountryRankingsRequest(ruleset, page); + ((GetCountryRankingsRequest)request).Success += rankings => Schedule(() => + { + var table = new CountriesTable(page) + { + Rankings = rankings, + }; + + LoadComponentAsync(table, t => + { + scrollFlow.Clear(); + scrollFlow.Add(t); + loading.Hide(); + }, cancellationToken.Token); + }); + + api.Queue(request); + } + + private void createPerformanceTable(RulesetInfo ruleset, string country, int page = 1) + { + loading.Show(); + + request?.Cancel(); + cancellationToken?.Cancel(); + cancellationToken = new CancellationTokenSource(); + + request = new GetUserRankingsRequest(ruleset, country: country, page: page); + ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => + { + var table = new PerformanceTable(page) + { + Rankings = rankings, + }; + + LoadComponentAsync(table, t => + { + scrollFlow.Clear(); + scrollFlow.Add(t); + loading.Hide(); + }, cancellationToken.Token); + }); + + api.Queue(request); + } + + private void createScoreTable(RulesetInfo ruleset, int page = 1) + { + loading.Show(); + + request?.Cancel(); + cancellationToken?.Cancel(); + cancellationToken = new CancellationTokenSource(); + + request = new GetUserRankingsRequest(ruleset, UserRankingsType.Score, page); + ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => + { + var table = new ScoresTable(page) + { + Rankings = rankings, + }; + + LoadComponentAsync(table, t => + { + scrollFlow.Clear(); + scrollFlow.Add(t); + loading.Hide(); + }, cancellationToken.Token); + }); + + api.Queue(request); + } + } +} diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs new file mode 100644 index 0000000000..cfd404ff07 --- /dev/null +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -0,0 +1,88 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Users.Drawables; +using osuTK; +using osu.Game.Online.API.Requests.Responses; +using System; + +namespace osu.Game.Overlays.Rankings.Tables +{ + public class CountriesTable : RankingsTable + { + public CountriesTable(int page = 1) + : base(page) + { + } + + protected override TableColumn[] CreateHeaders() => new[] + { + new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place + new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and country name + new TableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), + new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), + new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), + new TableColumn("Avg. Score", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), + new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), + new TableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), + }; + + protected override Drawable[] CreateContent(int index, APICountryRankings item) => new Drawable[] + { + new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] + { + new UpdateableFlag(item.Country) + { + Size = new Vector2(20, 13), + ShowPlaceholderOnNull = false, + }, + new OsuSpriteText + { + Text = $@"{item.Country.FullName}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + } + } + }, + new ColoredText + { + Text = $@"{item.ActiveUsers:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredMetricNumber(item.PlayCount) + { + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredMetricNumber(item.RankedScore) + { + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredMetricNumber(item.RankedScore / Math.Max(item.ActiveUsers, 1)) + { + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new MetricNumber(item.Performance) + { + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.Performance / Math.Max(item.ActiveUsers, 1):N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + } + }; + } +} diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs new file mode 100644 index 0000000000..eab3e67f39 --- /dev/null +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -0,0 +1,102 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using System.Collections.Generic; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Users.Drawables; +using osuTK; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Overlays.Rankings.Tables +{ + public class PerformanceTable : RankingsTable + { + public PerformanceTable(int page = 1) + : base(page) + { + } + + protected override TableColumn[] CreateHeaders() => new[] + { + new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place + new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username + new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), + new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), + new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), + new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), + new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), + new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), + }; + + protected override Drawable[] CreateContent(int index, APIUserRankings item) + { + var content = new List + { + new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) + }, + }; + + var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; + username.AddUserLink(item.User); + + content.Add(new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] + { + new UpdateableFlag(item.User.Country) + { + Size = new Vector2(20, 13), + ShowPlaceholderOnNull = false, + }, + username + } + }); + + content.AddRange(new Drawable[] + { + new ColoredText + { + Text = $@"{item.Accuracy:F2}%", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.PlayCount:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new OsuSpriteText + { + Text = $@"{item.PP:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.GradesCount.A:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + }); + + return content.ToArray(); + } + } +} diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs new file mode 100644 index 0000000000..0734004913 --- /dev/null +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -0,0 +1,128 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics.Cursor; +using osu.Game.Utils; + +namespace osu.Game.Overlays.Rankings.Tables +{ + public abstract class RankingsTable : TableContainer + { + protected const int TEXT_SIZE = 14; + private const float horizontal_inset = 20; + private const float row_height = 25; + private const int items_per_page = 50; + + private readonly int page; + private readonly FillFlowContainer backgroundFlow; + + public IReadOnlyList Rankings + { + set + { + Content = null; + backgroundFlow.Clear(); + + if (value?.Any() != true) + return; + + value.ForEach(_ => backgroundFlow.Add(new TableRowBackground())); + + Columns = CreateHeaders(); + Content = value.Select((s, i) => CreateContent(page * items_per_page - (items_per_page - i), s)).ToArray().ToRectangular(); + } + } + + protected RankingsTable(int page) + { + this.page = page; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Padding = new MarginPadding { Horizontal = horizontal_inset }; + RowSize = new Dimension(GridSizeMode.Absolute, row_height); + + AddInternal(backgroundFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Depth = 1f, + Margin = new MarginPadding { Top = row_height } + }); + } + + protected abstract TableColumn[] CreateHeaders(); + + protected abstract Drawable[] CreateContent(int index, TModel item); + + protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty, HighlightedColumn()); + + protected virtual string HighlightedColumn() => @"Performance"; + + private class HeaderText : OsuSpriteText + { + private readonly string highlighted; + + public HeaderText(string text, string highlighted) + { + this.highlighted = highlighted; + + Text = text; + Font = OsuFont.GetFont(size: 12); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + if (Text != highlighted) + Colour = colours.GreySeafoamLighter; + } + } + + protected class MetricNumber : OsuSpriteText, IHasTooltip + { + public string TooltipText => $"{value:N0}"; + + private readonly long value; + + public MetricNumber(long value) + { + this.value = value; + + Text = HumanizerUtils.ToMetric(value); + } + } + + protected class ColoredMetricNumber : MetricNumber + { + public ColoredMetricNumber(long value) + : base(value) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.GreySeafoamLighter; + } + } + + protected class ColoredText : OsuSpriteText + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.GreySeafoamLighter; + } + } + } +} diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs new file mode 100644 index 0000000000..561b08472b --- /dev/null +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -0,0 +1,108 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Users.Drawables; +using osuTK; +using osu.Game.Online.API.Requests.Responses; +using System.Collections.Generic; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Overlays.Rankings.Tables +{ + public class ScoresTable : RankingsTable + { + public ScoresTable(int page = 1) + : base(page) + { + } + + protected override TableColumn[] CreateHeaders() => new[] + { + new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place + new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username + new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), + new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), + new TableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), + new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), + new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), + new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), + new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), + }; + + protected override Drawable[] CreateContent(int index, APIUserRankings item) + { + var content = new List + { + new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) + }, + }; + + var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; + username.AddUserLink(item.User); + + content.Add(new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] + { + new UpdateableFlag(item.User.Country) + { + Size = new Vector2(20, 13), + ShowPlaceholderOnNull = false, + }, + username + } + }); + + content.AddRange(new Drawable[] + { + new ColoredText + { + Text = $@"{item.Accuracy:F2}%", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.PlayCount:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredMetricNumber(item.TotalScore) + { + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new MetricNumber(item.RankedScore) + { + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + new ColoredText + { + Text = $@"{item.GradesCount.A:N0}", + Font = OsuFont.GetFont(size: TEXT_SIZE), + }, + }); + + return content.ToArray(); + } + + protected override string HighlightedColumn() => @"Ranked Score"; + } +} diff --git a/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs b/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs new file mode 100644 index 0000000000..04e1c22dae --- /dev/null +++ b/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Rankings.Tables +{ + public class TableRowBackground : CompositeDrawable + { + private const int fade_duration = 100; + + private readonly Box background; + + private Color4 idleColour; + private Color4 hoverColour; + + public TableRowBackground() + { + RelativeSizeAxes = Axes.X; + Height = 25; + + CornerRadius = 3; + Masking = true; + + InternalChild = background = new Box + { + RelativeSizeAxes = Axes.Both, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = idleColour = colours.GreySeafoam; + hoverColour = colours.GreySeafoamLight; + } + + protected override bool OnHover(HoverEvent e) + { + background.FadeColour(hoverColour, fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + background.FadeColour(idleColour, fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } +} From 883ee9851af74ae0695e9731df269685f9a7ad70 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 29 Sep 2019 15:02:33 +0300 Subject: [PATCH 012/110] Update dependencies --- .../Visual/UserInterface/TestSceneMetricNumbers.cs | 2 +- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 2 +- osu.Game/Utils/HumanizerUtils.cs | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs index 74470f22fc..8e3924e1fb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs @@ -51,7 +51,7 @@ namespace osu.Game.Tests.Visual.UserInterface public DrawableNumber(long value) { this.value = value; - Text = HumanizerUtils.ToMetric(value); + Text = HumanizerUtils.ToReadableString(value); } } } diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 0734004913..d05d642051 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -98,7 +98,7 @@ namespace osu.Game.Overlays.Rankings.Tables { this.value = value; - Text = HumanizerUtils.ToMetric(value); + Text = HumanizerUtils.ToReadableString(value); } } diff --git a/osu.Game/Utils/HumanizerUtils.cs b/osu.Game/Utils/HumanizerUtils.cs index ee6f6f95a3..bc710a799d 100644 --- a/osu.Game/Utils/HumanizerUtils.cs +++ b/osu.Game/Utils/HumanizerUtils.cs @@ -32,7 +32,7 @@ namespace osu.Game.Utils /// /// The number to be humanized. /// Simplified number with a suffix. - public static string ToMetric(long input) + public static string ToReadableString(long input) { const int k = 1000; @@ -42,8 +42,7 @@ namespace osu.Game.Utils int i = (int)Math.Floor(Math.Round(Math.Log(input, k))); return $"{input / Math.Pow(k, i):F} {suffixes[i]}"; } - - private static readonly string[] suffixes = new[] + private static readonly string[] suffixes = { "", "k", From 138e65d7a49c0d9df0c5648148bc8e490b40542f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 29 Sep 2019 15:15:41 +0300 Subject: [PATCH 013/110] Add missing blank line --- osu.Game/Utils/HumanizerUtils.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Utils/HumanizerUtils.cs b/osu.Game/Utils/HumanizerUtils.cs index bc710a799d..9920f7d127 100644 --- a/osu.Game/Utils/HumanizerUtils.cs +++ b/osu.Game/Utils/HumanizerUtils.cs @@ -42,6 +42,7 @@ namespace osu.Game.Utils int i = (int)Math.Floor(Math.Round(Math.Log(input, k))); return $"{input / Math.Pow(k, i):F} {suffixes[i]}"; } + private static readonly string[] suffixes = { "", From febe0175cd6f6c3b594e2cf2b8dd2e1b1c59f0e0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 29 Sep 2019 15:27:29 +0300 Subject: [PATCH 014/110] Small cleanups --- .../Rankings/Tables/CountriesTable.cs | 22 ++------- .../Rankings/Tables/PerformanceTable.cs | 36 ++++++--------- .../Overlays/Rankings/Tables/RankingsTable.cs | 6 +++ .../Overlays/Rankings/Tables/ScoresTable.cs | 46 +++++++------------ 4 files changed, 42 insertions(+), 68 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index cfd404ff07..96ff506814 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -60,28 +60,14 @@ namespace osu.Game.Overlays.Rankings.Tables new ColoredText { Text = $@"{item.ActiveUsers:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), - }, - new ColoredMetricNumber(item.PlayCount) - { - Font = OsuFont.GetFont(size: TEXT_SIZE), - }, - new ColoredMetricNumber(item.RankedScore) - { - Font = OsuFont.GetFont(size: TEXT_SIZE), - }, - new ColoredMetricNumber(item.RankedScore / Math.Max(item.ActiveUsers, 1)) - { - Font = OsuFont.GetFont(size: TEXT_SIZE), - }, - new MetricNumber(item.Performance) - { - Font = OsuFont.GetFont(size: TEXT_SIZE), }, + new ColoredMetricNumber(item.PlayCount), + new ColoredMetricNumber(item.RankedScore), + new ColoredMetricNumber(item.RankedScore / Math.Max(item.ActiveUsers, 1)), + new MetricNumber(item.Performance), new ColoredText { Text = $@"{item.Performance / Math.Max(item.ActiveUsers, 1):N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), } }; } diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index eab3e67f39..c79553a3be 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -46,33 +46,30 @@ namespace osu.Game.Overlays.Rankings.Tables var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; username.AddUserLink(item.User); - content.Add(new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), - Children = new Drawable[] - { - new UpdateableFlag(item.User.Country) - { - Size = new Vector2(20, 13), - ShowPlaceholderOnNull = false, - }, - username - } - }); - content.AddRange(new Drawable[] { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] + { + new UpdateableFlag(item.User.Country) + { + Size = new Vector2(20, 13), + ShowPlaceholderOnNull = false, + }, + username + } + }, new ColoredText { Text = $@"{item.Accuracy:F2}%", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, new ColoredText { Text = $@"{item.PlayCount:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, new OsuSpriteText { @@ -82,17 +79,14 @@ namespace osu.Game.Overlays.Rankings.Tables new ColoredText { Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, new ColoredText { Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, new ColoredText { Text = $@"{item.GradesCount.A:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, }); diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index d05d642051..6c53a9fa74 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -99,6 +99,7 @@ namespace osu.Game.Overlays.Rankings.Tables this.value = value; Text = HumanizerUtils.ToReadableString(value); + Font = OsuFont.GetFont(size: TEXT_SIZE); } } @@ -118,6 +119,11 @@ namespace osu.Game.Overlays.Rankings.Tables protected class ColoredText : OsuSpriteText { + public ColoredText() + { + Font = OsuFont.GetFont(size: TEXT_SIZE); + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 561b08472b..1c8b474689 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -47,56 +47,44 @@ namespace osu.Game.Overlays.Rankings.Tables var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; username.AddUserLink(item.User); - content.Add(new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), - Children = new Drawable[] - { - new UpdateableFlag(item.User.Country) - { - Size = new Vector2(20, 13), - ShowPlaceholderOnNull = false, - }, - username - } - }); - content.AddRange(new Drawable[] { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] + { + new UpdateableFlag(item.User.Country) + { + Size = new Vector2(20, 13), + ShowPlaceholderOnNull = false, + }, + username + } + }, new ColoredText { Text = $@"{item.Accuracy:F2}%", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, new ColoredText { Text = $@"{item.PlayCount:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), - }, - new ColoredMetricNumber(item.TotalScore) - { - Font = OsuFont.GetFont(size: TEXT_SIZE), - }, - new MetricNumber(item.RankedScore) - { - Font = OsuFont.GetFont(size: TEXT_SIZE), }, + new ColoredMetricNumber(item.TotalScore), + new MetricNumber(item.RankedScore), new ColoredText { Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, new ColoredText { Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, new ColoredText { Text = $@"{item.GradesCount.A:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, }); From ff477cd56c36eb99a8e238dd0de607fc5f3a6222 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 1 Oct 2019 14:12:03 +0300 Subject: [PATCH 015/110] Remove humanized number dependency --- .../UserInterface/TestSceneMetricNumbers.cs | 58 ------------------- .../Rankings/Tables/CountriesTable.cs | 27 ++++++--- .../Rankings/Tables/PerformanceTable.cs | 13 ++--- .../Overlays/Rankings/Tables/RankingsTable.cs | 34 +---------- .../Overlays/Rankings/Tables/ScoresTable.cs | 20 ++++--- osu.Game/Utils/HumanizerUtils.cs | 27 --------- 6 files changed, 41 insertions(+), 138 deletions(-) delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs deleted file mode 100644 index 8e3924e1fb..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneMetricNumbers.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Sprites; -using osu.Game.Utils; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneMetricNumbers : OsuTestScene - { - public TestSceneMetricNumbers() - { - Child = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new DrawableNumber(0), - new DrawableNumber(1001), - new DrawableNumber(999_999), - new DrawableNumber(1_000_000), - new DrawableNumber(845_006_456), - new DrawableNumber(999_999_999), - new DrawableNumber(1_000_000_000), - new DrawableNumber(7_875_454_545), - new DrawableNumber(999_999_999_999), - new DrawableNumber(1_000_000_000_000), - new DrawableNumber(687_545_454_554_545), - new DrawableNumber(999_999_999_999_999), - new DrawableNumber(1_000_000_000_000_000), - new DrawableNumber(587_545_454_554_545_455), - new DrawableNumber(999_999_999_999_999_999), - new DrawableNumber(1_000_000_000_000_000_000), - new DrawableNumber(long.MaxValue), - } - }; - } - - private class DrawableNumber : SpriteText, IHasTooltip - { - public string TooltipText => value.ToString("F0"); - - private readonly long value; - - public DrawableNumber(long value) - { - this.value = value; - Text = HumanizerUtils.ToReadableString(value); - } - } - } -} diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index 96ff506814..8e0e55595d 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -50,22 +50,33 @@ namespace osu.Game.Overlays.Rankings.Tables Size = new Vector2(20, 13), ShowPlaceholderOnNull = false, }, - new OsuSpriteText + new RowText { Text = $@"{item.Country.FullName}", - Font = OsuFont.GetFont(size: TEXT_SIZE), } } }, - new ColoredText + new ColoredRowText { Text = $@"{item.ActiveUsers:N0}", }, - new ColoredMetricNumber(item.PlayCount), - new ColoredMetricNumber(item.RankedScore), - new ColoredMetricNumber(item.RankedScore / Math.Max(item.ActiveUsers, 1)), - new MetricNumber(item.Performance), - new ColoredText + new ColoredRowText + { + Text = $@"{item.PlayCount:N0}", + }, + new ColoredRowText + { + Text = $@"{item.RankedScore:N0}", + }, + new ColoredRowText + { + Text = $@"{item.RankedScore / Math.Max(item.ActiveUsers, 1):N0}", + }, + new RowText + { + Text = $@"{item.Performance:N0}", + }, + new ColoredRowText { Text = $@"{item.Performance / Math.Max(item.ActiveUsers, 1):N0}", } diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index c79553a3be..2d582f4321 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -63,28 +63,27 @@ namespace osu.Game.Overlays.Rankings.Tables username } }, - new ColoredText + new ColoredRowText { Text = $@"{item.Accuracy:F2}%", }, - new ColoredText + new ColoredRowText { Text = $@"{item.PlayCount:N0}", }, - new OsuSpriteText + new RowText { Text = $@"{item.PP:N0}", - Font = OsuFont.GetFont(size: TEXT_SIZE), }, - new ColoredText + new ColoredRowText { Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", }, - new ColoredText + new ColoredRowText { Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", }, - new ColoredText + new ColoredRowText { Text = $@"{item.GradesCount.A:N0}", }, diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 6c53a9fa74..a04e8be9d0 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -10,8 +10,6 @@ using osu.Framework.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics.Cursor; -using osu.Game.Utils; namespace osu.Game.Overlays.Rankings.Tables { @@ -88,42 +86,16 @@ namespace osu.Game.Overlays.Rankings.Tables } } - protected class MetricNumber : OsuSpriteText, IHasTooltip + protected class RowText : OsuSpriteText { - public string TooltipText => $"{value:N0}"; - - private readonly long value; - - public MetricNumber(long value) + public RowText() { - this.value = value; - - Text = HumanizerUtils.ToReadableString(value); Font = OsuFont.GetFont(size: TEXT_SIZE); } } - protected class ColoredMetricNumber : MetricNumber + protected class ColoredRowText : RowText { - public ColoredMetricNumber(long value) - : base(value) - { - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Colour = colours.GreySeafoamLighter; - } - } - - protected class ColoredText : OsuSpriteText - { - public ColoredText() - { - Font = OsuFont.GetFont(size: TEXT_SIZE); - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 1c8b474689..5d572a6af0 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -64,25 +64,31 @@ namespace osu.Game.Overlays.Rankings.Tables username } }, - new ColoredText + new ColoredRowText { Text = $@"{item.Accuracy:F2}%", }, - new ColoredText + new ColoredRowText { Text = $@"{item.PlayCount:N0}", }, - new ColoredMetricNumber(item.TotalScore), - new MetricNumber(item.RankedScore), - new ColoredText + new ColoredRowText + { + Text = $@"{item.TotalScore:N0}", + }, + new RowText + { + Text = $@"{item.RankedScore:N0}", + }, + new ColoredRowText { Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", }, - new ColoredText + new ColoredRowText { Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", }, - new ColoredText + new ColoredRowText { Text = $@"{item.GradesCount.A:N0}", }, diff --git a/osu.Game/Utils/HumanizerUtils.cs b/osu.Game/Utils/HumanizerUtils.cs index 9920f7d127..5b7c3630d9 100644 --- a/osu.Game/Utils/HumanizerUtils.cs +++ b/osu.Game/Utils/HumanizerUtils.cs @@ -26,32 +26,5 @@ namespace osu.Game.Utils return input.Humanize(culture: new CultureInfo("en-US")); } } - - /// - /// Turns the current or provided big number into a readable string. - /// - /// The number to be humanized. - /// Simplified number with a suffix. - public static string ToReadableString(long input) - { - const int k = 1000; - - if (input < k) - return input.ToString(); - - int i = (int)Math.Floor(Math.Round(Math.Log(input, k))); - return $"{input / Math.Pow(k, i):F} {suffixes[i]}"; - } - - private static readonly string[] suffixes = - { - "", - "k", - "million", - "billion", - "trillion", - "quadrillion", - "quintillion", - }; } } From 2f703090ef1996c34eb4db392a894f015cdb0130 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 1 Nov 2019 21:49:50 +0300 Subject: [PATCH 016/110] Update API with latest web changes --- .../Visual/Online/TestSceneRankingsTables.cs | 6 +++--- .../Online/API/Requests/GetCountriesResponse.cs | 15 +++++++++++++++ .../API/Requests/GetCountryRankingsRequest.cs | 3 +-- .../Online/API/Requests/GetRankingsRequest.cs | 3 +-- .../Online/API/Requests/GetUserRankingsRequest.cs | 3 +-- osu.Game/Online/API/Requests/GetUsersResponse.cs | 2 +- 6 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 osu.Game/Online/API/Requests/GetCountriesResponse.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs index 08a6da734f..49656900cc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs @@ -77,7 +77,7 @@ namespace osu.Game.Tests.Visual.Online { var table = new CountriesTable(page) { - Rankings = rankings, + Rankings = rankings.Countries, }; LoadComponentAsync(table, t => @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Online { var table = new PerformanceTable(page) { - Rankings = rankings, + Rankings = rankings.Users, }; LoadComponentAsync(table, t => @@ -131,7 +131,7 @@ namespace osu.Game.Tests.Visual.Online { var table = new ScoresTable(page) { - Rankings = rankings, + Rankings = rankings.Users, }; LoadComponentAsync(table, t => diff --git a/osu.Game/Online/API/Requests/GetCountriesResponse.cs b/osu.Game/Online/API/Requests/GetCountriesResponse.cs new file mode 100644 index 0000000000..7b65c6fadd --- /dev/null +++ b/osu.Game/Online/API/Requests/GetCountriesResponse.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using Newtonsoft.Json; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetCountriesResponse : ResponseWithCursor + { + [JsonProperty("ranking")] + public List Countries; + } +} diff --git a/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs index 3bd772732f..d8a1198627 100644 --- a/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests { - public class GetCountryRankingsRequest : GetRankingsRequest + public class GetCountryRankingsRequest : GetRankingsRequest { public GetCountryRankingsRequest(RulesetInfo ruleset, int page = 1) : base(ruleset, page) diff --git a/osu.Game/Online/API/Requests/GetRankingsRequest.cs b/osu.Game/Online/API/Requests/GetRankingsRequest.cs index efaaa2cb40..941691c4c1 100644 --- a/osu.Game/Online/API/Requests/GetRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetRankingsRequest.cs @@ -3,11 +3,10 @@ using osu.Framework.IO.Network; using osu.Game.Rulesets; -using System.Collections.Generic; namespace osu.Game.Online.API.Requests { - public abstract class GetRankingsRequest : APIRequest> + public abstract class GetRankingsRequest : APIRequest { private readonly RulesetInfo ruleset; private readonly int page; diff --git a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs index bbba6a210d..9c3eba9fdc 100644 --- a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs @@ -2,12 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.IO.Network; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests { - public class GetUserRankingsRequest : GetRankingsRequest + public class GetUserRankingsRequest : GetRankingsRequest { private readonly string country; private readonly UserRankingsType type; diff --git a/osu.Game/Online/API/Requests/GetUsersResponse.cs b/osu.Game/Online/API/Requests/GetUsersResponse.cs index 860785875a..c60bc71096 100644 --- a/osu.Game/Online/API/Requests/GetUsersResponse.cs +++ b/osu.Game/Online/API/Requests/GetUsersResponse.cs @@ -10,6 +10,6 @@ namespace osu.Game.Online.API.Requests public class GetUsersResponse : ResponseWithCursor { [JsonProperty("ranking")] - public List Users; + public List Users; } } From 48385dbdfe2dfbe685fbd03a8ca09206a794c4e1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 3 Nov 2019 14:31:23 +0300 Subject: [PATCH 017/110] Layout adjustments --- .../Overlays/Rankings/Tables/CountriesTable.cs | 12 ++++++------ .../Overlays/Rankings/Tables/PerformanceTable.cs | 12 ++++++------ osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 1 + osu.Game/Overlays/Rankings/Tables/ScoresTable.cs | 14 +++++++------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index 8e0e55595d..386225a606 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -23,12 +23,12 @@ namespace osu.Game.Overlays.Rankings.Tables { new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and country name - new TableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), - new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), - new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), - new TableColumn("Avg. Score", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), - new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), - new TableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), + new TableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Avg. Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; protected override Drawable[] CreateContent(int index, APICountryRankings item) => new Drawable[] diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 2d582f4321..11357a82a1 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -24,12 +24,12 @@ namespace osu.Game.Overlays.Rankings.Tables { new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username - new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), - new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), - new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), - new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), - new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), - new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), + new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; protected override Drawable[] CreateContent(int index, APIUserRankings item) diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index a04e8be9d0..16dca06c44 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -91,6 +91,7 @@ namespace osu.Game.Overlays.Rankings.Tables public RowText() { Font = OsuFont.GetFont(size: TEXT_SIZE); + Margin = new MarginPadding { Horizontal = 10 }; } } diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 5d572a6af0..0a8ec50e30 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -24,13 +24,13 @@ namespace osu.Game.Overlays.Rankings.Tables { new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username - new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), - new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 80)), - new TableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), - new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 100)), - new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), - new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), - new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), + new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; protected override Drawable[] CreateContent(int index, APIUserRankings item) From 5761cc673f09c2826f909164e9bf7767664bab50 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 May 2019 19:44:22 +0200 Subject: [PATCH 018/110] implement CatchModRelax --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 0454bc969d..47e32b1292 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -1,12 +1,48 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; +using osuTK; +using System; -namespace osu.Game.Rulesets.Catch.Mods -{ - public class CatchModRelax : ModRelax - { +namespace osu.Game.Rulesets.Catch.Mods { + public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset { public override string Description => @"Use the mouse to control the catcher."; + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) => + (drawableRuleset.Playfield.Parent as Container).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); + + private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { + private CatcherArea.Catcher catcher; + + public CatchModRelaxHelper(CatchPlayfield catchPlayfield) { + catcher = catchPlayfield.CatcherArea.MovableCatcher; + RelativeSizeAxes = Axes.Both; + } + + //disable keyboard controls + public bool OnPressed(CatchAction action) => true; + public bool OnReleased(CatchAction action) => true; + + protected override bool OnMouseMove(MouseMoveEvent e) { + //lock catcher to mouse position horizontally + catcher.X = e.MousePosition.X / DrawSize.X; + + //make Yuzu face the direction he's moving + var direction = Math.Sign(e.Delta.X); + if (direction != 0) + catcher.Scale = new Vector2(Math.Abs(catcher.Scale.X) * direction, catcher.Scale.Y); + + return base.OnMouseMove(e); + } + } } } From a842d727c7905af23bb411121ec513292fe240ae Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 May 2019 10:03:59 +0200 Subject: [PATCH 019/110] formatting --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 47e32b1292..5fa22f8bdb 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -13,17 +13,21 @@ using osu.Game.Rulesets.UI; using osuTK; using System; -namespace osu.Game.Rulesets.Catch.Mods { - public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset { +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModRelax : ModRelax, IApplicableToDrawableRuleset + { public override string Description => @"Use the mouse to control the catcher."; public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) => (drawableRuleset.Playfield.Parent as Container).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); - private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { + private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition + { private CatcherArea.Catcher catcher; - public CatchModRelaxHelper(CatchPlayfield catchPlayfield) { + public CatchModRelaxHelper(CatchPlayfield catchPlayfield) + { catcher = catchPlayfield.CatcherArea.MovableCatcher; RelativeSizeAxes = Axes.Both; } @@ -32,7 +36,8 @@ namespace osu.Game.Rulesets.Catch.Mods { public bool OnPressed(CatchAction action) => true; public bool OnReleased(CatchAction action) => true; - protected override bool OnMouseMove(MouseMoveEvent e) { + protected override bool OnMouseMove(MouseMoveEvent e) + { //lock catcher to mouse position horizontally catcher.X = e.MousePosition.X / DrawSize.X; From a8fab4cba1deacc0d154546f2d6fd7bdc3457056 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 May 2019 10:26:24 +0200 Subject: [PATCH 020/110] make catcher field readonly --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 5fa22f8bdb..9852e753c5 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Mods private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { - private CatcherArea.Catcher catcher; + private readonly CatcherArea.Catcher catcher; public CatchModRelaxHelper(CatchPlayfield catchPlayfield) { From 750e3c4aafa1d65e8aed975505fef3ded1c2eeee Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 May 2019 11:25:29 +0200 Subject: [PATCH 021/110] replace 'as' with direct cast to avoid possible nullref --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 9852e753c5..062c0f8b26 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Mods public override string Description => @"Use the mouse to control the catcher."; public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) => - (drawableRuleset.Playfield.Parent as Container).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); + ((Container)drawableRuleset.Playfield.Parent).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { From 8e248d5cfa6f0bd1560f67f2ceeb94a60734800c Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 20:20:11 +0200 Subject: [PATCH 022/110] add invisible cursor for ctb --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 14 ++++++++++++++ osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs new file mode 100644 index 0000000000..073f2e05b2 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -0,0 +1,14 @@ +using osu.Framework.Graphics; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Catch.UI { + class CatchCursorContainer : GameplayCursorContainer + { + protected override Drawable CreateCursor() => new InvisibleCursor(); + + private class InvisibleCursor : Drawable + { + + } + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index b6d8cf9cbe..7741096da2 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.UI internal readonly CatcherArea CatcherArea; + protected override GameplayCursorContainer CreateCursor() => new CatchCursorContainer(); + public CatchPlayfield(BeatmapDifficulty difficulty, Func> createDrawableRepresentation) { Container explodingFruitContainer; From bd5cb86b1546e9c9c7fe6d64f373f5b9766e0500 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 21:01:51 +0200 Subject: [PATCH 023/110] add license header --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index 073f2e05b2..072c5d4fdf 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -1,4 +1,7 @@ -using osu.Framework.Graphics; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.UI { From 883d5ed58edfb1922df3f00e42f5821efdeff15b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 21:14:27 +0200 Subject: [PATCH 024/110] formatting --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index 072c5d4fdf..642e0bb9de 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -4,7 +4,8 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.UI; -namespace osu.Game.Rulesets.Catch.UI { +namespace osu.Game.Rulesets.Catch.UI +{ class CatchCursorContainer : GameplayCursorContainer { protected override Drawable CreateCursor() => new InvisibleCursor(); From 2a0db8aeac74ba0dc41d7ee53c3cf96c10be8829 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 21:17:06 +0200 Subject: [PATCH 025/110] add missing access modifier --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index 642e0bb9de..d4ac4b2f2e 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -6,7 +6,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.UI { - class CatchCursorContainer : GameplayCursorContainer + public class CatchCursorContainer : GameplayCursorContainer { protected override Drawable CreateCursor() => new InvisibleCursor(); From 9570f7c04bc8a4653ee30f82d1abbcb11c0ca661 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 May 2019 21:23:59 +0200 Subject: [PATCH 026/110] more formatting --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index d4ac4b2f2e..03bfad7e8c 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -10,9 +10,6 @@ namespace osu.Game.Rulesets.Catch.UI { protected override Drawable CreateCursor() => new InvisibleCursor(); - private class InvisibleCursor : Drawable - { - - } + private class InvisibleCursor : Drawable { } } } From c180a71afe4e788a6d66043df3b9267ad2dec2ab Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 3 Nov 2019 15:57:52 +0100 Subject: [PATCH 027/110] even more formatting --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index 03bfad7e8c..c596217196 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Catch.UI { protected override Drawable CreateCursor() => new InvisibleCursor(); - private class InvisibleCursor : Drawable { } + private class InvisibleCursor : Drawable { + } } } From 131809838f7cab4413713cb7f2c99a2af9f590aa Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 3 Nov 2019 16:22:07 +0100 Subject: [PATCH 028/110] pleasing CI --- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs index c596217196..163718f202 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs @@ -10,7 +10,8 @@ namespace osu.Game.Rulesets.Catch.UI { protected override Drawable CreateCursor() => new InvisibleCursor(); - private class InvisibleCursor : Drawable { + private class InvisibleCursor : Drawable + { } } } From 423e26a4d147cef6525e9e88b3e86497e3978189 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 13:07:25 +0300 Subject: [PATCH 029/110] Fix header text could be sticked together --- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 16dca06c44..07e2257e8f 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -76,6 +76,7 @@ namespace osu.Game.Overlays.Rankings.Tables Text = text; Font = OsuFont.GetFont(size: 12); + Margin = new MarginPadding { Horizontal = 10 }; } [BackgroundDependencyLoader] From 137f3495e3d5ffa8c84ccec04ba83d3507f195e4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 23 Nov 2019 22:10:27 +0800 Subject: [PATCH 030/110] Use appveyor yml back for build. --- appveyor.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f911d67c6e..b64d56d4f6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,5 +2,10 @@ clone_depth: 1 version: '{branch}-{build}' image: Visual Studio 2019 test: off -build_script: - - cmd: PowerShell -Version 2.0 .\build.ps1 +before_build: + - ps: dotnet --info # Useful when version mismatch between CI and local + - ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects +build: + project: osu.sln + parallel: true + verbosity: minimal From 8479f8531e8c7d6fdfa929f9b65d5e755121f5b7 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 23 Nov 2019 22:20:38 +0800 Subject: [PATCH 031/110] Android package name cannot contain `Catch`. --- .../Properties/AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml index 0fa3b7730d..f8c3fcd894 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,6 @@  - + + \ No newline at end of file From fbb83045f37174556080b8e58b3bf0f926cd1ae8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 23 Nov 2019 23:13:30 +0800 Subject: [PATCH 032/110] Enable tests. --- appveyor.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b64d56d4f6..d8f54f7494 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,6 @@ clone_depth: 1 version: '{branch}-{build}' image: Visual Studio 2019 -test: off before_build: - ps: dotnet --info # Useful when version mismatch between CI and local - ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects @@ -9,3 +8,8 @@ build: project: osu.sln parallel: true verbosity: minimal +test: + assemblies: + except: + - '**\*Android*' + - '**\*iOS*' From 18840c63190d33c480ca407e969be743b4af284c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 24 Nov 2019 16:53:57 +0800 Subject: [PATCH 033/110] Run format check in CI. --- .config/dotnet-tools.json | 6 ++++++ appveyor.yml | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 6ba6ae82c8..e1a2c6025e 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -13,6 +13,12 @@ "commands": [ "dotnet-format" ] + }, + "codefilesanity": { + "version": "0.0.33", + "commands": [ + "CodeFileSanity" + ] } } } \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index d8f54f7494..6c8f073419 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,6 +8,10 @@ build: project: osu.sln parallel: true verbosity: minimal +after_build: + - ps: dotnet tool restore + - ps: dotnet CodeFileSanity + - ps: dotnet format --dry-run --check test: assemblies: except: From 38dae996a18b512a0645580846a7ec3b04319626 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 24 Nov 2019 17:50:48 +0800 Subject: [PATCH 034/110] Add InspectCode to CI. --- .config/dotnet-tools.json | 6 ----- InspectCode.ps1 | 27 ++++++++++++++++++++ appveyor.yml | 2 +- build/InspectCode.cake | 52 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 InspectCode.ps1 create mode 100644 build/InspectCode.cake diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index e1a2c6025e..6ba6ae82c8 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -13,12 +13,6 @@ "commands": [ "dotnet-format" ] - }, - "codefilesanity": { - "version": "0.0.33", - "commands": [ - "CodeFileSanity" - ] } } } \ No newline at end of file diff --git a/InspectCode.ps1 b/InspectCode.ps1 new file mode 100644 index 0000000000..6ed935fdbb --- /dev/null +++ b/InspectCode.ps1 @@ -0,0 +1,27 @@ +[CmdletBinding()] +Param( + [string]$Target, + [string]$Configuration, + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity, + [switch]$ShowDescription, + [Alias("WhatIf", "Noop")] + [switch]$DryRun, + [Parameter(Position = 0, Mandatory = $false, ValueFromRemainingArguments = $true)] + [string[]]$ScriptArgs +) + +# Build Cake arguments +$cakeArguments = ""; +if ($Target) { $cakeArguments += "-target=$Target" } +if ($Configuration) { $cakeArguments += "-configuration=$Configuration" } +if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" } +if ($ShowDescription) { $cakeArguments += "-showdescription" } +if ($DryRun) { $cakeArguments += "-dryrun" } +if ($Experimental) { $cakeArguments += "-experimental" } +$cakeArguments += $ScriptArgs + +dotnet tool restore +dotnet cake ./build/InspectCode.cake --bootstrap +dotnet cake ./build/InspectCode.cake $cakeArguments +exit $LASTEXITCODE \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 6c8f073419..20cf85f44b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,8 +10,8 @@ build: verbosity: minimal after_build: - ps: dotnet tool restore - - ps: dotnet CodeFileSanity - ps: dotnet format --dry-run --check + - ps: .\InspectCode.ps1 test: assemblies: except: diff --git a/build/InspectCode.cake b/build/InspectCode.cake new file mode 100644 index 0000000000..bd3fdf5f93 --- /dev/null +++ b/build/InspectCode.cake @@ -0,0 +1,52 @@ +#addin "nuget:?package=CodeFileSanity&version=0.0.33" +#addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2019.2.1" +#tool "nuget:?package=NVika.MSBuild&version=1.0.1" +var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); + +/////////////////////////////////////////////////////////////////////////////// +// ARGUMENTS +/////////////////////////////////////////////////////////////////////////////// + +var target = Argument("target", "CodeAnalysis"); +var configuration = Argument("configuration", "Release"); + +var rootDirectory = new DirectoryPath(".."); +var sln = rootDirectory.CombineWithFilePath("osu.sln"); +var desktopSlnf = rootDirectory.CombineWithFilePath("osu.Desktop.slnf"); + +/////////////////////////////////////////////////////////////////////////////// +// TASKS +/////////////////////////////////////////////////////////////////////////////// + +// windows only because both inspectcode and nvika depend on net45 +Task("InspectCode") + .WithCriteria(IsRunningOnWindows()) + .Does(() => { + InspectCode(desktopSlnf, new InspectCodeSettings { + CachesHome = "inspectcode", + OutputFile = "inspectcodereport.xml", + ArgumentCustomization = arg => { + if (AppVeyor.IsRunningOnAppVeyor) // Don't flood CI output + arg.Append("--verbosity:WARN"); + return arg; + }, + }); + + int returnCode = StartProcess(nVikaToolPath, $@"parsereport ""inspectcodereport.xml"" --treatwarningsaserrors"); + if (returnCode != 0) + throw new Exception($"inspectcode failed with return code {returnCode}"); + }); + +Task("CodeFileSanity") + .Does(() => { + ValidateCodeSanity(new ValidateCodeSanitySettings { + RootDirectory = rootDirectory.FullPath, + IsAppveyorBuild = AppVeyor.IsRunningOnAppVeyor + }); + }); + +Task("CodeAnalysis") + .IsDependentOn("CodeFileSanity") + .IsDependentOn("InspectCode"); + +RunTarget(target); \ No newline at end of file From 3a62406c581dd533dab5d93c66186d268a292fb4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 24 Nov 2019 19:44:13 +0800 Subject: [PATCH 035/110] Update deploy script. --- appveyor.yml | 2 ++ appveyor_deploy.yml | 12 ++++++++++-- osu.Game/osu.Game.csproj | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 20cf85f44b..7588520e36 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,6 +12,8 @@ after_build: - ps: dotnet tool restore - ps: dotnet format --dry-run --check - ps: .\InspectCode.ps1 +artifacts: + - path: '**\*.nupkg' test: assemblies: except: diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml index fb7825b31d..208ec38977 100644 --- a/appveyor_deploy.yml +++ b/appveyor_deploy.yml @@ -1,10 +1,18 @@ clone_depth: 1 version: '{build}' image: Visual Studio 2019 +before_build: + - ps: dotnet --info # Useful when version mismatch between CI and local + - ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects test: off skip_non_tags: true -build_script: - - cmd: PowerShell -Version 2.0 .\build.ps1 +configuration: Release +build: + project: osu.sln + parallel: true + verbosity: minimal +artifacts: + - path: '**\*.nupkg' deploy: - provider: Environment name: nuget diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 449b4dc4e3..e7614ff395 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -8,6 +8,7 @@ osu! ppy.osu.Game icon.png + true From 575b4db1864fb911b304b45d879b3b9af584651e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 24 Nov 2019 20:39:11 +0800 Subject: [PATCH 036/110] Patch csproj version. --- appveyor.yml | 4 ++++ appveyor_deploy.yml | 6 +++++- osu.Game/osu.Game.csproj | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 7588520e36..333ed94f6e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,10 @@ clone_depth: 1 version: '{branch}-{build}' image: Visual Studio 2019 +dotnet_csproj: + patch: true + file: 'osu.Game\osu.Game.csproj' # Use wildcard when it's able to exclude Xamarin projects + version: '0.0.{build}' before_build: - ps: dotnet --info # Useful when version mismatch between CI and local - ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml index 208ec38977..d8d18028de 100644 --- a/appveyor_deploy.yml +++ b/appveyor_deploy.yml @@ -1,6 +1,10 @@ clone_depth: 1 version: '{build}' image: Visual Studio 2019 +dotnet_csproj: + patch: true + file: 'osu.Game\osu.Game.csproj' # Use wildcard when it's able to exclude Xamarin projects + version: $(APPVEYOR_REPO_TAG_NAME) before_build: - ps: dotnet --info # Useful when version mismatch between CI and local - ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects @@ -8,7 +12,7 @@ test: off skip_non_tags: true configuration: Release build: - project: osu.sln + project: build\Desktop.proj # Skipping Xamarin Release that's slow and covered by fastlane parallel: true verbosity: minimal artifacts: diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e7614ff395..6c25e9e5fe 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -7,6 +7,7 @@ osu! ppy.osu.Game + 0.0.0 icon.png true From 3c6526bbd2afd3f8b5a45086a9c8ee0541aa30b8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Nov 2019 15:59:38 +0800 Subject: [PATCH 037/110] Add nuget http cache --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 333ed94f6e..dbe7ed4cf2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,6 +5,8 @@ dotnet_csproj: patch: true file: 'osu.Game\osu.Game.csproj' # Use wildcard when it's able to exclude Xamarin projects version: '0.0.{build}' +cache: + - '%LOCALAPPDATA%\NuGet\v3-cache' -> appveyor.yml before_build: - ps: dotnet --info # Useful when version mismatch between CI and local - ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects From e31e83deaaa29e7f6e69bd11b65fe445fec3a96f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Nov 2019 16:40:13 +0800 Subject: [PATCH 038/110] Clean up and update readme. --- README.md | 11 ++++++-- build.ps1 | 27 ------------------ build.sh | 17 ----------- build/build.cake | 73 ------------------------------------------------ 4 files changed, 9 insertions(+), 119 deletions(-) delete mode 100755 build.ps1 delete mode 100755 build.sh delete mode 100644 build/build.cake diff --git a/README.md b/README.md index 65fb97eb5d..7bbd43c961 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh - A desktop platform with the [.NET Core SDK 3.0](https://www.microsoft.com/net/learn/get-started) or higher installed. - When running on Linux, please have a system-wide FFmpeg installation available to support video decoding. -- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs. +- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/install/dependencies?tabs=netcore30&pivots=os-windows)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs. +- When developing with mobile, [Xamarin](https://docs.microsoft.com/en-us/xamarin/) is required, which is shipped together with Visual Studio or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). - When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). ## Running osu! @@ -73,13 +74,19 @@ If you are not interested in debugging osu!, you can add `-c Release` to gain pe If the build fails, try to restore NuGet packages with `dotnet restore`. +_Due to historical feature gap between .NET Core and Xamarin, running `dotnet` CLI from the root directory will probably not work. You can try to run the CLI towards single .NET Core project, or helper project at `build/Desktop.proj`. Or you can get help from your IDE of choice to run the correct commands. We are keeping configuration files in the repository for the popular IDEs._ + ### Testing with resource/framework modifications Sometimes it may be necessary to cross-test changes in [osu-resources](https://github.com/ppy/osu-resources) or [osu-framework](https://github.com/ppy/osu-framework). This can be achieved by running some commands as documented on the [osu-resources](https://github.com/ppy/osu-resources/wiki/Testing-local-resources-checkout-with-other-projects) and [osu-framework](https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects) wiki pages. ### Code analysis -Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is currently only supported under Windows due to [ReSharper CLI shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install ReSharper or use Rider to get inline support in your IDE of choice. +Before committing your code, please run code formatter. It can be achieved with command `dotnet format`, or `Format code` command in your IDE. (Defaults to `Ctrl+K,Ctrl+D` in Visual Studio, `Shift+Alt+F` in Visual Studio Code, or `Ctrl+Alt+L` in Rider) + +We have adopted some cross-platform, compiler integrated analyzers. They can provide warnings when you are editing, building inside IDE or from command line, as-if they are provided by the compiler itself. + +JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it from PowerShell with `.\InspectCode.ps1`, which is [only supported on Windows](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install ReSharper or use Rider to get inline support in your IDE of choice. ## Contributing diff --git a/build.ps1 b/build.ps1 deleted file mode 100755 index 4b3b1f717a..0000000000 --- a/build.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -[CmdletBinding()] -Param( - [string]$Target, - [string]$Configuration, - [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] - [string]$Verbosity, - [switch]$ShowDescription, - [Alias("WhatIf", "Noop")] - [switch]$DryRun, - [Parameter(Position = 0, Mandatory = $false, ValueFromRemainingArguments = $true)] - [string[]]$ScriptArgs -) - -# Build Cake arguments -$cakeArguments = ""; -if ($Target) { $cakeArguments += "-target=$Target" } -if ($Configuration) { $cakeArguments += "-configuration=$Configuration" } -if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" } -if ($ShowDescription) { $cakeArguments += "-showdescription" } -if ($DryRun) { $cakeArguments += "-dryrun" } -if ($Experimental) { $cakeArguments += "-experimental" } -$cakeArguments += $ScriptArgs - -dotnet tool restore -dotnet cake ./build/build.cake --bootstrap -dotnet cake ./build/build.cake $cakeArguments -exit $LASTEXITCODE \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100755 index 2c22f08574..0000000000 --- a/build.sh +++ /dev/null @@ -1,17 +0,0 @@ -echo "Installing Cake.Tool..." -dotnet tool restore - -# Parse arguments. -CAKE_ARGUMENTS=() -for i in "$@"; do - case $1 in - -s|--script) SCRIPT="$2"; shift ;; - --) shift; CAKE_ARGUMENTS+=("$@"); break ;; - *) CAKE_ARGUMENTS+=("$1") ;; - esac - shift -done - -echo "Running build script..." -dotnet cake ./build/build.cake --bootstrap -dotnet cake ./build/build.cake "${CAKE_ARGUMENTS[@]}" \ No newline at end of file diff --git a/build/build.cake b/build/build.cake deleted file mode 100644 index 274e57ef4e..0000000000 --- a/build/build.cake +++ /dev/null @@ -1,73 +0,0 @@ -#addin "nuget:?package=CodeFileSanity&version=0.0.33" -#addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2019.2.1" -#tool "nuget:?package=NVika.MSBuild&version=1.0.1" -var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); - -/////////////////////////////////////////////////////////////////////////////// -// ARGUMENTS -/////////////////////////////////////////////////////////////////////////////// - -var target = Argument("target", "Build"); -var configuration = Argument("configuration", "Release"); - -var rootDirectory = new DirectoryPath(".."); -var sln = rootDirectory.CombineWithFilePath("osu.sln"); -var desktopBuilds = rootDirectory.CombineWithFilePath("build/Desktop.proj"); -var desktopSlnf = rootDirectory.CombineWithFilePath("osu.Desktop.slnf"); - -/////////////////////////////////////////////////////////////////////////////// -// TASKS -/////////////////////////////////////////////////////////////////////////////// - -Task("Compile") - .Does(() => { - DotNetCoreBuild(desktopBuilds.FullPath, new DotNetCoreBuildSettings { - Configuration = configuration, - }); - }); - -Task("Test") - .IsDependentOn("Compile") - .Does(() => { - var testAssemblies = GetFiles(rootDirectory + "/**/*.Tests/bin/**/*.Tests.dll"); - - DotNetCoreVSTest(testAssemblies, new DotNetCoreVSTestSettings { - Logger = AppVeyor.IsRunningOnAppVeyor ? "Appveyor" : $"trx", - Parallel = true, - ToolTimeout = TimeSpan.FromMinutes(10), - }); - }); - -// windows only because both inspectcore and nvika depend on net45 -Task("InspectCode") - .WithCriteria(IsRunningOnWindows()) - .IsDependentOn("Compile") - .Does(() => { - InspectCode(desktopSlnf, new InspectCodeSettings { - CachesHome = "inspectcode", - OutputFile = "inspectcodereport.xml", - }); - - int returnCode = StartProcess(nVikaToolPath, $@"parsereport ""inspectcodereport.xml"" --treatwarningsaserrors"); - if (returnCode != 0) - throw new Exception($"inspectcode failed with return code {returnCode}"); - }); - -Task("CodeFileSanity") - .Does(() => { - ValidateCodeSanity(new ValidateCodeSanitySettings { - RootDirectory = rootDirectory.FullPath, - IsAppveyorBuild = AppVeyor.IsRunningOnAppVeyor - }); - }); - -Task("DotnetFormat") - .Does(() => DotNetCoreTool(sln.FullPath, "format", "--dry-run --check")); - -Task("Build") - .IsDependentOn("CodeFileSanity") - .IsDependentOn("DotnetFormat") - .IsDependentOn("InspectCode") - .IsDependentOn("Test"); - -RunTarget(target); \ No newline at end of file From de3079d8e9bfa577914823eaacb594b6eeed82ee Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Nov 2019 17:14:35 +0800 Subject: [PATCH 039/110] Fix appveyor configuration --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index dbe7ed4cf2..f8469f9f80 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ dotnet_csproj: file: 'osu.Game\osu.Game.csproj' # Use wildcard when it's able to exclude Xamarin projects version: '0.0.{build}' cache: - - '%LOCALAPPDATA%\NuGet\v3-cache' -> appveyor.yml + - '%LOCALAPPDATA%\NuGet\v3-cache -> appveyor.yml' before_build: - ps: dotnet --info # Useful when version mismatch between CI and local - ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects @@ -25,3 +25,4 @@ test: except: - '**\*Android*' - '**\*iOS*' + - 'build\**\*' From 9fcc56634121d21a5c34e8153d3c4f0bf23d7e1b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Nov 2019 18:32:41 +0800 Subject: [PATCH 040/110] Change the postition of nupkg artifacts. --- Directory.Build.props | 1 + appveyor.yml | 2 +- appveyor_deploy.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 838851b712..cee459faf9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -36,5 +36,6 @@ ppy Pty Ltd Copyright (c) 2019 ppy Pty Ltd osu game + $(MSBuildThisFileDirectory)artifacts\nupkg\ \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index f8469f9f80..82c0a21aff 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ after_build: - ps: dotnet format --dry-run --check - ps: .\InspectCode.ps1 artifacts: - - path: '**\*.nupkg' + - path: 'artifacts\nupkg\*.nupkg' test: assemblies: except: diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml index d8d18028de..c7f762d425 100644 --- a/appveyor_deploy.yml +++ b/appveyor_deploy.yml @@ -16,7 +16,7 @@ build: parallel: true verbosity: minimal artifacts: - - path: '**\*.nupkg' + - path: 'artifacts\nupkg\*.nupkg' deploy: - provider: Environment name: nuget From 8928f05f4f262c9fdcdb596e5debb95f05d21a5f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 01:39:48 +0800 Subject: [PATCH 041/110] Temporarily remove deepequal test from Android to make CI green. --- osu.Game.Tests.Android/osu.Game.Tests.Android.csproj | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index c2dd194e09..c44ed69c4d 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -24,6 +24,7 @@ %(RecursiveDir)%(Filename)%(Extension) + %(RecursiveDir)%(Filename)%(Extension) @@ -68,10 +69,5 @@ osu.Game - - - 2.0.0 - - \ No newline at end of file From aa1545c9388a937db3ee4d1b4651d8cd0cf55747 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 15:52:22 +0800 Subject: [PATCH 042/110] Refine words in README. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7bbd43c961..7adc8dc973 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ If you are not interested in debugging osu!, you can add `-c Release` to gain pe If the build fails, try to restore NuGet packages with `dotnet restore`. -_Due to historical feature gap between .NET Core and Xamarin, running `dotnet` CLI from the root directory will probably not work. You can try to run the CLI towards single .NET Core project, or helper project at `build/Desktop.proj`. Or you can get help from your IDE of choice to run the correct commands. We are keeping configuration files in the repository for the popular IDEs._ +_Due to historical feature gap between .NET Core and Xamarin, running `dotnet` CLI from the root directory will not work for most commands. This can be resolved by specifying a target `.csproj` or the helper project at `build/Desktop.proj`. Configurations have been provided to work around this issue for all supported IDEs mentioned above._ ### Testing with resource/framework modifications @@ -82,7 +82,7 @@ Sometimes it may be necessary to cross-test changes in [osu-resources](https://g ### Code analysis -Before committing your code, please run code formatter. It can be achieved with command `dotnet format`, or `Format code` command in your IDE. (Defaults to `Ctrl+K,Ctrl+D` in Visual Studio, `Shift+Alt+F` in Visual Studio Code, or `Ctrl+Alt+L` in Rider) +Before committing your code, please run a code formatter. It can be achieved with `dotnet format` in command line, or `Format code` command in your IDE. We have adopted some cross-platform, compiler integrated analyzers. They can provide warnings when you are editing, building inside IDE or from command line, as-if they are provided by the compiler itself. From deaeda7348c8cfcf67083dd2bd7631cbdfb00610 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 16:40:48 +0800 Subject: [PATCH 043/110] Change packing to be runned by AppVeyor. --- Directory.Build.props | 2 +- appveyor.yml | 3 +-- appveyor_deploy.yml | 3 +-- osu.Game/osu.Game.csproj | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index cee459faf9..693e132c40 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -28,6 +28,7 @@ $(NoWarn);NU1701 + false ppy Pty Ltd MIT https://github.com/ppy/osu @@ -36,6 +37,5 @@ ppy Pty Ltd Copyright (c) 2019 ppy Pty Ltd osu game - $(MSBuildThisFileDirectory)artifacts\nupkg\ \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 82c0a21aff..a4a0cedc66 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,12 +14,11 @@ build: project: osu.sln parallel: true verbosity: minimal + publish_nuget: true after_build: - ps: dotnet tool restore - ps: dotnet format --dry-run --check - ps: .\InspectCode.ps1 -artifacts: - - path: 'artifacts\nupkg\*.nupkg' test: assemblies: except: diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml index c7f762d425..bb4482f501 100644 --- a/appveyor_deploy.yml +++ b/appveyor_deploy.yml @@ -15,8 +15,7 @@ build: project: build\Desktop.proj # Skipping Xamarin Release that's slow and covered by fastlane parallel: true verbosity: minimal -artifacts: - - path: 'artifacts\nupkg\*.nupkg' + publish_nuget: true deploy: - provider: Environment name: nuget diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6c25e9e5fe..2e456f1fa1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -9,7 +9,7 @@ ppy.osu.Game 0.0.0 icon.png - true + true From d1e3718038f806afff93aaebd9bf8a1481312f34 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 27 Nov 2019 15:04:09 +0900 Subject: [PATCH 044/110] Reduce the scale of background blurs --- osu.Game/Graphics/Backgrounds/Background.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index 0f923c3a28..21fca5d5da 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -16,6 +16,8 @@ namespace osu.Game.Graphics.Backgrounds /// public class Background : CompositeDrawable { + private const float blur_scale = 0.5f; + public readonly Sprite Sprite; private readonly string textureName; @@ -64,7 +66,10 @@ namespace osu.Game.Graphics.Backgrounds }); } - bufferedContainer?.BlurTo(newBlurSigma, duration, easing); + if (bufferedContainer != null) + bufferedContainer.FrameBufferScale = newBlurSigma == Vector2.Zero ? Vector2.One : new Vector2(blur_scale); + + bufferedContainer?.BlurTo(newBlurSigma * blur_scale, duration, easing); } } } From fe0785657cc8cc86df8a32f4f04fdcda3b7068cb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 27 Nov 2019 19:37:11 +0800 Subject: [PATCH 045/110] Turn WarningAsError to always on. --- Directory.Build.props | 1 + 1 file changed, 1 insertion(+) diff --git a/Directory.Build.props b/Directory.Build.props index 693e132c40..572d97fafa 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,6 +2,7 @@ 7.3 + true $(MSBuildThisFileDirectory)app.manifest From b126700f01b206b4fc6fb97223b0c1ab8fc97913 Mon Sep 17 00:00:00 2001 From: phosphene47 Date: Wed, 27 Nov 2019 22:47:00 +1100 Subject: [PATCH 046/110] Debounce hover sounds --- .../UserInterface/HoverClickSounds.cs | 15 +++++++++++++- .../Graphics/UserInterface/HoverSounds.cs | 20 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 4f678b7218..b1a58b5d57 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,12 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Extensions; using osu.Framework.Input.Events; +using osu.Framework.Threading; using osuTK.Input; namespace osu.Game.Graphics.UserInterface @@ -34,10 +36,21 @@ namespace osu.Game.Graphics.UserInterface this.buttons = buttons ?? new[] { MouseButton.Left }; } + private ScheduledDelegate playDelegate; + protected override bool OnClick(ClickEvent e) { + playDelegate?.Cancel(); + if (buttons.Contains(e.Button) && Contains(e.ScreenSpaceMousePosition)) - sampleClick?.Play(); + { + var debounceMs = (int)DebounceTime.TotalMilliseconds; + + if (debounceMs == 0) + sampleClick?.Play(); + else + playDelegate = Scheduler.AddDelayed(() => sampleClick?.Play(), debounceMs); + } return base.OnClick(e); } diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index f1ac8ced6e..f4258f2b6d 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -9,6 +10,7 @@ using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Framework.Threading; namespace osu.Game.Graphics.UserInterface { @@ -20,6 +22,12 @@ namespace osu.Game.Graphics.UserInterface { private SampleChannel sampleHover; + /// + /// Length of debounce for sound playback. + /// Set this to to disable debouncing. + /// + public TimeSpan DebounceTime { get; set; } = TimeSpan.FromMilliseconds(50); + protected readonly HoverSampleSet SampleSet; public HoverSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal) @@ -28,9 +36,19 @@ namespace osu.Game.Graphics.UserInterface RelativeSizeAxes = Axes.Both; } + private ScheduledDelegate playDelegate; + protected override bool OnHover(HoverEvent e) { - sampleHover?.Play(); + playDelegate?.Cancel(); + + var debounceMs = (int)DebounceTime.TotalMilliseconds; + + if (debounceMs == 0) + sampleHover?.Play(); + else + playDelegate = Scheduler.AddDelayed(() => sampleHover?.Play(), debounceMs); + return base.OnHover(e); } From 037d927e4518ee16925ff08e4eb037f6b8b2d6dc Mon Sep 17 00:00:00 2001 From: phosphene47 Date: Wed, 27 Nov 2019 22:51:27 +1100 Subject: [PATCH 047/110] TimeSpans can be negative! --- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 2 +- osu.Game/Graphics/UserInterface/HoverSounds.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index b1a58b5d57..fcb8f8d6bd 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -46,7 +46,7 @@ namespace osu.Game.Graphics.UserInterface { var debounceMs = (int)DebounceTime.TotalMilliseconds; - if (debounceMs == 0) + if (debounceMs <= 0) sampleClick?.Play(); else playDelegate = Scheduler.AddDelayed(() => sampleClick?.Play(), debounceMs); diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index f4258f2b6d..2223ac21db 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -44,7 +44,7 @@ namespace osu.Game.Graphics.UserInterface var debounceMs = (int)DebounceTime.TotalMilliseconds; - if (debounceMs == 0) + if (debounceMs <= 0) sampleHover?.Play(); else playDelegate = Scheduler.AddDelayed(() => sampleHover?.Play(), debounceMs); From d4afea0b5e5197d81999ee7edbf774a5946e0319 Mon Sep 17 00:00:00 2001 From: phosphene47 Date: Wed, 27 Nov 2019 23:06:07 +1100 Subject: [PATCH 048/110] Use double instead of TimeSpan --- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 7 ++----- osu.Game/Graphics/UserInterface/HoverSounds.cs | 12 ++++-------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index fcb8f8d6bd..a8e074d2ef 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.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 osu.Framework.Allocation; using osu.Framework.Audio; @@ -44,12 +43,10 @@ namespace osu.Game.Graphics.UserInterface if (buttons.Contains(e.Button) && Contains(e.ScreenSpaceMousePosition)) { - var debounceMs = (int)DebounceTime.TotalMilliseconds; - - if (debounceMs <= 0) + if (DebounceTime <= 0) sampleClick?.Play(); else - playDelegate = Scheduler.AddDelayed(() => sampleClick?.Play(), debounceMs); + playDelegate = Scheduler.AddDelayed(() => sampleClick?.Play(), DebounceTime); } return base.OnClick(e); diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index 2223ac21db..c98d50efff 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.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.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -23,10 +22,9 @@ namespace osu.Game.Graphics.UserInterface private SampleChannel sampleHover; /// - /// Length of debounce for sound playback. - /// Set this to to disable debouncing. + /// Length of debounce for sound playback, in milliseconds. Default is 50ms. /// - public TimeSpan DebounceTime { get; set; } = TimeSpan.FromMilliseconds(50); + public double DebounceTime { get; set; } = 50; protected readonly HoverSampleSet SampleSet; @@ -42,12 +40,10 @@ namespace osu.Game.Graphics.UserInterface { playDelegate?.Cancel(); - var debounceMs = (int)DebounceTime.TotalMilliseconds; - - if (debounceMs <= 0) + if (DebounceTime <= 0) sampleHover?.Play(); else - playDelegate = Scheduler.AddDelayed(() => sampleHover?.Play(), debounceMs); + playDelegate = Scheduler.AddDelayed(() => sampleHover?.Play(), DebounceTime); return base.OnHover(e); } From 786fb9ede350164c1e9e79c760e5a472d3441b25 Mon Sep 17 00:00:00 2001 From: phosphene47 Date: Thu, 28 Nov 2019 00:44:01 +1100 Subject: [PATCH 049/110] Split click and hover and disable click debounce --- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 9 +++++++-- osu.Game/Graphics/UserInterface/HoverSounds.cs | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index a8e074d2ef..61cacee45f 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -21,6 +21,11 @@ namespace osu.Game.Graphics.UserInterface private SampleChannel sampleClick; private readonly MouseButton[] buttons; + /// + /// Length of debounce for click sound playback, in milliseconds. Default is 0ms. + /// + public double ClickDebounceTime { get; set; } + /// /// a container which plays sounds on hover and click for any specified s. /// @@ -43,10 +48,10 @@ namespace osu.Game.Graphics.UserInterface if (buttons.Contains(e.Button) && Contains(e.ScreenSpaceMousePosition)) { - if (DebounceTime <= 0) + if (ClickDebounceTime <= 0) sampleClick?.Play(); else - playDelegate = Scheduler.AddDelayed(() => sampleClick?.Play(), DebounceTime); + playDelegate = Scheduler.AddDelayed(() => sampleClick?.Play(), ClickDebounceTime); } return base.OnClick(e); diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index c98d50efff..fcd8940348 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -22,9 +22,9 @@ namespace osu.Game.Graphics.UserInterface private SampleChannel sampleHover; /// - /// Length of debounce for sound playback, in milliseconds. Default is 50ms. + /// Length of debounce for hover sound playback, in milliseconds. Default is 50ms. /// - public double DebounceTime { get; set; } = 50; + public double HoverDebounceTime { get; set; } = 50; protected readonly HoverSampleSet SampleSet; @@ -40,10 +40,10 @@ namespace osu.Game.Graphics.UserInterface { playDelegate?.Cancel(); - if (DebounceTime <= 0) + if (HoverDebounceTime <= 0) sampleHover?.Play(); else - playDelegate = Scheduler.AddDelayed(() => sampleHover?.Play(), DebounceTime); + playDelegate = Scheduler.AddDelayed(() => sampleHover?.Play(), HoverDebounceTime); return base.OnHover(e); } From 2865f320524dd149de900aa09516075df17162d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Nov 2019 00:13:44 +0900 Subject: [PATCH 050/110] Fix nullref on clicking links in tests --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 61391b7102..2bbac92f7f 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -19,14 +19,8 @@ namespace osu.Game.Graphics.Containers { } - private OsuGame game; - - [BackgroundDependencyLoader(true)] - private void load(OsuGame game) - { - // will be null in tests - this.game = game; - } + [Resolved(CanBeNull = true)] + private OsuGame game { get; set; } public void AddLinks(string text, List links) { @@ -82,7 +76,7 @@ namespace osu.Game.Graphics.Containers if (action != null) action(); else - game.HandleLink(link); + game?.HandleLink(link); }, }); } From e1302d84ddd51f71bcb3b8e85c241323a9552e8c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Nov 2019 00:26:10 +0900 Subject: [PATCH 051/110] Use string.Empty --- osu.Game/Overlays/Rankings/Tables/CountriesTable.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index 386225a606..ae686cd4ad 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -21,8 +21,8 @@ namespace osu.Game.Overlays.Rankings.Tables protected override TableColumn[] CreateHeaders() => new[] { - new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place - new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and country name + new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place + new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and country name new TableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), From 724fcecbc572f803478c12b9132296f28425fb01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Nov 2019 00:32:31 +0900 Subject: [PATCH 052/110] Fix test scene not actually covering the class it's testing --- osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs index 49656900cc..2c76b1937b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs @@ -29,6 +29,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ScoresTable), typeof(CountriesTable), typeof(TableRowBackground), + typeof(RankingsTable<>) }; [Resolved] From bb3152ac8b58def442b9a3ea996ea73c9d694bbf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 27 Nov 2019 21:35:03 +0300 Subject: [PATCH 053/110] Use string.empty for empty headers --- osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs | 4 ++-- osu.Game/Overlays/Rankings/Tables/ScoresTable.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 11357a82a1..2a658ec0de 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -22,8 +22,8 @@ namespace osu.Game.Overlays.Rankings.Tables protected override TableColumn[] CreateHeaders() => new[] { - new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place - new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username + new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place + new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 0a8ec50e30..b644edefd1 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -22,8 +22,8 @@ namespace osu.Game.Overlays.Rankings.Tables protected override TableColumn[] CreateHeaders() => new[] { - new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place - new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username + new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place + new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), From 14c471fe5d8a4391be57546530d916338e3de71f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 27 Nov 2019 21:37:34 +0300 Subject: [PATCH 054/110] Move Rankings property below ctor --- .../Overlays/Rankings/Tables/RankingsTable.cs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 07e2257e8f..58363929b3 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -23,23 +23,6 @@ namespace osu.Game.Overlays.Rankings.Tables private readonly int page; private readonly FillFlowContainer backgroundFlow; - public IReadOnlyList Rankings - { - set - { - Content = null; - backgroundFlow.Clear(); - - if (value?.Any() != true) - return; - - value.ForEach(_ => backgroundFlow.Add(new TableRowBackground())); - - Columns = CreateHeaders(); - Content = value.Select((s, i) => CreateContent(page * items_per_page - (items_per_page - i), s)).ToArray().ToRectangular(); - } - } - protected RankingsTable(int page) { this.page = page; @@ -58,6 +41,23 @@ namespace osu.Game.Overlays.Rankings.Tables }); } + public IReadOnlyList Rankings + { + set + { + Content = null; + backgroundFlow.Clear(); + + if (value?.Any() != true) + return; + + value.ForEach(_ => backgroundFlow.Add(new TableRowBackground())); + + Columns = CreateHeaders(); + Content = value.Select((s, i) => CreateContent(page * items_per_page - (items_per_page - i), s)).ToArray().ToRectangular(); + } + } + protected abstract TableColumn[] CreateHeaders(); protected abstract Drawable[] CreateContent(int index, TModel item); From 4cf59680263a2aa6f2883426a00d385cd72b6500 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 27 Nov 2019 21:39:38 +0300 Subject: [PATCH 055/110] Simplify place calculation --- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 58363929b3..98a6cc1caf 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Rankings.Tables value.ForEach(_ => backgroundFlow.Add(new TableRowBackground())); Columns = CreateHeaders(); - Content = value.Select((s, i) => CreateContent(page * items_per_page - (items_per_page - i), s)).ToArray().ToRectangular(); + Content = value.Select((s, i) => CreateContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular(); } } From 2135a7fd7b32b8763cbe950a32705145f144ed54 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 27 Nov 2019 21:46:41 +0300 Subject: [PATCH 056/110] Don't use repetitive headers in each class --- osu.Game/Overlays/Rankings/Tables/CountriesTable.cs | 4 +--- osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs | 4 +--- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 10 ++++++++-- osu.Game/Overlays/Rankings/Tables/ScoresTable.cs | 4 +--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index ae686cd4ad..f5e95f316e 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -19,10 +19,8 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected override TableColumn[] CreateHeaders() => new[] + protected override TableColumn[] CreateAdditionalHeaders() => new[] { - new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place - new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and country name new TableColumn("Active Users", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 2a658ec0de..7d4bd71526 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -20,10 +20,8 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected override TableColumn[] CreateHeaders() => new[] + protected override TableColumn[] CreateAdditionalHeaders() => new[] { - new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place - new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 98a6cc1caf..530295b039 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -53,12 +53,18 @@ namespace osu.Game.Overlays.Rankings.Tables value.ForEach(_ => backgroundFlow.Add(new TableRowBackground())); - Columns = CreateHeaders(); + Columns = mainHeaders.Concat(CreateAdditionalHeaders()).ToArray(); Content = value.Select((s, i) => CreateContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular(); } } - protected abstract TableColumn[] CreateHeaders(); + private static TableColumn[] mainHeaders => new[] + { + new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place + new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username (country name) + }; + + protected abstract TableColumn[] CreateAdditionalHeaders(); protected abstract Drawable[] CreateContent(int index, TModel item); diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index b644edefd1..9ddd89914a 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -20,10 +20,8 @@ namespace osu.Game.Overlays.Rankings.Tables { } - protected override TableColumn[] CreateHeaders() => new[] + protected override TableColumn[] CreateAdditionalHeaders() => new[] { - new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place - new TableColumn(string.Empty, Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed)), // flag and username new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), From c546df8a8050e5e220c9d8c372a00b6062b38947 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 27 Nov 2019 21:56:22 +0300 Subject: [PATCH 057/110] Refactor API logic --- .../Online/API/Requests/GetCountriesResponse.cs | 4 ++-- osu.Game/Online/API/Requests/GetUsersResponse.cs | 4 ++-- .../API/Requests/Responses/APICountryRankings.cs | 14 -------------- .../API/Requests/Responses/APIUserRankings.cs | 14 -------------- .../Overlays/Rankings/Tables/CountriesTable.cs | 6 +++--- .../Overlays/Rankings/Tables/PerformanceTable.cs | 6 +++--- osu.Game/Overlays/Rankings/Tables/ScoresTable.cs | 6 +++--- osu.Game/Users/CountryStatistics.cs | 3 +++ osu.Game/Users/UserStatistics.cs | 3 +++ 9 files changed, 19 insertions(+), 41 deletions(-) delete mode 100644 osu.Game/Online/API/Requests/Responses/APICountryRankings.cs delete mode 100644 osu.Game/Online/API/Requests/Responses/APIUserRankings.cs diff --git a/osu.Game/Online/API/Requests/GetCountriesResponse.cs b/osu.Game/Online/API/Requests/GetCountriesResponse.cs index 7b65c6fadd..6624344b44 100644 --- a/osu.Game/Online/API/Requests/GetCountriesResponse.cs +++ b/osu.Game/Online/API/Requests/GetCountriesResponse.cs @@ -3,13 +3,13 @@ using System.Collections.Generic; using Newtonsoft.Json; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Users; namespace osu.Game.Online.API.Requests { public class GetCountriesResponse : ResponseWithCursor { [JsonProperty("ranking")] - public List Countries; + public List Countries; } } diff --git a/osu.Game/Online/API/Requests/GetUsersResponse.cs b/osu.Game/Online/API/Requests/GetUsersResponse.cs index c60bc71096..b301f551e3 100644 --- a/osu.Game/Online/API/Requests/GetUsersResponse.cs +++ b/osu.Game/Online/API/Requests/GetUsersResponse.cs @@ -3,13 +3,13 @@ using System.Collections.Generic; using Newtonsoft.Json; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Users; namespace osu.Game.Online.API.Requests { public class GetUsersResponse : ResponseWithCursor { [JsonProperty("ranking")] - public List Users; + public List Users; } } diff --git a/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs b/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs deleted file mode 100644 index 91086876a9..0000000000 --- a/osu.Game/Online/API/Requests/Responses/APICountryRankings.cs +++ /dev/null @@ -1,14 +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 Newtonsoft.Json; -using osu.Game.Users; - -namespace osu.Game.Online.API.Requests.Responses -{ - public class APICountryRankings : CountryStatistics - { - [JsonProperty] - public Country Country; - } -} diff --git a/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs b/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs deleted file mode 100644 index 1cdb6ecb8c..0000000000 --- a/osu.Game/Online/API/Requests/Responses/APIUserRankings.cs +++ /dev/null @@ -1,14 +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 Newtonsoft.Json; -using osu.Game.Users; - -namespace osu.Game.Online.API.Requests.Responses -{ - public class APIUserRankings : UserStatistics - { - [JsonProperty] - public User User; - } -} diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index f5e95f316e..878f85b346 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -7,12 +7,12 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Users.Drawables; using osuTK; -using osu.Game.Online.API.Requests.Responses; using System; +using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables { - public class CountriesTable : RankingsTable + public class CountriesTable : RankingsTable { public CountriesTable(int page = 1) : base(page) @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Rankings.Tables new TableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; - protected override Drawable[] CreateContent(int index, APICountryRankings item) => new Drawable[] + protected override Drawable[] CreateContent(int index, CountryStatistics item) => new Drawable[] { new OsuSpriteText { diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 7d4bd71526..010da07858 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -9,11 +9,11 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Users.Drawables; using osuTK; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables { - public class PerformanceTable : RankingsTable + public class PerformanceTable : RankingsTable { public PerformanceTable(int page = 1) : base(page) @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Rankings.Tables new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; - protected override Drawable[] CreateContent(int index, APIUserRankings item) + protected override Drawable[] CreateContent(int index, UserStatistics item) { var content = new List { diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 9ddd89914a..d40da63f7f 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -7,13 +7,13 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Users.Drawables; using osuTK; -using osu.Game.Online.API.Requests.Responses; using System.Collections.Generic; using osu.Game.Graphics.Containers; +using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables { - public class ScoresTable : RankingsTable + public class ScoresTable : RankingsTable { public ScoresTable(int page = 1) : base(page) @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Rankings.Tables new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; - protected override Drawable[] CreateContent(int index, APIUserRankings item) + protected override Drawable[] CreateContent(int index, UserStatistics item) { var content = new List { diff --git a/osu.Game/Users/CountryStatistics.cs b/osu.Game/Users/CountryStatistics.cs index 53fa70f0d4..000553c32b 100644 --- a/osu.Game/Users/CountryStatistics.cs +++ b/osu.Game/Users/CountryStatistics.cs @@ -7,6 +7,9 @@ namespace osu.Game.Users { public class CountryStatistics { + [JsonProperty] + public Country Country; + [JsonProperty(@"code")] public string FlagName; diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index 032ec2e05f..24f1f0b30e 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -10,6 +10,9 @@ namespace osu.Game.Users { public class UserStatistics { + [JsonProperty] + public User User; + [JsonProperty(@"level")] public LevelInfo Level; From 800bda7e815caa2ff0739642444e431acf49c1f3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 27 Nov 2019 23:35:02 +0300 Subject: [PATCH 058/110] Refactor tables to avoid code duplication --- .../Visual/Online/TestSceneRankingsTables.cs | 1 + .../Rankings/Tables/CountriesTable.cs | 39 +++------ .../Rankings/Tables/PerformanceTable.cs | 77 ++--------------- .../Overlays/Rankings/Tables/RankingsTable.cs | 35 +++++++- .../Overlays/Rankings/Tables/ScoresTable.cs | 85 +++---------------- .../Rankings/Tables/UserBasedTable.cs | 70 +++++++++++++++ 6 files changed, 133 insertions(+), 174 deletions(-) create mode 100644 osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs index 2c76b1937b..ff238803a5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs @@ -29,6 +29,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ScoresTable), typeof(CountriesTable), typeof(TableRowBackground), + typeof(UserBasedTable), typeof(RankingsTable<>) }; diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index 878f85b346..208a4dbfe4 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -3,12 +3,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Users.Drawables; -using osuTK; using System; using osu.Game.Users; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics; namespace osu.Game.Overlays.Rankings.Tables { @@ -29,31 +27,16 @@ namespace osu.Game.Overlays.Rankings.Tables new TableColumn("Avg. Perf.", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; - protected override Drawable[] CreateContent(int index, CountryStatistics item) => new Drawable[] + protected override Country GetCountry(CountryStatistics item) => item.Country; + + protected override Drawable CreateFlagContent(CountryStatistics item) => new OsuSpriteText + { + Font = OsuFont.GetFont(size: TEXT_SIZE), + Text = $@"{item.Country.FullName}", + }; + + protected override Drawable[] CreateAdditionalContent(CountryStatistics item) => new[] { - new OsuSpriteText - { - Text = $"#{index + 1}", - Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), - Children = new Drawable[] - { - new UpdateableFlag(item.Country) - { - Size = new Vector2(20, 13), - ShowPlaceholderOnNull = false, - }, - new RowText - { - Text = $@"{item.Country.FullName}", - } - } - }, new ColoredRowText { Text = $@"{item.ActiveUsers:N0}", diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 010da07858..263f6052cc 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -3,91 +3,28 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using System.Collections.Generic; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Users.Drawables; -using osuTK; using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables { - public class PerformanceTable : RankingsTable + public class PerformanceTable : UserBasedTable { public PerformanceTable(int page = 1) : base(page) { } - protected override TableColumn[] CreateAdditionalHeaders() => new[] + protected override TableColumn[] CreateUniqueHeaders() => new[] { - new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; - protected override Drawable[] CreateContent(int index, UserStatistics item) + protected override Drawable[] CreateUniqueContent(UserStatistics item) => new[] { - var content = new List + new RowText { - new OsuSpriteText - { - Text = $"#{index + 1}", - Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) - }, - }; - - var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; - username.AddUserLink(item.User); - - content.AddRange(new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), - Children = new Drawable[] - { - new UpdateableFlag(item.User.Country) - { - Size = new Vector2(20, 13), - ShowPlaceholderOnNull = false, - }, - username - } - }, - new ColoredRowText - { - Text = $@"{item.Accuracy:F2}%", - }, - new ColoredRowText - { - Text = $@"{item.PlayCount:N0}", - }, - new RowText - { - Text = $@"{item.PP:N0}", - }, - new ColoredRowText - { - Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", - }, - new ColoredRowText - { - Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", - }, - new ColoredRowText - { - Text = $@"{item.GradesCount.A:N0}", - }, - }); - - return content.ToArray(); - } + Text = $@"{item.PP:N0}", + } + }; } } diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 530295b039..d085b3a9a8 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -10,6 +10,9 @@ using osu.Framework.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Users; +using osu.Game.Users.Drawables; +using osuTK; namespace osu.Game.Overlays.Rankings.Tables { @@ -54,10 +57,12 @@ namespace osu.Game.Overlays.Rankings.Tables value.ForEach(_ => backgroundFlow.Add(new TableRowBackground())); Columns = mainHeaders.Concat(CreateAdditionalHeaders()).ToArray(); - Content = value.Select((s, i) => CreateContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular(); + Content = value.Select((s, i) => createContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular(); } } + private Drawable[] createContent(int index, TModel item) => new Drawable[] { createIndexDrawable(index), createMainContent(item) }.Concat(CreateAdditionalContent(item)).ToArray(); + private static TableColumn[] mainHeaders => new[] { new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.Absolute, 50)), // place @@ -66,10 +71,36 @@ namespace osu.Game.Overlays.Rankings.Tables protected abstract TableColumn[] CreateAdditionalHeaders(); - protected abstract Drawable[] CreateContent(int index, TModel item); + protected abstract Drawable[] CreateAdditionalContent(TModel item); protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty, HighlightedColumn()); + protected abstract Country GetCountry(TModel item); + + protected abstract Drawable CreateFlagContent(TModel item); + + private OsuSpriteText createIndexDrawable(int index) => new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) + }; + + private FillFlowContainer createMainContent(TModel item) => new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] + { + new UpdateableFlag(GetCountry(item)) + { + Size = new Vector2(20, 13), + ShowPlaceholderOnNull = false, + }, + CreateFlagContent(item) + } + }; + protected virtual string HighlightedColumn() => @"Performance"; private class HeaderText : OsuSpriteText diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index d40da63f7f..0d4999ee8f 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -3,97 +3,34 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Users.Drawables; -using osuTK; -using System.Collections.Generic; -using osu.Game.Graphics.Containers; using osu.Game.Users; namespace osu.Game.Overlays.Rankings.Tables { - public class ScoresTable : RankingsTable + public class ScoresTable : UserBasedTable { public ScoresTable(int page = 1) : base(page) { } - protected override TableColumn[] CreateAdditionalHeaders() => new[] + protected override TableColumn[] CreateUniqueHeaders() => new[] { - new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Total Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)) }; - protected override Drawable[] CreateContent(int index, UserStatistics item) + protected override Drawable[] CreateUniqueContent(UserStatistics item) => new[] { - var content = new List + new ColoredRowText { - new OsuSpriteText - { - Text = $"#{index + 1}", - Font = OsuFont.GetFont(size: TEXT_SIZE, weight: FontWeight.Bold) - }, - }; - - var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; - username.AddUserLink(item.User); - - content.AddRange(new Drawable[] + Text = $@"{item.TotalScore:N0}", + }, + new RowText { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), - Children = new Drawable[] - { - new UpdateableFlag(item.User.Country) - { - Size = new Vector2(20, 13), - ShowPlaceholderOnNull = false, - }, - username - } - }, - new ColoredRowText - { - Text = $@"{item.Accuracy:F2}%", - }, - new ColoredRowText - { - Text = $@"{item.PlayCount:N0}", - }, - new ColoredRowText - { - Text = $@"{item.TotalScore:N0}", - }, - new RowText - { - Text = $@"{item.RankedScore:N0}", - }, - new ColoredRowText - { - Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", - }, - new ColoredRowText - { - Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", - }, - new ColoredRowText - { - Text = $@"{item.GradesCount.A:N0}", - }, - }); - - return content.ToArray(); - } + Text = $@"{item.RankedScore:N0}", + } + }; protected override string HighlightedColumn() => @"Ranked Score"; } diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs new file mode 100644 index 0000000000..1283db9e32 --- /dev/null +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -0,0 +1,70 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Users; + +namespace osu.Game.Overlays.Rankings.Tables +{ + public abstract class UserBasedTable : RankingsTable + { + protected UserBasedTable(int page) + : base(page) + { + } + + protected override TableColumn[] CreateAdditionalHeaders() => new[] + { + new TableColumn("Accuracy", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Play Count", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + }.Concat(CreateUniqueHeaders()).Concat(new[] + { + new TableColumn("SS", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("S", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + }).ToArray(); + + protected override Country GetCountry(UserStatistics item) => item.User.Country; + + protected override Drawable CreateFlagContent(UserStatistics item) + { + var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; + username.AddUserLink(item.User); + return username; + } + + protected override Drawable[] CreateAdditionalContent(UserStatistics item) => new[] + { + new ColoredRowText + { + Text = $@"{item.Accuracy:F2}%", + }, + new ColoredRowText + { + Text = $@"{item.PlayCount:N0}", + }, + }.Concat(CreateUniqueContent(item)).Concat(new[] + { + new ColoredRowText + { + Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", + }, + new ColoredRowText + { + Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", + }, + new ColoredRowText + { + Text = $@"{item.GradesCount.A:N0}", + } + }).ToArray(); + + protected abstract TableColumn[] CreateUniqueHeaders(); + + protected abstract Drawable[] CreateUniqueContent(UserStatistics item); + } +} From 44cfe98278a60e0fea2ccf43caf6e4d3a52568c8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 27 Nov 2019 23:40:52 +0300 Subject: [PATCH 059/110] Simplify test scene --- .../Visual/Online/TestSceneRankingsTables.cs | 57 ++++++++----------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs index ff238803a5..5501bb54d0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs @@ -68,11 +68,7 @@ namespace osu.Game.Tests.Visual.Online private void createCountryTable(RulesetInfo ruleset, int page = 1) { - loading.Show(); - - request?.Cancel(); - cancellationToken?.Cancel(); - cancellationToken = new CancellationTokenSource(); + onLoadStarted(); request = new GetCountryRankingsRequest(ruleset, page); ((GetCountryRankingsRequest)request).Success += rankings => Schedule(() => @@ -82,12 +78,7 @@ namespace osu.Game.Tests.Visual.Online Rankings = rankings.Countries, }; - LoadComponentAsync(table, t => - { - scrollFlow.Clear(); - scrollFlow.Add(t); - loading.Hide(); - }, cancellationToken.Token); + loadTable(table); }); api.Queue(request); @@ -95,11 +86,7 @@ namespace osu.Game.Tests.Visual.Online private void createPerformanceTable(RulesetInfo ruleset, string country, int page = 1) { - loading.Show(); - - request?.Cancel(); - cancellationToken?.Cancel(); - cancellationToken = new CancellationTokenSource(); + onLoadStarted(); request = new GetUserRankingsRequest(ruleset, country: country, page: page); ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => @@ -109,12 +96,7 @@ namespace osu.Game.Tests.Visual.Online Rankings = rankings.Users, }; - LoadComponentAsync(table, t => - { - scrollFlow.Clear(); - scrollFlow.Add(t); - loading.Hide(); - }, cancellationToken.Token); + loadTable(table); }); api.Queue(request); @@ -122,11 +104,7 @@ namespace osu.Game.Tests.Visual.Online private void createScoreTable(RulesetInfo ruleset, int page = 1) { - loading.Show(); - - request?.Cancel(); - cancellationToken?.Cancel(); - cancellationToken = new CancellationTokenSource(); + onLoadStarted(); request = new GetUserRankingsRequest(ruleset, UserRankingsType.Score, page); ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => @@ -136,15 +114,28 @@ namespace osu.Game.Tests.Visual.Online Rankings = rankings.Users, }; - LoadComponentAsync(table, t => - { - scrollFlow.Clear(); - scrollFlow.Add(t); - loading.Hide(); - }, cancellationToken.Token); + loadTable(table); }); api.Queue(request); } + + private void onLoadStarted() + { + loading.Show(); + request?.Cancel(); + cancellationToken?.Cancel(); + cancellationToken = new CancellationTokenSource(); + } + + private void loadTable(Drawable table) + { + LoadComponentAsync(table, t => + { + scrollFlow.Clear(); + scrollFlow.Add(t); + loading.Hide(); + }, cancellationToken.Token); + } } } From 8077c86d13265e2d58677269d3ae457fc9ce3f86 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 27 Nov 2019 23:58:31 +0300 Subject: [PATCH 060/110] CI fixes --- osu.Game/Overlays/Rankings/Tables/CountriesTable.cs | 2 +- osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs | 2 +- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 2 +- osu.Game/Overlays/Rankings/Tables/ScoresTable.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index 208a4dbfe4..b49583f0e2 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Rankings.Tables Text = $@"{item.Country.FullName}", }; - protected override Drawable[] CreateAdditionalContent(CountryStatistics item) => new[] + protected override Drawable[] CreateAdditionalContent(CountryStatistics item) => new Drawable[] { new ColoredRowText { diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 263f6052cc..ec3252b22a 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Rankings.Tables new TableColumn("Performance", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; - protected override Drawable[] CreateUniqueContent(UserStatistics item) => new[] + protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] { new RowText { diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index d085b3a9a8..7a20d60f6e 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Rankings.Tables AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(7, 0), - Children = new Drawable[] + Children = new[] { new UpdateableFlag(GetCountry(item)) { diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 0d4999ee8f..cc3c5ccf94 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Rankings.Tables new TableColumn("Ranked Score", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)) }; - protected override Drawable[] CreateUniqueContent(UserStatistics item) => new[] + protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] { new ColoredRowText { From a2d935bebf7bb43bb5a35f966166ad3c1d1e42c6 Mon Sep 17 00:00:00 2001 From: Luxiono <55364481+Luxiono@users.noreply.github.com> Date: Wed, 27 Nov 2019 20:58:13 -0500 Subject: [PATCH 061/110] Adjust wording and make small format changes This makes small changes to the README file to make certain parts properly formatted (such as adding 'a' in front of a sentence with 'to' straight before it, as done in the Building section) and added special formatting where it feels needed. This may also make certain sentences slightly more natural. Please let me know if you want any other changes. --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 7adc8dc973..e343e498cd 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ [![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) [![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy) -Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Commonly known by the codename "osu!lazer". Pew pew. +Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Commonly known by the codename *osu!lazer*. Pew pew. ## Status -This project is still heavily under development, but is in a state where users are encouraged to try it out and keep it installed alongside the stable osu! client. It will continue to evolve over the coming months and hopefully bring some new unique features to the table. +This project is still heavily under development, but is in a state where users are encouraged to try it out and keep it installed alongside the stable *osu!* client. It will continue to evolve over the coming months and hopefully bring some new unique features to the table. We are accepting bug reports (please report with as much detail as possible). Feature requests are welcome as long as you read and understand the contribution guidelines listed below. @@ -59,22 +59,22 @@ git pull ### Building -Build configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `VisualTests` project/configuration. More information on this provided [below](#contributing). +Build configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `VisualTests` project/configuration. More information on this is provided [below](#contributing). -- Visual Studio / Rider users should load the project via one of the platform-specific .slnf files, rather than the main .sln. This will allow access to template run configurations. +- Visual Studio / Rider users should load the project via one of the platform-specific `.slnf` files, rather than the main `.sln.` This will allow access to template run configurations. - Visual Studio Code users must run the `Restore` task before any build attempt. -You can also build and run osu! from the command-line with a single command: +You can also build and run *osu!* from the command-line with a single command: ```shell dotnet run --project osu.Desktop ``` -If you are not interested in debugging osu!, you can add `-c Release` to gain performance. In this case, you must replace `Debug` with `Release` in any commands mentioned in this document. +If you are not interested in debugging *osu!*, you can add `-c Release` to gain performance. In this case, you must replace `Debug` with `Release` in any commands mentioned in this document. If the build fails, try to restore NuGet packages with `dotnet restore`. -_Due to historical feature gap between .NET Core and Xamarin, running `dotnet` CLI from the root directory will not work for most commands. This can be resolved by specifying a target `.csproj` or the helper project at `build/Desktop.proj`. Configurations have been provided to work around this issue for all supported IDEs mentioned above._ +_Due to a historical feature gap between .NET Core and Xamarin, running `dotnet` CLI from the root directory will not work for most commands. This can be resolved by specifying a target `.csproj` or the helper project at `build/Desktop.proj`. Configurations have been provided to work around this issue for all supported IDEs mentioned above._ ### Testing with resource/framework modifications @@ -82,7 +82,7 @@ Sometimes it may be necessary to cross-test changes in [osu-resources](https://g ### Code analysis -Before committing your code, please run a code formatter. It can be achieved with `dotnet format` in command line, or `Format code` command in your IDE. +Before committing your code, please run a code formatter. This can be achieved with running `dotnet format` in the command line, or the `Format code` command in your IDE. We have adopted some cross-platform, compiler integrated analyzers. They can provide warnings when you are editing, building inside IDE or from command line, as-if they are provided by the compiler itself. @@ -90,19 +90,19 @@ JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it ## Contributing -We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention of having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time, to ensure no effort is wasted. +We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention of having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time to ensure no effort is wasted. If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu/issues) (especially those with the ["good first issue"](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) label). Before starting, please make sure you are familiar with the [development and testing](https://github.com/ppy/osu-framework/wiki/Development-and-Testing) procedure we have set up. New component development, and where possible, bug fixing and debugging existing components **should always be done under VisualTests**. -Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured; with any libraries we are using; with any processes involved with contributing, *please* bring it up. We welcome all feedback so we can make contributing to this project as pain-free as possible. +Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured, with any libraries we are using, or with any processes involved with contributing, *please* bring it up. We welcome all feedback so we can make contributing to this project as painless as possible. For those interested, we love to reward quality contributions via [bounties](https://docs.google.com/spreadsheets/d/1jNXfj_S3Pb5PErA-czDdC9DUu4IgUbe1Lt8E7CYUJuE/view?&rm=minimal#gid=523803337), paid out via PayPal or osu!supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project. ## Licence -The osu! client code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source. +The *osu!client* code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source. Please note that this *does not cover* the usage of the "osu!" or "ppy" branding in any software, resources, advertising or promotion, as this is protected by trademark law. From 078e0c10581527b9aa6323454722ad8b2a986d62 Mon Sep 17 00:00:00 2001 From: Luxiono <55364481+Luxiono@users.noreply.github.com> Date: Wed, 27 Nov 2019 21:11:42 -0500 Subject: [PATCH 062/110] Add peppy's suggestion Co-Authored-By: Dean Herbert --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e343e498cd..ac164b3e8d 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ For those interested, we love to reward quality contributions via [bounties](htt ## Licence -The *osu!client* code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source. +*osu!*'s code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source. Please note that this *does not cover* the usage of the "osu!" or "ppy" branding in any software, resources, advertising or promotion, as this is protected by trademark law. From 32aa624ef3e941bc838ea956b487211310d05b3b Mon Sep 17 00:00:00 2001 From: Luxiono <55364481+Luxiono@users.noreply.github.com> Date: Wed, 27 Nov 2019 21:12:45 -0500 Subject: [PATCH 063/110] Add peppy's suggestion (part 2) Co-Authored-By: Dean Herbert --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ac164b3e8d..e2e854c755 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ Sometimes it may be necessary to cross-test changes in [osu-resources](https://g ### Code analysis -Before committing your code, please run a code formatter. This can be achieved with running `dotnet format` in the command line, or the `Format code` command in your IDE. +Before committing your code, please run a code formatter. This can be achieved by running `dotnet format` in the command line, or using the `Format code` command in your IDE. We have adopted some cross-platform, compiler integrated analyzers. They can provide warnings when you are editing, building inside IDE or from command line, as-if they are provided by the compiler itself. From 92ab8026a006bd9e7977bd659dcb3e9b1a41d63e Mon Sep 17 00:00:00 2001 From: Min Date: Thu, 28 Nov 2019 16:03:59 +1100 Subject: [PATCH 064/110] Completely remove click sound debounce --- .../UserInterface/HoverClickSounds.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 61cacee45f..803facae04 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Linq; @@ -7,7 +7,6 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Extensions; using osu.Framework.Input.Events; -using osu.Framework.Threading; using osuTK.Input; namespace osu.Game.Graphics.UserInterface @@ -21,11 +20,6 @@ namespace osu.Game.Graphics.UserInterface private SampleChannel sampleClick; private readonly MouseButton[] buttons; - /// - /// Length of debounce for click sound playback, in milliseconds. Default is 0ms. - /// - public double ClickDebounceTime { get; set; } - /// /// a container which plays sounds on hover and click for any specified s. /// @@ -40,19 +34,10 @@ namespace osu.Game.Graphics.UserInterface this.buttons = buttons ?? new[] { MouseButton.Left }; } - private ScheduledDelegate playDelegate; - protected override bool OnClick(ClickEvent e) { - playDelegate?.Cancel(); - if (buttons.Contains(e.Button) && Contains(e.ScreenSpaceMousePosition)) - { - if (ClickDebounceTime <= 0) - sampleClick?.Play(); - else - playDelegate = Scheduler.AddDelayed(() => sampleClick?.Play(), ClickDebounceTime); - } + sampleClick?.Play(); return base.OnClick(e); } From f504370867a1f221444c743a2520a686dc5459c2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Nov 2019 15:58:26 +0900 Subject: [PATCH 065/110] Make player block exit if pausable --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 7 ++++++- osu.Game/Screens/Play/Player.cs | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 6e8975f11b..803cab9325 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -115,8 +115,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestExitTooSoon() { - pauseAndConfirm(); + AddStep("seek before gameplay", () => Player.GameplayClockContainer.Seek(-5000)); + pauseAndConfirm(); resume(); AddStep("exit too soon", () => Player.Exit()); @@ -176,7 +177,9 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestExitFromGameplay() { AddStep("exit", () => Player.Exit()); + confirmPaused(); + AddStep("exit", () => Player.Exit()); confirmExited(); } @@ -214,6 +217,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRestartAfterResume() { + AddStep("seek before gameplay", () => Player.GameplayClockContainer.Seek(-5000)); + pauseAndConfirm(); resumeAndConfirm(); restart(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7f32db2ebf..d40c448452 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -536,6 +536,12 @@ namespace osu.Game.Screens.Play return true; } + if (canPause) + { + Pause(); + return true; + } + // GameplayClockContainer performs seeks / start / stop operations on the beatmap's track. // as we are no longer the current screen, we cannot guarantee the track is still usable. GameplayClockContainer.StopUsingBeatmapClock(); From aa9776d51ad200634d87e38fea50946552bebbe6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Nov 2019 19:07:43 +0900 Subject: [PATCH 066/110] seal and compact rows --- .../Rankings/Tables/PerformanceTable.cs | 5 +-- .../Rankings/Tables/UserBasedTable.cs | 31 +++++-------------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index ec3252b22a..f604efb8d5 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -21,10 +21,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected override Drawable[] CreateUniqueContent(UserStatistics item) => new Drawable[] { - new RowText - { - Text = $@"{item.PP:N0}", - } + new RowText { Text = $@"{item.PP:N0}", } }; } } diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index 1283db9e32..6ea145be9c 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -28,39 +28,24 @@ namespace osu.Game.Overlays.Rankings.Tables new TableColumn("A", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }).ToArray(); - protected override Country GetCountry(UserStatistics item) => item.User.Country; + protected sealed override Country GetCountry(UserStatistics item) => item.User.Country; - protected override Drawable CreateFlagContent(UserStatistics item) + protected sealed override Drawable CreateFlagContent(UserStatistics item) { var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; username.AddUserLink(item.User); return username; } - protected override Drawable[] CreateAdditionalContent(UserStatistics item) => new[] + protected sealed override Drawable[] CreateAdditionalContent(UserStatistics item) => new[] { - new ColoredRowText - { - Text = $@"{item.Accuracy:F2}%", - }, - new ColoredRowText - { - Text = $@"{item.PlayCount:N0}", - }, + new ColoredRowText { Text = $@"{item.Accuracy:F2}%", }, + new ColoredRowText { Text = $@"{item.PlayCount:N0}", }, }.Concat(CreateUniqueContent(item)).Concat(new[] { - new ColoredRowText - { - Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", - }, - new ColoredRowText - { - Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", - }, - new ColoredRowText - { - Text = $@"{item.GradesCount.A:N0}", - } + new ColoredRowText { Text = $@"{item.GradesCount.SS + item.GradesCount.SSPlus:N0}", }, + new ColoredRowText { Text = $@"{item.GradesCount.S + item.GradesCount.SPlus:N0}", }, + new ColoredRowText { Text = $@"{item.GradesCount.A:N0}", } }).ToArray(); protected abstract TableColumn[] CreateUniqueHeaders(); From a4f584c6a4771c0f8c40bafaa544d4e83e8a571e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Nov 2019 22:00:01 +0900 Subject: [PATCH 067/110] 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 f2d2af5678..b5e8c62123 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,6 +53,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 449b4dc4e3..143ad48c7f 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 ff6839f5ca..105ef08c7a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + @@ -81,7 +81,7 @@ - + From 71a871d7d1dede52cc9d75b435b7a70b664befc3 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 28 Nov 2019 21:59:57 +0700 Subject: [PATCH 068/110] Add loved enum on BeatmapApproval --- osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index 4908e5ecc2..123624d333 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs @@ -42,5 +42,6 @@ namespace osu.Game.Online.API.Requests Ranked, Approved, Qualified, + Loved } } From b9a8a36e60e633e94042734d2a7dc8b81b74bfe3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 00:44:32 +0900 Subject: [PATCH 069/110] 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 3a6a6e9832..997bd32bac 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -54,6 +54,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ef873bd3ac..3f056cacfb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 1723a6210c..b231e924ef 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 1c4063677ddd33d04dc4f9fd34a95f4af1d3d461 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 00:45:35 +0900 Subject: [PATCH 070/110] Ignore test temporarily --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 6e8975f11b..1c9132edef 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -113,6 +113,7 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] + [Ignore("Will be resolved with merge of https://github.com/ppy/osu/pull/6992")] public void TestExitTooSoon() { pauseAndConfirm(); From 14277d714e11ecf7309e2b65b9b606be30880e31 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 01:01:25 +0900 Subject: [PATCH 071/110] Fix tournament client crashing due to null ruleset --- osu.Game.Tournament/TournamentGameBase.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index b5e4a2756a..6bff3fb725 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -129,6 +129,9 @@ namespace osu.Game.Tournament ladder = new LadderInfo(); } + if (ladder.Ruleset.Value == null) + ladder.Ruleset.Value = RulesetStore.AvailableRulesets.First(); + Ruleset.BindTo(ladder.Ruleset); dependencies.Cache(ladder); From bb0a4db847ae8e084233576cd39845252f331dac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 01:16:26 +0900 Subject: [PATCH 072/110] Fix failing tests --- osu.Game/Graphics/Backgrounds/Background.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index 21fca5d5da..c90b1e0e98 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.Backgrounds Sprite.Texture = textures.Get(textureName); } - public Vector2 BlurSigma => bufferedContainer?.BlurSigma ?? Vector2.Zero; + public Vector2 BlurSigma => bufferedContainer?.BlurSigma / blur_scale ?? Vector2.Zero; /// /// Smoothly adjusts over time. From e7ef919b0b12b31706f1eb9036259c663c706bb2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 01:47:52 +0900 Subject: [PATCH 073/110] Ignore another failing test --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 1c9132edef..e3f1694ee5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -213,6 +213,7 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] + [Ignore("Will be resolved with merge of https://github.com/ppy/osu/pull/6992")] public void TestRestartAfterResume() { pauseAndConfirm(); From 83e3ad9e696bcbaf2dcee329efbde84c92d11f5f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 28 Nov 2019 20:09:05 +0300 Subject: [PATCH 074/110] Make Rankings a ctor variable --- .../Visual/Online/TestSceneRankingsTables.cs | 18 +++---------- .../Rankings/Tables/CountriesTable.cs | 5 ++-- .../Rankings/Tables/PerformanceTable.cs | 5 ++-- .../Overlays/Rankings/Tables/RankingsTable.cs | 25 ++++--------------- .../Overlays/Rankings/Tables/ScoresTable.cs | 5 ++-- .../Rankings/Tables/UserBasedTable.cs | 5 ++-- 6 files changed, 20 insertions(+), 43 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs index 5501bb54d0..93da2a439e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs @@ -73,11 +73,7 @@ namespace osu.Game.Tests.Visual.Online request = new GetCountryRankingsRequest(ruleset, page); ((GetCountryRankingsRequest)request).Success += rankings => Schedule(() => { - var table = new CountriesTable(page) - { - Rankings = rankings.Countries, - }; - + var table = new CountriesTable(page, rankings.Countries); loadTable(table); }); @@ -91,11 +87,7 @@ namespace osu.Game.Tests.Visual.Online request = new GetUserRankingsRequest(ruleset, country: country, page: page); ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => { - var table = new PerformanceTable(page) - { - Rankings = rankings.Users, - }; - + var table = new PerformanceTable(page, rankings.Users); loadTable(table); }); @@ -109,11 +101,7 @@ namespace osu.Game.Tests.Visual.Online request = new GetUserRankingsRequest(ruleset, UserRankingsType.Score, page); ((GetUserRankingsRequest)request).Success += rankings => Schedule(() => { - var table = new ScoresTable(page) - { - Rankings = rankings.Users, - }; - + var table = new ScoresTable(page, rankings.Users); loadTable(table); }); diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index b49583f0e2..a0e4f694bd 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -7,13 +7,14 @@ using System; using osu.Game.Users; using osu.Game.Graphics.Sprites; using osu.Game.Graphics; +using System.Collections.Generic; namespace osu.Game.Overlays.Rankings.Tables { public class CountriesTable : RankingsTable { - public CountriesTable(int page = 1) - : base(page) + public CountriesTable(int page, IReadOnlyList rankings) + : base(page, rankings) { } diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index f604efb8d5..1e6b2307e0 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.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 osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Users; @@ -9,8 +10,8 @@ namespace osu.Game.Overlays.Rankings.Tables { public class PerformanceTable : UserBasedTable { - public PerformanceTable(int page = 1) - : base(page) + public PerformanceTable(int page, IReadOnlyList rankings) + : base(page, rankings) { } diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 7a20d60f6e..08d396d88e 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -23,12 +23,9 @@ namespace osu.Game.Overlays.Rankings.Tables private const float row_height = 25; private const int items_per_page = 50; - private readonly int page; - private readonly FillFlowContainer backgroundFlow; - - protected RankingsTable(int page) + protected RankingsTable(int page, IReadOnlyList rankings) { - this.page = page; + FillFlowContainer backgroundFlow; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -42,23 +39,11 @@ namespace osu.Game.Overlays.Rankings.Tables Depth = 1f, Margin = new MarginPadding { Top = row_height } }); - } - public IReadOnlyList Rankings - { - set - { - Content = null; - backgroundFlow.Clear(); + rankings.ForEach(_ => backgroundFlow.Add(new TableRowBackground())); - if (value?.Any() != true) - return; - - value.ForEach(_ => backgroundFlow.Add(new TableRowBackground())); - - Columns = mainHeaders.Concat(CreateAdditionalHeaders()).ToArray(); - Content = value.Select((s, i) => createContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular(); - } + Columns = mainHeaders.Concat(CreateAdditionalHeaders()).ToArray(); + Content = rankings.Select((s, i) => createContent((page - 1) * items_per_page + i, s)).ToArray().ToRectangular(); } private Drawable[] createContent(int index, TModel item) => new Drawable[] { createIndexDrawable(index), createMainContent(item) }.Concat(CreateAdditionalContent(item)).ToArray(); diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index cc3c5ccf94..370ee506c2 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.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 osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Users; @@ -9,8 +10,8 @@ namespace osu.Game.Overlays.Rankings.Tables { public class ScoresTable : UserBasedTable { - public ScoresTable(int page = 1) - : base(page) + public ScoresTable(int page, IReadOnlyList rankings) + : base(page, rankings) { } diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index 6ea145be9c..019a278771 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.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.Graphics; using osu.Framework.Graphics.Containers; @@ -12,8 +13,8 @@ namespace osu.Game.Overlays.Rankings.Tables { public abstract class UserBasedTable : RankingsTable { - protected UserBasedTable(int page) - : base(page) + protected UserBasedTable(int page, IReadOnlyList rankings) + : base(page, rankings) { } From 9a941c4f941c7b0072b0bbe46379530dace1c6c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 02:15:13 +0900 Subject: [PATCH 075/110] Update font loading to use new method --- osu.Game.Tournament/TournamentGameBase.cs | 4 +-- osu.Game/OsuGameBase.cs | 40 +++++++++++------------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 6bff3fb725..6456ce2d58 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -54,8 +54,8 @@ namespace osu.Game.Tournament { Resources.AddStore(new DllResourceStore(@"osu.Game.Tournament.dll")); - Fonts.AddStore(new GlyphStore(Resources, @"Resources/Fonts/Aquatico-Regular")); - Fonts.AddStore(new GlyphStore(Resources, @"Resources/Fonts/Aquatico-Light")); + AddFont(Resources, @"Resources/Fonts/Aquatico-Regular"); + AddFont(Resources, @"Resources/Fonts/Aquatico-Light"); Textures.AddStore(new TextureLoaderStore(new ResourceStore(new StorageBackedResourceStore(storage)))); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 0845a33639..f310da3883 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -131,29 +131,29 @@ namespace osu.Game dependencies.CacheAs(this); dependencies.Cache(LocalConfig); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Medium")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-MediumItalic")); + AddFont(Resources, @"Fonts/osuFont"); + AddFont(Resources, @"Fonts/Exo2.0-Medium"); + AddFont(Resources, @"Fonts/Exo2.0-MediumItalic"); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Basic")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Hangul")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Basic")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Compatibility")); + AddFont(Resources, @"Fonts/Noto-Basic"); + AddFont(Resources, @"Fonts/Noto-Hangul"); + AddFont(Resources, @"Fonts/Noto-CJK-Basic"); + AddFont(Resources, @"Fonts/Noto-CJK-Compatibility"); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Regular")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-RegularItalic")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBold")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBoldItalic")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Bold")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BoldItalic")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Light")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-LightItalic")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Black")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BlackItalic")); + AddFont(Resources, @"Fonts/Exo2.0-Regular"); + AddFont(Resources, @"Fonts/Exo2.0-RegularItalic"); + AddFont(Resources, @"Fonts/Exo2.0-SemiBold"); + AddFont(Resources, @"Fonts/Exo2.0-SemiBoldItalic"); + AddFont(Resources, @"Fonts/Exo2.0-Bold"); + AddFont(Resources, @"Fonts/Exo2.0-BoldItalic"); + AddFont(Resources, @"Fonts/Exo2.0-Light"); + AddFont(Resources, @"Fonts/Exo2.0-LightItalic"); + AddFont(Resources, @"Fonts/Exo2.0-Black"); + AddFont(Resources, @"Fonts/Exo2.0-BlackItalic"); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera-Light")); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera-Medium")); + AddFont(Resources, @"Fonts/Venera"); + AddFont(Resources, @"Fonts/Venera-Light"); + AddFont(Resources, @"Fonts/Venera-Medium"); runMigrations(); From f4f54bc46b6e7dc64a7e0f651ef0fb86f0f85621 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 13:02:15 +0900 Subject: [PATCH 076/110] Fix social browser calling game-wide load stalls --- osu.Game/Users/UserCoverBackground.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index a45fd85901..748d9bd939 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -23,6 +23,7 @@ namespace osu.Game.Users protected override Drawable CreateDrawable(User user) => new Cover(user); + [LongRunningLoad] private class Cover : CompositeDrawable { private readonly User user; From 2663e5d756854a043ef091c66a8973f7ba9b3432 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 13:52:23 +0900 Subject: [PATCH 077/110] Add some more missing LongRunningLoad flags --- osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 1 + osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs | 1 + osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs | 1 + osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs | 1 + 4 files changed, 4 insertions(+) diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index f1ae5d64f5..a9b4bed334 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -16,6 +16,7 @@ using osu.Game.Users; namespace osu.Game.Overlays.MedalSplash { + [LongRunningLoad] public class DrawableMedal : Container, IStateful { private const float scale_when_unlocked = 0.76f; diff --git a/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs b/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs index ea259fe49a..7eed4d3b6b 100644 --- a/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs @@ -12,6 +12,7 @@ using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { + [LongRunningLoad] public class DrawableBadge : CompositeDrawable, IHasTooltip { public static readonly Vector2 DRAWABLE_BADGE_SIZE = new Vector2(86, 40); diff --git a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs index 56ff4d4dec..4563510046 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Overlays.Profile.Sections.Recent { + [LongRunningLoad] public class MedalIcon : Container { private readonly string slug; diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 27cea99f1c..027c53bf58 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -370,6 +370,7 @@ namespace osu.Game.Screens.Ranking.Pages } } + [LongRunningLoad] private class UserHeader : Container { private readonly User user; From e678fe7a773336e5ee2b8b7ed2bb0579101b9748 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 15:35:33 +0900 Subject: [PATCH 078/110] Move potentially expensive load to BDL --- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index 08d396d88e..f947c5585c 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -23,15 +23,25 @@ namespace osu.Game.Overlays.Rankings.Tables private const float row_height = 25; private const int items_per_page = 50; + private readonly int page; + private readonly IReadOnlyList rankings; + protected RankingsTable(int page, IReadOnlyList rankings) { - FillFlowContainer backgroundFlow; + this.page = page; + this.rankings = rankings; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Padding = new MarginPadding { Horizontal = horizontal_inset }; RowSize = new Dimension(GridSizeMode.Absolute, row_height); + } + + [BackgroundDependencyLoader] + private void load() + { + FillFlowContainer backgroundFlow; AddInternal(backgroundFlow = new FillFlowContainer { From b51ebe443199a19806a8d8a51d03d9169fc33a44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 15:50:50 +0900 Subject: [PATCH 079/110] Fix ScoreResultsPage usage --- osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 027c53bf58..43234c0b29 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -70,7 +70,10 @@ namespace osu.Game.Screens.Ranking.Pages Direction = FillDirection.Vertical, Children = new Drawable[] { - new UserHeader(Score.User) + new DelayedLoadWrapper(new UserHeader(Score.User) + { + RelativeSizeAxes = Axes.Both, + }) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, From 3fc2afeb2629061b887220fff116def08f7343b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 15:51:00 +0900 Subject: [PATCH 080/110] Fix UserDimContainer test failing on subsequent runs --- .../Visual/Background/TestSceneUserDimContainer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index f858174ff2..8f71584b4d 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -209,9 +209,10 @@ namespace osu.Game.Tests.Visual.Background public void TransitionTest() { performFullSetup(); - var results = new FadeAccessibleResults(new ScoreInfo { User = new User { Username = "osu!" } }); - AddStep("Transition to Results", () => player.Push(results)); - AddUntilStep("Wait for results is current", results.IsCurrentScreen); + FadeAccessibleResults results = null; + AddStep("Transition to Results", () => player.Push(results = + new FadeAccessibleResults(new ScoreInfo { User = new User { Username = "osu!" } }))); + AddUntilStep("Wait for results is current", () => results.IsCurrentScreen()); waitForDim(); AddAssert("Screen is undimmed, original background retained", () => songSelect.IsBackgroundUndimmed() && songSelect.IsBackgroundCurrent() && results.IsBlurCorrect()); From 5dbc32f49be13313bdc37835fbd38e6cca956113 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 16:19:57 +0900 Subject: [PATCH 081/110] Fix MedalIcon usage --- .../Profile/Sections/DrawableProfileRow.cs | 35 +++++++++---------- .../Sections/Recent/DrawableRecentActivity.cs | 7 ++-- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs index 23fe6e9cd5..03ee29d0c2 100644 --- a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs +++ b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs @@ -19,8 +19,8 @@ namespace osu.Game.Overlays.Profile.Sections private const int fade_duration = 200; private Box underscoreLine; - private readonly Box coloredBackground; - private readonly Container background; + private Box coloredBackground; + private Container background; /// /// A visual element displayed to the left of content. @@ -36,6 +36,19 @@ namespace osu.Game.Overlays.Profile.Sections { RelativeSizeAxes = Axes.X; Height = 60; + + Content = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 0.97f, + }; + } + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colour) + { InternalChildren = new Drawable[] { background = new Container @@ -53,21 +66,7 @@ namespace osu.Game.Overlays.Profile.Sections }, Child = coloredBackground = new Box { RelativeSizeAxes = Axes.Both } }, - Content = new Container - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 0.97f, - }, - }; - } - - [BackgroundDependencyLoader(true)] - private void load(OsuColour colour) - { - AddRange(new Drawable[] - { + Content, underscoreLine = new Box { Anchor = Anchor.BottomCentre, @@ -101,7 +100,7 @@ namespace osu.Game.Overlays.Profile.Sections Origin = Anchor.CentreRight, Direction = FillDirection.Vertical, }, - }); + }; coloredBackground.Colour = underscoreLine.Colour = colour.Gray4; } diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index b5a508bff7..4e856845ac 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -66,11 +66,14 @@ namespace osu.Game.Overlays.Profile.Sections.Recent }; case RecentActivityType.Achievement: - return new MedalIcon(activity.Achievement.Slug) + return new DelayedLoadWrapper(new MedalIcon(activity.Achievement.Slug) + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + }) { RelativeSizeAxes = Axes.Y, Width = 60, - FillMode = FillMode.Fit, }; default: From f181ee18434cea3c22f09ae470a3bc651cb6e8d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 17:35:11 +0900 Subject: [PATCH 082/110] Hide the menu cursor while inside the playfield by default --- osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs | 3 +++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 4 ++++ osu.Game/Rulesets/UI/Playfield.cs | 18 +++++++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index aa61fb6922..49aea52902 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; +using osuTK; namespace osu.Game.Rulesets.Osu.UI { @@ -30,6 +31,8 @@ namespace osu.Game.Rulesets.Osu.UI { } + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; // always show the gameplay cursor + public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this); protected override Playfield CreatePlayfield() => new OsuPlayfield(); diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 5ed1e5a368..96275c1274 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -34,6 +34,7 @@ using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osuTK; namespace osu.Game.Rulesets.UI { @@ -331,6 +332,9 @@ namespace osu.Game.Rulesets.UI protected override bool OnHover(HoverEvent e) => true; // required for IProvideCursor + // only show the cursor when within the playfield, by default. + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Playfield.ReceivePositionalInputAt(screenSpacePos); + CursorContainer IProvideCursor.Cursor => Playfield.Cursor; public override GameplayCursorContainer Cursor => Playfield.Cursor; diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index ca4983e3d7..047047ccfd 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -100,10 +100,13 @@ namespace osu.Game.Rulesets.UI public GameplayCursorContainer Cursor { get; private set; } /// - /// Provide an optional cursor which is to be used for gameplay. + /// Provide a cursor which is to be used for gameplay. /// - /// The cursor, or null if a cursor is not rqeuired. - protected virtual GameplayCursorContainer CreateCursor() => null; + /// + /// The default provided cursor is invisible when inside the bounds of the . + /// + /// The cursor, or null to show the menu cursor. + protected virtual GameplayCursorContainer CreateCursor() => new InvisibleCursorContainer(); /// /// Registers a as a nested . @@ -143,5 +146,14 @@ namespace osu.Game.Rulesets.UI /// Creates the container that will be used to contain the s. /// protected virtual HitObjectContainer CreateHitObjectContainer() => new HitObjectContainer(); + + public class InvisibleCursorContainer : GameplayCursorContainer + { + protected override Drawable CreateCursor() => new InvisibleCursor(); + + private class InvisibleCursor : Drawable + { + } + } } } From 4f081f2fe897ca4700696ab3e5d26a94aefb77c3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 17:38:28 +0900 Subject: [PATCH 083/110] Remove catch-specific cursor provider --- .../UI/CatchCursorContainer.cs | 17 ----------------- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 3 --- 2 files changed, 20 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs diff --git a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs deleted file mode 100644 index 163718f202..0000000000 --- a/osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osu.Game.Rulesets.UI; - -namespace osu.Game.Rulesets.Catch.UI -{ - public class CatchCursorContainer : GameplayCursorContainer - { - protected override Drawable CreateCursor() => new InvisibleCursor(); - - private class InvisibleCursor : Drawable - { - } - } -} diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 7741096da2..b6d8cf9cbe 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -9,7 +9,6 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI @@ -20,8 +19,6 @@ namespace osu.Game.Rulesets.Catch.UI internal readonly CatcherArea CatcherArea; - protected override GameplayCursorContainer CreateCursor() => new CatchCursorContainer(); - public CatchPlayfield(BeatmapDifficulty difficulty, Func> createDrawableRepresentation) { Container explodingFruitContainer; From 3864ea6ca3ddf8d59568558448fde9597af1a44a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 18:24:46 +0900 Subject: [PATCH 084/110] Move position updating logic back to CatcherArea --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 11 ++--------- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 062c0f8b26..a2554850c0 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; @@ -38,14 +38,7 @@ namespace osu.Game.Rulesets.Catch.Mods protected override bool OnMouseMove(MouseMoveEvent e) { - //lock catcher to mouse position horizontally - catcher.X = e.MousePosition.X / DrawSize.X; - - //make Yuzu face the direction he's moving - var direction = Math.Sign(e.Delta.X); - if (direction != 0) - catcher.Scale = new Vector2(Math.Abs(catcher.Scale.X) * direction, catcher.Scale.Y); - + catcher.UpdatePosition(e.MousePosition.X / DrawSize.X); return base.OnMouseMove(e); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 49393a836f..2d6ce02e45 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -377,8 +377,7 @@ namespace osu.Game.Rulesets.Catch.UI double dashModifier = Dashing ? 1 : 0.5; double speed = BASE_SPEED * dashModifier * hyperDashModifier; - Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)Math.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + UpdatePosition((float)(X + direction * Clock.ElapsedFrameTime * speed)); // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || @@ -452,6 +451,17 @@ namespace osu.Game.Rulesets.Catch.UI fruit.LifetimeStart = Time.Current; fruit.Expire(); } + + public void UpdatePosition(float position) + { + position = Math.Clamp(position, 0, 1); + + if (position == X) + return; + + Scale = new Vector2(Math.Abs(Scale.X) * (position > X ? 1 : -1), Scale.Y); + X = position; + } } } } From 63128c9465669cda7e699d608cc33aeb46b8c844 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 18:25:11 +0900 Subject: [PATCH 085/110] Extend mouse hiding in catch to include catcher area --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index b6d8cf9cbe..589503c35b 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; +using osuTK; namespace osu.Game.Rulesets.Catch.UI { @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.UI internal readonly CatcherArea CatcherArea; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) || CatcherArea.ReceivePositionalInputAt(screenSpacePos); + public CatchPlayfield(BeatmapDifficulty difficulty, Func> createDrawableRepresentation) { Container explodingFruitContainer; From c7305f0b4462cf77440d9f74dc42e37f9e7fe6ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 18:25:24 +0900 Subject: [PATCH 086/110] Simplify implementation structure --- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index a2554850c0..a47efcc10a 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -1,8 +1,7 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; @@ -11,7 +10,6 @@ using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osuTK; -using System; namespace osu.Game.Rulesets.Catch.Mods { @@ -19,16 +17,20 @@ namespace osu.Game.Rulesets.Catch.Mods { public override string Description => @"Use the mouse to control the catcher."; - public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) => - ((Container)drawableRuleset.Playfield.Parent).Add(new CatchModRelaxHelper(drawableRuleset.Playfield as CatchPlayfield)); + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + drawableRuleset.Cursor.Add(new MouseInputHelper((CatchPlayfield)drawableRuleset.Playfield)); + } - private class CatchModRelaxHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition + private class MouseInputHelper : Drawable, IKeyBindingHandler, IRequireHighFrequencyMousePosition { private readonly CatcherArea.Catcher catcher; - public CatchModRelaxHelper(CatchPlayfield catchPlayfield) + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + + public MouseInputHelper(CatchPlayfield playfield) { - catcher = catchPlayfield.CatcherArea.MovableCatcher; + catcher = playfield.CatcherArea.MovableCatcher; RelativeSizeAxes = Axes.Both; } From c49aeb08c4f2a135831f245eac39c2d6cdf976e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Nov 2019 20:03:14 +0900 Subject: [PATCH 087/110] Add API methods to perform requests out-of-queue --- osu.Game.Tournament/TournamentGameBase.cs | 2 +- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- .../DownloadableArchiveModelManager.cs | 12 +----------- osu.Game/Online/API/APIAccess.cs | 17 +++++++++++++++++ osu.Game/Online/API/DummyAPIAccess.cs | 5 +++++ osu.Game/Online/API/IAPIProvider.cs | 19 +++++++++++++++++++ .../Changelog/ChangelogSingleBuild.cs | 14 +------------- osu.Game/Overlays/ChangelogOverlay.cs | 10 +--------- 8 files changed, 46 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 6456ce2d58..4d7abfe272 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -228,7 +228,7 @@ namespace osu.Game.Tournament if (b.BeatmapInfo == null && b.ID > 0) { var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); - req.Perform(API); + API.Perform(req); b.BeatmapInfo = req.Result?.ToBeatmap(RulesetStore); addedInfo = true; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index bc78e50f5d..a2e750cac5 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -398,7 +398,7 @@ namespace osu.Game.Beatmaps try { // intentionally blocking to limit web request concurrency - req.Perform(api); + api.Perform(req); var res = req.Result; diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index 0b7d63f469..243060388f 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -99,17 +99,7 @@ namespace osu.Game.Database currentDownloads.Add(request); PostNotification?.Invoke(notification); - Task.Factory.StartNew(() => - { - try - { - request.Perform(api); - } - catch (Exception error) - { - triggerFailure(error); - } - }, TaskCreationOptions.LongRunning); + api.PerformAsync(request); DownloadBegan?.Invoke(request); return true; diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index b6127027cc..1c45d26afd 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Net; using System.Net.Http; using System.Threading; +using System.Threading.Tasks; using Newtonsoft.Json.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -198,6 +199,22 @@ namespace osu.Game.Online.API } } + public void Perform(APIRequest request) + { + try + { + request.Perform(this); + } + catch (Exception e) + { + // todo: fix exception handling + request.Fail(e); + } + } + + public Task PerformAsync(APIRequest request) => + Task.Factory.StartNew(() => Perform(request), TaskCreationOptions.LongRunning); + public void Login(string username, string password) { Debug.Assert(State == APIState.Offline); diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 28132765d3..7f23f9b5d5 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Users; @@ -56,6 +57,10 @@ namespace osu.Game.Online.API { } + public void Perform(APIRequest request) { } + + public Task PerformAsync(APIRequest request) => Task.CompletedTask; + public void Register(IOnlineComponent component) { Scheduler.Add(delegate { components.Add(component); }); diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index 0cd41aee26..dff6d0b2ce 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.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.Threading.Tasks; using osu.Framework.Bindables; using osu.Game.Users; @@ -42,6 +43,24 @@ namespace osu.Game.Online.API /// The request to perform. void Queue(APIRequest request); + /// + /// Perform a request immediately, bypassing any API state checks. + /// + /// + /// Can be used to run requests as a guest user. + /// + /// The request to perform. + void Perform(APIRequest request); + + /// + /// Perform a request immediately, bypassing any API state checks. + /// + /// + /// Can be used to run requests as a guest user. + /// + /// The request to perform. + Task PerformAsync(APIRequest request); + /// /// Register a component to receive state changes. /// diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 3297b00322..67bcb6f558 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using System.Threading; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -43,18 +42,7 @@ namespace osu.Game.Overlays.Changelog }; req.Failure += _ => complete = true; - // This is done on a separate thread to support cancellation below - Task.Run(() => - { - try - { - req.Perform(api); - } - catch - { - complete = true; - } - }); + api.PerformAsync(req); while (!complete) { diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 559989af5c..fbc9dfcbd9 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -191,15 +191,7 @@ namespace osu.Game.Overlays tcs.SetResult(false); }; - try - { - req.Perform(API); - } - catch - { - initialFetchTask = null; - tcs.SetResult(false); - } + await API.PerformAsync(req); await tcs.Task; }); From 3b88afd069fd179195d4593db439e9da9247cdaf Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 1 Dec 2019 12:02:47 -0800 Subject: [PATCH 088/110] Fix overlays closing when dragging from in/out or out/in --- .../Containers/OsuFocusedOverlayContainer.cs | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index b117d71006..4977b6b70a 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -67,33 +67,21 @@ namespace osu.Game.Graphics.Containers // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BlockScreenWideMouse || base.ReceivePositionalInputAt(screenSpacePos); - protected override bool OnClick(ClickEvent e) - { - if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) - Hide(); + private bool closeOnMouseUp; - return base.OnClick(e); + protected override bool OnMouseDown(MouseDownEvent e) + { + closeOnMouseUp = !base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition) ? true : false; + + return base.OnMouseDown(e); } - private bool closeOnDragEnd; - - protected override bool OnDragStart(DragStartEvent e) + protected override bool OnMouseUp(MouseUpEvent e) { - if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) - closeOnDragEnd = true; - - return base.OnDragStart(e); - } - - protected override bool OnDragEnd(DragEndEvent e) - { - if (closeOnDragEnd) - { + if (closeOnMouseUp && !base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) Hide(); - closeOnDragEnd = false; - } - return base.OnDragEnd(e); + return base.OnMouseUp(e); } public virtual bool OnPressed(GlobalAction action) From 74176a69545d569895914ab03cfa359370408850 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 1 Dec 2019 12:54:37 -0800 Subject: [PATCH 089/110] Remove redundant ternary expression --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 4977b6b70a..facf70b47a 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -71,7 +71,7 @@ namespace osu.Game.Graphics.Containers protected override bool OnMouseDown(MouseDownEvent e) { - closeOnMouseUp = !base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition) ? true : false; + closeOnMouseUp = !base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition); return base.OnMouseDown(e); } From 59f956bb01e550e0723355467275b17348e32fe6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2019 07:18:54 +0000 Subject: [PATCH 090/110] Bump Microsoft.CodeAnalysis.BannedApiAnalyzers from 2.9.7 to 2.9.8 Bumps [Microsoft.CodeAnalysis.BannedApiAnalyzers](https://github.com/dotnet/roslyn-analyzers) from 2.9.7 to 2.9.8. - [Release notes](https://github.com/dotnet/roslyn-analyzers/releases) - [Changelog](https://github.com/dotnet/roslyn-analyzers/blob/master/PostReleaseActivities.md) - [Commits](https://github.com/dotnet/roslyn-analyzers/compare/v2.9.7...v2.9.8) Signed-off-by: dependabot-preview[bot] --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index c8d441a78c..c0d740bac1 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -16,7 +16,7 @@ - + From 6893ec22bbf7610c2736e7ba485650c5bef4f722 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 2 Dec 2019 16:14:52 +0900 Subject: [PATCH 091/110] Fix currenTrackCompleted not being run on main thread --- osu.Game/OsuGame.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e978df404f..c7c746bed3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -406,11 +406,11 @@ namespace osu.Game nextBeatmap?.LoadBeatmapAsync(); } - private void currentTrackCompleted() + private void currentTrackCompleted() => Schedule(() => { if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled) musicController.NextTrack(); - } + }); #endregion From 1ec11946c63f56467de94a303ed1be07272a1a44 Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Mon, 2 Dec 2019 18:45:57 +0700 Subject: [PATCH 092/110] Fix spelling in comment on SearchTextBox.OnPressed --- osu.Game/Graphics/UserInterface/SearchTextBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index e2b0e1b425..ff3618b263 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -35,7 +35,7 @@ namespace osu.Game.Graphics.UserInterface public override bool OnPressed(PlatformAction action) { // Shift+delete is handled via PlatformAction on macOS. this is not so useful in the context of a SearchTextBox - // as we do not allow arrow key navigation in the first place (ie. the care should always be at the end of text) + // as we do not allow arrow key navigation in the first place (ie. the caret should always be at the end of text) // Avoid handling it here to allow other components to potentially consume the shortcut. if (action.ActionType == PlatformActionType.CharNext && action.ActionMethod == PlatformActionMethod.Delete) return false; From aadbbb1af3c100e8145332384b8b07bb5c4bcff9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 3 Dec 2019 13:33:42 +0900 Subject: [PATCH 093/110] Fix replay download button not working --- osu.Game.Tests/Scores/IO/TestScoreEquality.cs | 73 +++++++++++++++++++ osu.Game/Scoring/ScoreInfo.cs | 21 ++++-- 2 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Tests/Scores/IO/TestScoreEquality.cs diff --git a/osu.Game.Tests/Scores/IO/TestScoreEquality.cs b/osu.Game.Tests/Scores/IO/TestScoreEquality.cs new file mode 100644 index 0000000000..d1374eb6e5 --- /dev/null +++ b/osu.Game.Tests/Scores/IO/TestScoreEquality.cs @@ -0,0 +1,73 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Scoring; + +namespace osu.Game.Tests.Scores.IO +{ + [TestFixture] + public class TestScoreEquality + { + [Test] + public void TestNonMatchingByReference() + { + ScoreInfo score1 = new ScoreInfo(); + ScoreInfo score2 = new ScoreInfo(); + + Assert.That(score1, Is.Not.EqualTo(score2)); + } + + [Test] + public void TestMatchingByReference() + { + ScoreInfo score = new ScoreInfo(); + + Assert.That(score, Is.EqualTo(score)); + } + + [Test] + public void TestNonMatchingByPrimaryKey() + { + ScoreInfo score1 = new ScoreInfo { ID = 1 }; + ScoreInfo score2 = new ScoreInfo { ID = 2 }; + + Assert.That(score1, Is.Not.EqualTo(score2)); + } + + [Test] + public void TestMatchingByPrimaryKey() + { + ScoreInfo score1 = new ScoreInfo { ID = 1 }; + ScoreInfo score2 = new ScoreInfo { ID = 1 }; + + Assert.That(score1, Is.EqualTo(score2)); + } + + [Test] + public void TestNonMatchingByHash() + { + ScoreInfo score1 = new ScoreInfo { Hash = "a" }; + ScoreInfo score2 = new ScoreInfo { Hash = "b" }; + + Assert.That(score1, Is.Not.EqualTo(score2)); + } + + [Test] + public void TestMatchingByHash() + { + ScoreInfo score1 = new ScoreInfo { Hash = "a" }; + ScoreInfo score2 = new ScoreInfo { Hash = "a" }; + + Assert.That(score1, Is.EqualTo(score2)); + } + + [Test] + public void TestNonMatchingByNull() + { + ScoreInfo score = new ScoreInfo(); + + Assert.That(score, Is.Not.EqualTo(null)); + } + } +} diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index f7bac82e74..c7609e8a0b 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -183,10 +183,21 @@ namespace osu.Game.Scoring public override string ToString() => $"{User} playing {Beatmap}"; - public bool Equals(ScoreInfo other) => - other != null - && other.OnlineScoreID == OnlineScoreID - && other.BeatmapInfoID == BeatmapInfoID - && other.Hash == Hash; + public bool Equals(ScoreInfo other) + { + if (other == null) + return false; + + if (ID != 0 && other.ID != 0) + return ID == other.ID; + + if (OnlineScoreID.HasValue && other.OnlineScoreID.HasValue) + return OnlineScoreID == other.OnlineScoreID; + + if (!string.IsNullOrEmpty(Hash) && !string.IsNullOrEmpty(other.Hash)) + return Hash == other.Hash; + + return ReferenceEquals(this, other); + } } } From f0d49d0cdf3283f8d1680ab118adc3f0f5e4315d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Dec 2019 15:28:10 +0900 Subject: [PATCH 094/110] Decouple APILegacyScoreInfo from ScoreInfo --- .../Difficulty/CatchPerformanceCalculator.cs | 10 +- .../Gameplay/TestSceneReplayDownloadButton.cs | 11 +- .../Visual/Online/TestSceneScoresContainer.cs | 50 +++-- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 3 +- .../TestSceneUserTopScoreContainer.cs | 3 +- .../Online/API/Requests/GetScoresRequest.cs | 7 +- .../Requests/Responses/APILegacyScoreInfo.cs | 161 ++++++++-------- .../BeatmapSet/Scores/ScoresContainer.cs | 14 +- .../Sections/Ranks/PaginatedScoreContainer.cs | 12 +- osu.Game/Scoring/Legacy/LegacyScoreInfo.cs | 177 ++++++++++-------- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 14 +- .../Ranking/Pages/ReplayDownloadButton.cs | 3 +- .../Select/Leaderboards/BeatmapLeaderboard.cs | 5 +- .../Leaderboards/UserTopScoreContainer.cs | 11 +- 14 files changed, 254 insertions(+), 227 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 3c237c86be..a6283eb7c4 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -34,12 +34,10 @@ namespace osu.Game.Rulesets.Catch.Difficulty { mods = Score.Mods; - var legacyScore = Score as LegacyScoreInfo; - - fruitsHit = legacyScore?.Count300 ?? Score.Statistics[HitResult.Perfect]; - ticksHit = legacyScore?.Count100 ?? 0; - tinyTicksHit = legacyScore?.Count50 ?? 0; - tinyTicksMissed = legacyScore?.CountKatu ?? 0; + fruitsHit = Score?.GetCount300() ?? Score.Statistics[HitResult.Perfect]; + ticksHit = Score?.GetCount100() ?? 0; + tinyTicksHit = Score?.GetCount50() ?? 0; + tinyTicksMissed = Score?.GetCountKatu() ?? 0; misses = Score.Statistics[HitResult.Miss]; // Don't count scores made with supposedly unranked mods diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index 7b22fedbd5..8cb44de8cb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -5,11 +5,12 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Rulesets.Osu; using osu.Game.Scoring; using osu.Game.Users; using System; using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Game.Rulesets; using osu.Game.Screens.Ranking.Pages; namespace osu.Game.Tests.Visual.Gameplay @@ -17,6 +18,9 @@ namespace osu.Game.Tests.Visual.Gameplay [TestFixture] public class TestSceneReplayDownloadButton : OsuTestScene { + [Resolved] + private RulesetStore rulesets { get; set; } + public override IReadOnlyList RequiredTypes => new[] { typeof(ReplayDownloadButton) @@ -49,16 +53,15 @@ namespace osu.Game.Tests.Visual.Gameplay { return new APILegacyScoreInfo { - ID = 1, OnlineScoreID = 2553163309, - Ruleset = new OsuRuleset().RulesetInfo, + OnlineRulesetID = 0, Replay = replayAvailable, User = new User { Id = 39828, Username = @"WubWoofWolf", } - }; + }.CreateScoreInfo(rulesets); } private class TestReplayDownloadButton : ReplayDownloadButton diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index b26de1984a..3386cc41e7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -9,9 +9,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Scores; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; using osuTK.Graphics; @@ -66,12 +64,12 @@ namespace osu.Game.Tests.Visual.Online FlagName = @"ES", }, }, - Mods = new Mod[] + Mods = new[] { - new OsuModDoubleTime(), - new OsuModHidden(), - new OsuModFlashlight(), - new OsuModHardRock(), + new OsuModDoubleTime().Acronym, + new OsuModHidden().Acronym, + new OsuModFlashlight().Acronym, + new OsuModHardRock().Acronym, }, Rank = ScoreRank.XH, PP = 200, @@ -91,11 +89,11 @@ namespace osu.Game.Tests.Visual.Online FlagName = @"BR", }, }, - Mods = new Mod[] + Mods = new[] { - new OsuModDoubleTime(), - new OsuModHidden(), - new OsuModFlashlight(), + new OsuModDoubleTime().Acronym, + new OsuModHidden().Acronym, + new OsuModFlashlight().Acronym, }, Rank = ScoreRank.S, PP = 190, @@ -115,10 +113,10 @@ namespace osu.Game.Tests.Visual.Online FlagName = @"JP", }, }, - Mods = new Mod[] + Mods = new[] { - new OsuModDoubleTime(), - new OsuModHidden(), + new OsuModDoubleTime().Acronym, + new OsuModHidden().Acronym, }, Rank = ScoreRank.B, PP = 180, @@ -138,9 +136,9 @@ namespace osu.Game.Tests.Visual.Online FlagName = @"CA", }, }, - Mods = new Mod[] + Mods = new[] { - new OsuModDoubleTime(), + new OsuModDoubleTime().Acronym, }, Rank = ScoreRank.C, PP = 170, @@ -208,12 +206,12 @@ namespace osu.Game.Tests.Visual.Online FlagName = @"ES", }, }, - Mods = new Mod[] + Mods = new[] { - new OsuModDoubleTime(), - new OsuModHidden(), - new OsuModFlashlight(), - new OsuModHardRock(), + new OsuModDoubleTime().Acronym, + new OsuModHidden().Acronym, + new OsuModFlashlight().Acronym, + new OsuModHardRock().Acronym, }, Rank = ScoreRank.XH, PP = 200, @@ -226,10 +224,10 @@ namespace osu.Game.Tests.Visual.Online foreach (var s in allScores.Scores) { - s.Statistics.Add(HitResult.Great, RNG.Next(2000)); - s.Statistics.Add(HitResult.Good, RNG.Next(2000)); - s.Statistics.Add(HitResult.Meh, RNG.Next(2000)); - s.Statistics.Add(HitResult.Miss, RNG.Next(2000)); + s.Statistics.Add("count_300", RNG.Next(2000)); + s.Statistics.Add("count_100", RNG.Next(2000)); + s.Statistics.Add("count_50", RNG.Next(2000)); + s.Statistics.Add("count_miss", RNG.Next(2000)); } AddStep("Load all scores", () => diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index fb27ec7654..57e297bcd5 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; using osu.Game.Screens.Select.Leaderboards; @@ -62,7 +61,7 @@ namespace osu.Game.Tests.Visual.SongSelect Accuracy = 1, MaxCombo = 244, TotalScore = 1707827, - Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, + Mods = new[] { new OsuModHidden().Acronym, new OsuModHardRock().Acronym, }, User = new User { Id = 6602580, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index 7fac45e0f1..e34e1844ce 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Shapes; using osuTK.Graphics; using osu.Game.Online.API.Requests.Responses; using osu.Game.Scoring; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; @@ -52,7 +51,7 @@ namespace osu.Game.Tests.Visual.SongSelect Accuracy = 1, MaxCombo = 244, TotalScore = 1707827, - Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, + Mods = new[] { new OsuModHidden().Acronym, new OsuModHardRock().Acronym, }, User = new User { Id = 6602580, diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 50844fa256..bf3441d2a0 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -9,6 +9,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using System.Text; using System.Collections.Generic; +using System.Diagnostics; namespace osu.Game.Online.API.Requests { @@ -37,10 +38,12 @@ namespace osu.Game.Online.API.Requests private void onSuccess(APILegacyScores r) { + Debug.Assert(ruleset.ID != null, "ruleset.ID != null"); + foreach (APILegacyScoreInfo score in r.Scores) { score.Beatmap = beatmap; - score.Ruleset = ruleset; + score.OnlineRulesetID = ruleset.ID.Value; } var userScore = r.UserScore; @@ -48,7 +51,7 @@ namespace osu.Game.Online.API.Requests if (userScore != null) { userScore.Score.Beatmap = beatmap; - userScore.Score.Ruleset = ruleset; + userScore.Score.OnlineRulesetID = ruleset.ID.Value; } } diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs index 17da255873..d231b8a5df 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs @@ -5,56 +5,103 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; using osu.Game.Scoring.Legacy; using osu.Game.Users; namespace osu.Game.Online.API.Requests.Responses { - public class APILegacyScoreInfo : LegacyScoreInfo + public class APILegacyScoreInfo { - [JsonProperty(@"score")] - private int totalScore + public ScoreInfo CreateScoreInfo(RulesetStore rulesets) { - set => TotalScore = value; + var ruleset = rulesets.GetRuleset(OnlineRulesetID); + + var mods = Mods != null ? ruleset.CreateInstance().GetAllMods().Where(mod => Mods.Contains(mod.Acronym)).ToArray() : Array.Empty(); + + var scoreInfo = new ScoreInfo + { + TotalScore = TotalScore, + MaxCombo = MaxCombo, + User = User, + Accuracy = Accuracy, + OnlineScoreID = OnlineScoreID, + Date = Date, + PP = PP, + Beatmap = Beatmap, + RulesetID = OnlineRulesetID, + Hash = "online", // todo: temporary? + Rank = Rank, + Ruleset = ruleset, + Mods = mods, + }; + + foreach (var kvp in Statistics) + { + switch (kvp.Key) + { + case @"count_geki": + scoreInfo.SetCountGeki(kvp.Value); + break; + + case @"count_300": + scoreInfo.SetCount300(kvp.Value); + break; + + case @"count_katu": + scoreInfo.SetCountKatu(kvp.Value); + break; + + case @"count_100": + scoreInfo.SetCount100(kvp.Value); + break; + + case @"count_50": + scoreInfo.SetCount50(kvp.Value); + break; + + case @"count_miss": + scoreInfo.SetCountMiss(kvp.Value); + break; + } + } + + return scoreInfo; } + [JsonProperty(@"score")] + public int TotalScore { get; set; } + [JsonProperty(@"max_combo")] - private int maxCombo - { - set => MaxCombo = value; - } + public int MaxCombo { get; set; } [JsonProperty(@"user")] - private User user - { - set => User = value; - } + public User User { get; set; } [JsonProperty(@"id")] - private long onlineScoreID - { - set => OnlineScoreID = value; - } + public long OnlineScoreID { get; set; } [JsonProperty(@"replay")] public bool Replay { get; set; } [JsonProperty(@"created_at")] - private DateTimeOffset date - { - set => Date = value; - } + public DateTimeOffset Date { get; set; } [JsonProperty(@"beatmap")] - private BeatmapInfo beatmap - { - set => Beatmap = value; - } + public BeatmapInfo Beatmap { get; set; } + + [JsonProperty("accuracy")] + public double Accuracy { get; set; } + + [JsonProperty(@"pp")] + public double? PP { get; set; } [JsonProperty(@"beatmapset")] - private BeatmapMetadata metadata + public BeatmapMetadata Metadata { set { @@ -67,68 +114,16 @@ namespace osu.Game.Online.API.Requests.Responses } [JsonProperty(@"statistics")] - private Dictionary jsonStats - { - set - { - foreach (var kvp in value) - { - switch (kvp.Key) - { - case @"count_geki": - CountGeki = kvp.Value; - break; - - case @"count_300": - Count300 = kvp.Value; - break; - - case @"count_katu": - CountKatu = kvp.Value; - break; - - case @"count_100": - Count100 = kvp.Value; - break; - - case @"count_50": - Count50 = kvp.Value; - break; - - case @"count_miss": - CountMiss = kvp.Value; - break; - - default: - continue; - } - } - } - } + public Dictionary Statistics { get; set; } [JsonProperty(@"mode_int")] - public int OnlineRulesetID - { - get => RulesetID; - set => RulesetID = value; - } + public int OnlineRulesetID { get; set; } [JsonProperty(@"mods")] - private string[] modStrings { get; set; } + public string[] Mods { get; set; } - public override RulesetInfo Ruleset - { - get => base.Ruleset; - set - { - base.Ruleset = value; - - if (modStrings != null) - { - // Evaluate the mod string - Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.Acronym)).ToArray(); - } - } - } + [JsonProperty("rank")] + [JsonConverter(typeof(StringEnumConverter))] + public ScoreRank Rank { get; set; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index f06f2ac802..0378d364b8 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -41,6 +41,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private RulesetStore rulesets { get; set; } + private GetScoresRequest getScoresRequest; protected APILegacyScores Scores @@ -56,16 +59,19 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; } - scoreTable.Scores = value.Scores; + var scoreInfos = value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToList(); + + scoreTable.Scores = scoreInfos; scoreTable.Show(); - var topScore = value.Scores.First(); + var topScore = scoreInfos.First(); var userScore = value.UserScore; + var userScoreInfo = userScore?.Score.CreateScoreInfo(rulesets); topScoresContainer.Add(new DrawableTopScore(topScore)); - if (userScore != null && userScore.Score.OnlineScoreID != topScore.OnlineScoreID) - topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); + if (userScoreInfo != null && userScoreInfo.OnlineScoreID != topScore.OnlineScoreID) + topScoresContainer.Add(new DrawableTopScore(userScoreInfo, userScore.Position)); }); } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 853b9db0a7..5b58fc0930 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -29,14 +29,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks ItemsContainer.Direction = FillDirection.Vertical; } - protected override void UpdateItems(List items) - { - foreach (var item in items) - item.Ruleset = Rulesets.GetRuleset(item.RulesetID); - - base.UpdateItems(items); - } - protected override APIRequest> CreateRequest() => new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); @@ -45,10 +37,10 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks switch (type) { default: - return new DrawablePerformanceScore(model, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null); + return new DrawablePerformanceScore(model.CreateScoreInfo(Rulesets), includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null); case ScoreType.Recent: - return new DrawableTotalScore(model); + return new DrawableTotalScore(model.CreateScoreInfo(Rulesets)); } } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs b/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs index e66f93ec8d..2ee450b501 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs @@ -5,114 +5,139 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring.Legacy { - public class LegacyScoreInfo : ScoreInfo + public static class ScoreInfoLegacyExtensions { - private int countGeki; - - public int CountGeki + public static int? GetCountGeki(this ScoreInfo scoreInfo) { - get => countGeki; - set + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) { - countGeki = value; + case 3: + return scoreInfo.Statistics[HitResult.Perfect]; + } - switch (Ruleset?.ID ?? RulesetID) - { - case 3: - Statistics[HitResult.Perfect] = value; - break; - } + return null; + } + + public static void SetCountGeki(this ScoreInfo scoreInfo, int value) + { + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) + { + case 3: + scoreInfo.Statistics[HitResult.Perfect] = value; + break; } } - private int count300; - - public int Count300 + public static int? GetCount300(this ScoreInfo scoreInfo) { - get => count300; - set + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) { - count300 = value; + case 0: + case 1: + case 3: + return scoreInfo.Statistics[HitResult.Great]; - switch (Ruleset?.ID ?? RulesetID) - { - case 0: - case 1: - case 3: - Statistics[HitResult.Great] = value; - break; + case 2: + return scoreInfo.Statistics[HitResult.Perfect]; + } - case 2: - Statistics[HitResult.Perfect] = value; - break; - } + return null; + } + + public static void SetCount300(this ScoreInfo scoreInfo, int value) + { + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) + { + case 0: + case 1: + case 3: + scoreInfo.Statistics[HitResult.Great] = value; + break; + + case 2: + scoreInfo.Statistics[HitResult.Perfect] = value; + break; } } - private int countKatu; - - public int CountKatu + public static int? GetCountKatu(this ScoreInfo scoreInfo) { - get => countKatu; - set + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) { - countKatu = value; + case 3: + return scoreInfo.Statistics[HitResult.Good]; + } - switch (Ruleset?.ID ?? RulesetID) - { - case 3: - Statistics[HitResult.Good] = value; - break; - } + return null; + } + + public static void SetCountKatu(this ScoreInfo scoreInfo, int value) + { + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) + { + case 3: + scoreInfo.Statistics[HitResult.Good] = value; + break; } } - private int count100; - - public int Count100 + public static int? GetCount100(this ScoreInfo scoreInfo) { - get => count100; - set + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) { - count100 = value; + case 0: + case 1: + return scoreInfo.Statistics[HitResult.Good]; - switch (Ruleset?.ID ?? RulesetID) - { - case 0: - case 1: - Statistics[HitResult.Good] = value; - break; + case 3: + return scoreInfo.Statistics[HitResult.Ok]; + } - case 3: - Statistics[HitResult.Ok] = value; - break; - } + return null; + } + + public static void SetCount100(this ScoreInfo scoreInfo, int value) + { + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) + { + case 0: + case 1: + scoreInfo.Statistics[HitResult.Good] = value; + break; + + case 3: + scoreInfo.Statistics[HitResult.Ok] = value; + break; } } - private int count50; - - public int Count50 + public static int? GetCount50(this ScoreInfo scoreInfo) { - get => count50; - set + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) { - count50 = value; + case 0: + case 3: + return scoreInfo.Statistics[HitResult.Meh]; + } - switch (Ruleset?.ID ?? RulesetID) - { - case 0: - case 3: - Statistics[HitResult.Meh] = value; - break; - } + return null; + } + + public static void SetCount50(this ScoreInfo scoreInfo, int value) + { + switch (scoreInfo.Ruleset?.ID ?? scoreInfo.RulesetID) + { + case 0: + case 3: + scoreInfo.Statistics[HitResult.Meh] = value; + break; } } - public int CountMiss - { - get => Statistics[HitResult.Miss]; - set => Statistics[HitResult.Miss] = value; - } + public static int? GetCountMiss(this ScoreInfo scoreInfo) => + scoreInfo.Statistics[HitResult.Miss]; + + public static void SetCountMiss(this ScoreInfo scoreInfo, int value) => + scoreInfo.Statistics[HitResult.Miss] = value; } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 2cdd0c4b5e..0029c843b4 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -35,7 +35,7 @@ namespace osu.Game.Scoring.Legacy using (SerializationReader sr = new SerializationReader(stream)) { currentRuleset = GetRuleset(sr.ReadByte()); - var scoreInfo = new LegacyScoreInfo { Ruleset = currentRuleset.RulesetInfo }; + var scoreInfo = new ScoreInfo { Ruleset = currentRuleset.RulesetInfo }; score.ScoreInfo = scoreInfo; @@ -53,12 +53,12 @@ namespace osu.Game.Scoring.Legacy // MD5Hash sr.ReadString(); - scoreInfo.Count300 = sr.ReadUInt16(); - scoreInfo.Count100 = sr.ReadUInt16(); - scoreInfo.Count50 = sr.ReadUInt16(); - scoreInfo.CountGeki = sr.ReadUInt16(); - scoreInfo.CountKatu = sr.ReadUInt16(); - scoreInfo.CountMiss = sr.ReadUInt16(); + scoreInfo.SetCount300(sr.ReadUInt16()); + scoreInfo.SetCount100(sr.ReadUInt16()); + scoreInfo.SetCount50(sr.ReadUInt16()); + scoreInfo.SetCountGeki(sr.ReadUInt16()); + scoreInfo.SetCountKatu(sr.ReadUInt16()); + scoreInfo.SetCountMiss(sr.ReadUInt16()); scoreInfo.TotalScore = sr.ReadInt32(); scoreInfo.MaxCombo = sr.ReadUInt16(); diff --git a/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs index 73c647d6fa..9cc6ea2628 100644 --- a/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/Pages/ReplayDownloadButton.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Scoring; using osuTK; @@ -24,7 +23,7 @@ namespace osu.Game.Screens.Ranking.Pages if (State.Value == DownloadState.LocallyAvailable) return ReplayAvailability.Local; - if (Model.Value is APILegacyScoreInfo apiScore && apiScore.Replay) + if (!string.IsNullOrEmpty(Model.Value.Hash)) return ReplayAvailability.Online; return ReplayAvailability.NotAvailable; diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 3ef1fe5bc5..1b45a9d270 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -21,6 +21,9 @@ namespace osu.Game.Screens.Select.Leaderboards { public Action ScoreSelected; + [Resolved] + private RulesetStore rulesets { get; set; } + private BeatmapInfo beatmap; public BeatmapInfo Beatmap @@ -172,7 +175,7 @@ namespace osu.Game.Screens.Select.Leaderboards req.Success += r => { - scoresCallback?.Invoke(r.Scores); + scoresCallback?.Invoke(r.Scores.Select(s => s.CreateScoreInfo(rulesets))); TopScore = r.UserScore; }; diff --git a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs index a787eb5629..8e10734454 100644 --- a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -10,6 +11,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets; using osu.Game.Scoring; using osuTK; @@ -27,6 +29,9 @@ namespace osu.Game.Screens.Select.Leaderboards protected override bool StartHidden => true; + [Resolved] + private RulesetStore rulesets { get; set; } + public UserTopScoreContainer() { RelativeSizeAxes = Axes.X; @@ -77,9 +82,11 @@ namespace osu.Game.Screens.Select.Leaderboards if (newScore == null) return; - LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position, false) + var scoreInfo = newScore.Score.CreateScoreInfo(rulesets); + + LoadComponentAsync(new LeaderboardScore(scoreInfo, newScore.Position, false) { - Action = () => ScoreSelected?.Invoke(newScore.Score) + Action = () => ScoreSelected?.Invoke(scoreInfo) }, drawableScore => { scoreContainer.Child = drawableScore; From 1ce6a5ceb36bf0a9d412c8bca374eeddafff3fef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Dec 2019 15:38:57 +0900 Subject: [PATCH 095/110] Rename class --- .../Legacy/{LegacyScoreInfo.cs => ScoreInfoExtensions.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game/Scoring/Legacy/{LegacyScoreInfo.cs => ScoreInfoExtensions.cs} (98%) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs similarity index 98% rename from osu.Game/Scoring/Legacy/LegacyScoreInfo.cs rename to osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs index 2ee450b501..66b1acf591 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreInfo.cs +++ b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs @@ -5,7 +5,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring.Legacy { - public static class ScoreInfoLegacyExtensions + public static class ScoreInfoExtensions { public static int? GetCountGeki(this ScoreInfo scoreInfo) { From e2591f154ba7b8d821fb6186da44d17506c91a16 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Dec 2019 16:16:27 +0900 Subject: [PATCH 096/110] Only parse statistics when not null --- .../Requests/Responses/APILegacyScoreInfo.cs | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs index d231b8a5df..79ce04ed66 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScoreInfo.cs @@ -40,33 +40,36 @@ namespace osu.Game.Online.API.Requests.Responses Mods = mods, }; - foreach (var kvp in Statistics) + if (Statistics != null) { - switch (kvp.Key) + foreach (var kvp in Statistics) { - case @"count_geki": - scoreInfo.SetCountGeki(kvp.Value); - break; + switch (kvp.Key) + { + case @"count_geki": + scoreInfo.SetCountGeki(kvp.Value); + break; - case @"count_300": - scoreInfo.SetCount300(kvp.Value); - break; + case @"count_300": + scoreInfo.SetCount300(kvp.Value); + break; - case @"count_katu": - scoreInfo.SetCountKatu(kvp.Value); - break; + case @"count_katu": + scoreInfo.SetCountKatu(kvp.Value); + break; - case @"count_100": - scoreInfo.SetCount100(kvp.Value); - break; + case @"count_100": + scoreInfo.SetCount100(kvp.Value); + break; - case @"count_50": - scoreInfo.SetCount50(kvp.Value); - break; + case @"count_50": + scoreInfo.SetCount50(kvp.Value); + break; - case @"count_miss": - scoreInfo.SetCountMiss(kvp.Value); - break; + case @"count_miss": + scoreInfo.SetCountMiss(kvp.Value); + break; + } } } From a225a35f91cd8030234a72dd33b37d4585c180bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Dec 2019 16:18:36 +0900 Subject: [PATCH 097/110] Fix failing tests --- .../Visual/Online/TestSceneScoresContainer.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 3386cc41e7..b19f2dbf31 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -224,10 +224,13 @@ namespace osu.Game.Tests.Visual.Online foreach (var s in allScores.Scores) { - s.Statistics.Add("count_300", RNG.Next(2000)); - s.Statistics.Add("count_100", RNG.Next(2000)); - s.Statistics.Add("count_50", RNG.Next(2000)); - s.Statistics.Add("count_miss", RNG.Next(2000)); + s.Statistics = new Dictionary + { + { "count_300", RNG.Next(2000) }, + { "count_100", RNG.Next(2000) }, + { "count_50", RNG.Next(2000) }, + { "count_miss", RNG.Next(2000) } + }; } AddStep("Load all scores", () => From a42f9447e629f81ec61d2d05e52a1f3e6e97ac07 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 3 Dec 2019 20:07:22 +0800 Subject: [PATCH 098/110] Don't use Equals(object) on T?. --- CodeAnalysis/BannedSymbols.txt | 1 + osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- osu.Game/Screens/Select/FilterCriteria.cs | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index 5d86b99fd7..a92191a439 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -1,5 +1,6 @@ M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable or EqualityComparer.Default instead. M:System.Object.Equals(System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable or EqualityComparer.Default instead. M:System.ValueType.Equals(System.Object)~System.Boolean;Don't use object.Equals(Fallbacks to ValueType). Use IEquatable or EqualityComparer.Default instead. +M:System.Nullable`1.Equals(System.Object)~System.Boolean;Use == instead. T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. M:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText. diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 8161baba70..bd234675cb 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -280,7 +280,7 @@ namespace osu.Game.Rulesets.Objects if (other.ControlPoints == null && ControlPoints != null) return false; - return ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance.Equals(other.ExpectedDistance) && Type == other.Type; + return ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance == other.ExpectedDistance && Type == other.Type; } } } diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index c2cbac905e..7971506fa3 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -79,8 +79,8 @@ namespace osu.Game.Screens.Select public bool IsUpperInclusive; public bool Equals(OptionalRange other) - => Min.Equals(other.Min) - && Max.Equals(other.Max) + => EqualityComparer.Default.Equals(Min, other.Min) + && EqualityComparer.Default.Equals(Max, other.Max) && IsLowerInclusive.Equals(other.IsLowerInclusive) && IsUpperInclusive.Equals(other.IsUpperInclusive); } From 05cfef92f9d1827bacbaaaee21491c809518f2ef Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 3 Dec 2019 20:09:58 +0800 Subject: [PATCH 099/110] Don't compare spans with null. --- osu.Game/Rulesets/Objects/SliderPath.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index bd234675cb..ae6aad5b9c 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -273,14 +273,6 @@ namespace osu.Game.Rulesets.Objects return p0 + (p1 - p0) * (float)w; } - public bool Equals(SliderPath other) - { - if (ControlPoints == null && other.ControlPoints != null) - return false; - if (other.ControlPoints == null && ControlPoints != null) - return false; - - return ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance == other.ExpectedDistance && Type == other.Type; - } + public bool Equals(SliderPath other) => ControlPoints.SequenceEqual(other.ControlPoints) && ExpectedDistance == other.ExpectedDistance && Type == other.Type; } } From 5375af782051327afd704b60447e9af974ae8e44 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 3 Dec 2019 20:16:41 +0800 Subject: [PATCH 100/110] Remove other Equals(object) calls. --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 2 +- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 7351187ab9..39a0e6f6d4 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -25,6 +25,6 @@ namespace osu.Game.Beatmaps.ControlPoints /// Whether equivalent. public abstract bool EquivalentTo(ControlPoint other); - public bool Equals(ControlPoint other) => Time.Equals(other?.Time) && EquivalentTo(other); + public bool Equals(ControlPoint other) => Time == other?.Time && EquivalentTo(other); } } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index b144de35c5..ef86186e41 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -240,6 +240,6 @@ namespace osu.Game.Tests.Beatmaps set => Objects = value; } - public virtual bool Equals(ConvertMapping other) => StartTime.Equals(other?.StartTime); + public virtual bool Equals(ConvertMapping other) => StartTime == other?.StartTime; } } From 9ddfdab27a7d1a2ea9e050f8cf140e83497b086a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 3 Dec 2019 20:47:00 +0800 Subject: [PATCH 101/110] Remove meaningless Convert calls. --- .../Difficulty/ManiaPerformanceCalculator.cs | 12 ++++++------ .../Difficulty/OsuPerformanceCalculator.cs | 8 ++++---- .../Difficulty/TaikoPerformanceCalculator.cs | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index b99bddee96..3f7a2baedd 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -37,12 +37,12 @@ namespace osu.Game.Rulesets.Mania.Difficulty { mods = Score.Mods; scaledScore = Score.TotalScore; - countPerfect = Convert.ToInt32(Score.Statistics[HitResult.Perfect]); - countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); - countOk = Convert.ToInt32(Score.Statistics[HitResult.Ok]); - countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); + countPerfect = Score.Statistics[HitResult.Perfect]; + countGreat = Score.Statistics[HitResult.Great]; + countGood = Score.Statistics[HitResult.Good]; + countOk = Score.Statistics[HitResult.Ok]; + countMeh = Score.Statistics[HitResult.Meh]; + countMiss = Score.Statistics[HitResult.Miss]; if (mods.Any(m => !m.Ranked)) return 0; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 05c78cbc95..ce8ecf02ac 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -45,10 +45,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty mods = Score.Mods; accuracy = Score.Accuracy; scoreMaxCombo = Score.MaxCombo; - countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); - countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); + countGreat = Score.Statistics[HitResult.Great]; + countGood = Score.Statistics[HitResult.Good]; + countMeh = Score.Statistics[HitResult.Meh]; + countMiss = Score.Statistics[HitResult.Miss]; // Don't count scores made with supposedly unranked mods if (mods.Any(m => !m.Ranked)) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index c3638253e4..ead70c4b0a 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -31,10 +31,10 @@ namespace osu.Game.Rulesets.Taiko.Difficulty public override double Calculate(Dictionary categoryDifficulty = null) { mods = Score.Mods; - countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]); - countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]); - countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]); - countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]); + countGreat = Score.Statistics[HitResult.Great]; + countGood = Score.Statistics[HitResult.Good]; + countMeh =Score.Statistics[HitResult.Meh]; + countMiss = Score.Statistics[HitResult.Miss]; // Don't count scores made with supposedly unranked mods if (mods.Any(m => !m.Ranked)) From 46c9bdcf6289c32586f2c14f1bb192e4a9b974c9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 3 Dec 2019 20:49:41 +0800 Subject: [PATCH 102/110] Replace Convert.ChangeType with IConvertible. --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 7412224f6c..563dc2dad9 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -151,18 +151,18 @@ namespace osu.Game.Graphics.UserInterface private void updateTooltipText(T value) { if (CurrentNumber.IsInteger) - TooltipText = ((int)Convert.ChangeType(value, typeof(int))).ToString("N0"); + TooltipText = value.ToInt32(NumberFormatInfo.InvariantInfo).ToString("N0"); else { - double floatValue = (double)Convert.ChangeType(value, typeof(double)); - double floatMinValue = (double)Convert.ChangeType(CurrentNumber.MinValue, typeof(double)); - double floatMaxValue = (double)Convert.ChangeType(CurrentNumber.MaxValue, typeof(double)); + double floatValue = value.ToDouble(NumberFormatInfo.InvariantInfo); + double floatMinValue = CurrentNumber.MinValue.ToDouble(NumberFormatInfo.InvariantInfo); + double floatMaxValue = CurrentNumber.MaxValue.ToDouble(NumberFormatInfo.InvariantInfo); if (floatMaxValue == 1 && floatMinValue >= -1) TooltipText = floatValue.ToString("P0"); else { - var decimalPrecision = normalise((decimal)Convert.ChangeType(CurrentNumber.Precision, typeof(decimal)), max_decimal_digits); + var decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); // Find the number of significant digits (we could have less than 5 after normalize()) var significantDigits = findPrecision(decimalPrecision); From 6a58509f41b78d42fcbf8aed5b0d4c212aaa1996 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 3 Dec 2019 20:59:42 +0800 Subject: [PATCH 103/110] Fix format. --- .../Difficulty/TaikoPerformanceCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index ead70c4b0a..3a0fb64622 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty mods = Score.Mods; countGreat = Score.Statistics[HitResult.Great]; countGood = Score.Statistics[HitResult.Good]; - countMeh =Score.Statistics[HitResult.Meh]; + countMeh = Score.Statistics[HitResult.Meh]; countMiss = Score.Statistics[HitResult.Miss]; // Don't count scores made with supposedly unranked mods From 0734b52483061db156eda0f491b5ff0938178413 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Dec 2019 23:33:26 +0900 Subject: [PATCH 104/110] 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 997bd32bac..ff6d7396ee 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -54,6 +54,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3f056cacfb..d7a34c2b1c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index b231e924ef..d2feebbfc9 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 5b8ca8f84abce675b7021fa439ea108698ca0711 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 01:17:11 +0900 Subject: [PATCH 105/110] Remove test ignore rules --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 700c2561d5..803cab9325 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -113,7 +113,6 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] - [Ignore("Will be resolved with merge of https://github.com/ppy/osu/pull/6992")] public void TestExitTooSoon() { AddStep("seek before gameplay", () => Player.GameplayClockContainer.Seek(-5000)); @@ -216,7 +215,6 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] - [Ignore("Will be resolved with merge of https://github.com/ppy/osu/pull/6992")] public void TestRestartAfterResume() { AddStep("seek before gameplay", () => Player.GameplayClockContainer.Seek(-5000)); From 36224dca133b41a3a4b9d6028a81542add8268ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 3 Dec 2019 16:10:25 +0900 Subject: [PATCH 106/110] Fix multiplayer aggregate score inheriting from ScoreInfo --- .../Multiplayer/TestSceneMatchResults.cs | 4 +- .../API/Requests/GetRoomScoresRequest.cs | 2 +- .../Requests/Responses/APIRoomScoreInfo.cs | 17 ------- .../Responses/APIUserScoreAggregate.cs | 45 +++++++++++++++++++ .../Match/Components/MatchLeaderboard.cs | 8 ++-- .../Match/Components/MatchLeaderboardScore.cs | 11 +++-- .../Ranking/Pages/RoomLeaderboardPage.cs | 8 ++-- 7 files changed, 63 insertions(+), 32 deletions(-) delete mode 100644 osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIUserScoreAggregate.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchResults.cs index 7915a981dd..58e9240026 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchResults.cs @@ -83,7 +83,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard { - protected override APIRequest FetchScores(Action> scoresCallback) + protected override APIRequest FetchScores(Action> scoresCallback) { var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray(); @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual.Multiplayer return null; } - private APIRoomScoreInfo createRoomScore(int id) => new APIRoomScoreInfo + private APIUserScoreAggregate createRoomScore(int id) => new APIUserScoreAggregate { User = new User { Id = id, Username = $"User {id}" }, Accuracy = 0.98, diff --git a/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs b/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs index 993e49dab2..eb53369d18 100644 --- a/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs @@ -6,7 +6,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetRoomScoresRequest : APIRequest> + public class GetRoomScoresRequest : APIRequest> { private readonly int roomId; diff --git a/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs deleted file mode 100644 index 33467b59b2..0000000000 --- a/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs +++ /dev/null @@ -1,17 +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 Newtonsoft.Json; -using osu.Game.Scoring; - -namespace osu.Game.Online.API.Requests.Responses -{ - public class APIRoomScoreInfo : ScoreInfo - { - [JsonProperty("attempts")] - public int TotalAttempts { get; set; } - - [JsonProperty("completed")] - public int CompletedBeatmaps { get; set; } - } -} diff --git a/osu.Game/Online/API/Requests/Responses/APIUserScoreAggregate.cs b/osu.Game/Online/API/Requests/Responses/APIUserScoreAggregate.cs new file mode 100644 index 0000000000..0bba6a93bd --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIUserScoreAggregate.cs @@ -0,0 +1,45 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIUserScoreAggregate + { + [JsonProperty("attempts")] + public int TotalAttempts { get; set; } + + [JsonProperty("completed")] + public int CompletedBeatmaps { get; set; } + + [JsonProperty("accuracy")] + public double Accuracy { get; set; } + + [JsonProperty(@"pp")] + public double? PP { get; set; } + + [JsonProperty(@"room_id")] + public int RoomID { get; set; } + + [JsonProperty("total_score")] + public long TotalScore { get; set; } + + [JsonProperty(@"user_id")] + public long UserID { get; set; } + + [JsonProperty("user")] + public User User { get; set; } + + public ScoreInfo CreateScoreInfo() => + new ScoreInfo + { + Accuracy = Accuracy, + PP = PP, + TotalScore = TotalScore, + User = User, + }; + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index ae27e53813..571bbde716 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -13,9 +13,9 @@ using osu.Game.Online.Multiplayer; namespace osu.Game.Screens.Multi.Match.Components { - public class MatchLeaderboard : Leaderboard + public class MatchLeaderboard : Leaderboard { - public Action> ScoresLoaded; + public Action> ScoresLoaded; [Resolved(typeof(Room), nameof(Room.RoomID))] private Bindable roomId { get; set; } @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Multi.Match.Components protected override bool IsOnlineScope => true; - protected override APIRequest FetchScores(Action> scoresCallback) + protected override APIRequest FetchScores(Action> scoresCallback) { if (roomId.Value == null) return null; @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Multi.Match.Components return req; } - protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) => new MatchLeaderboardScore(model, index); + protected override LeaderboardScore CreateDrawableScore(APIUserScoreAggregate model, int index) => new MatchLeaderboardScore(model, index); } public enum MatchLeaderboardScope diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs index 92074abe4b..aa92451c77 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs @@ -12,9 +12,12 @@ namespace osu.Game.Screens.Multi.Match.Components { public class MatchLeaderboardScore : LeaderboardScore { - public MatchLeaderboardScore(APIRoomScoreInfo score, int rank) - : base(score, rank) + private readonly APIUserScoreAggregate score; + + public MatchLeaderboardScore(APIUserScoreAggregate score, int rank) + : base(score.CreateScoreInfo(), rank) { + this.score = score; } [BackgroundDependencyLoader] @@ -26,8 +29,8 @@ namespace osu.Game.Screens.Multi.Match.Components protected override IEnumerable GetStatistics(ScoreInfo model) => new[] { new LeaderboardScoreStatistic(FontAwesome.Solid.Crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)), - new LeaderboardScoreStatistic(FontAwesome.Solid.Sync, "Total Attempts", ((APIRoomScoreInfo)model).TotalAttempts.ToString()), - new LeaderboardScoreStatistic(FontAwesome.Solid.Check, "Completed Beatmaps", ((APIRoomScoreInfo)model).CompletedBeatmaps.ToString()), + new LeaderboardScoreStatistic(FontAwesome.Solid.Sync, "Total Attempts", score.TotalAttempts.ToString()), + new LeaderboardScoreStatistic(FontAwesome.Solid.Check, "Completed Beatmaps", score.CompletedBeatmaps.ToString()), }; } } diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index e389611caf..ff5471cf4a 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs @@ -74,7 +74,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages leaderboard.ScoresLoaded = scoresLoaded; } - private void scoresLoaded(IEnumerable scores) + private void scoresLoaded(IEnumerable scores) { void gray(SpriteText s) => s.Colour = colours.GrayC; @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages rankText.AddText(name + "\n", white); rankText.AddText("You are placed ", gray); - int index = scores.IndexOf(new APIRoomScoreInfo { User = Score.User }, new FuncEqualityComparer((s1, s2) => s1.User.Id.Equals(s2.User.Id))); + int index = scores.IndexOf(new APIUserScoreAggregate { User = Score.User }, new FuncEqualityComparer((s1, s2) => s1.User.Id.Equals(s2.User.Id))); rankText.AddText($"#{index + 1} ", s => { @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages { protected override bool FadeTop => true; - protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) + protected override LeaderboardScore CreateDrawableScore(APIUserScoreAggregate model, int index) => new ResultsMatchLeaderboardScore(model, index); protected override FillFlowContainer CreateScoreFlow() @@ -120,7 +120,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages private class ResultsMatchLeaderboardScore : MatchLeaderboardScore { - public ResultsMatchLeaderboardScore(APIRoomScoreInfo score, int rank) + public ResultsMatchLeaderboardScore(APIUserScoreAggregate score, int rank) : base(score, rank) { } From 48287459a0aa6136e711eb7bc07df187338a7876 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 01:52:22 +0900 Subject: [PATCH 107/110] Optimise filters to avoid property retrieval Also reduces number of instantiations of SearchableTerms array in the case of multiple criteria terms. --- .../Select/Carousel/CarouselBeatmap.cs | 32 ++++++++++--------- osu.Game/Screens/Select/FilterCriteria.cs | 6 +++- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index afd6211dec..68a6ad8845 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Screens.Select.Filter; @@ -29,28 +30,29 @@ namespace osu.Game.Screens.Select.Carousel Beatmap.RulesetID == criteria.Ruleset.ID || (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); - match &= criteria.StarDifficulty.IsInRange(Beatmap.StarDifficulty); - match &= criteria.ApproachRate.IsInRange(Beatmap.BaseDifficulty.ApproachRate); - match &= criteria.DrainRate.IsInRange(Beatmap.BaseDifficulty.DrainRate); - match &= criteria.CircleSize.IsInRange(Beatmap.BaseDifficulty.CircleSize); - match &= criteria.Length.IsInRange(Beatmap.Length); - match &= criteria.BPM.IsInRange(Beatmap.BPM); + match &= !criteria.StarDifficulty.HasFilter || criteria.StarDifficulty.IsInRange(Beatmap.StarDifficulty); + match &= !criteria.ApproachRate.HasFilter || criteria.ApproachRate.IsInRange(Beatmap.BaseDifficulty.ApproachRate); + match &= !criteria.DrainRate.HasFilter || criteria.DrainRate.IsInRange(Beatmap.BaseDifficulty.DrainRate); + match &= !criteria.CircleSize.HasFilter || criteria.CircleSize.IsInRange(Beatmap.BaseDifficulty.CircleSize); + match &= !criteria.Length.HasFilter || criteria.Length.IsInRange(Beatmap.Length); + match &= !criteria.BPM.HasFilter || criteria.BPM.IsInRange(Beatmap.BPM); - match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); - match &= criteria.OnlineStatus.IsInRange(Beatmap.Status); + match &= !criteria.BeatDivisor.HasFilter || criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); + match &= !criteria.OnlineStatus.HasFilter || criteria.OnlineStatus.IsInRange(Beatmap.Status); - match &= criteria.Creator.Matches(Beatmap.Metadata.AuthorString); - match &= criteria.Artist.Matches(Beatmap.Metadata.Artist) || + match &= !criteria.Creator.HasFilter || criteria.Creator.Matches(Beatmap.Metadata.AuthorString); + match &= !criteria.Artist.HasFilter || criteria.Artist.Matches(Beatmap.Metadata.Artist) || criteria.Artist.Matches(Beatmap.Metadata.ArtistUnicode); if (match) { + var terms = new List(); + + terms.AddRange(Beatmap.Metadata.SearchableTerms); + terms.Add(Beatmap.Version); + foreach (var criteriaTerm in criteria.SearchTerms) - { - match &= - Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) || - Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; - } + match &= terms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0); } Filtered.Value = !match; diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 7971506fa3..abcb1f2171 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -46,6 +46,8 @@ namespace osu.Game.Screens.Select public struct OptionalRange : IEquatable> where T : struct, IComparable { + public bool HasFilter => Max != null || Min != null; + public bool IsInRange(T value) { if (Min != null) @@ -87,9 +89,11 @@ namespace osu.Game.Screens.Select public struct OptionalTextFilter : IEquatable { + public bool HasFilter => !string.IsNullOrEmpty(SearchTerm); + public bool Matches(string value) { - if (string.IsNullOrEmpty(SearchTerm)) + if (!HasFilter) return true; // search term is guaranteed to be non-empty, so if the string we're comparing is empty, it's not matching From 0e9787146115d728eff1b04f3e79d6b6724955ed Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Thu, 5 Dec 2019 14:53:01 +0700 Subject: [PATCH 108/110] Change colour if difficulty is ExpertPlus --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 8014631eca..025b7e11fd 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -168,7 +168,7 @@ namespace osu.Game.Beatmaps.Drawables difficultyName.Text = beatmap.Version; starRating.Text = $"{beatmap.StarDifficulty:0.##}"; - difficultyFlow.Colour = colours.ForDifficultyRating(beatmap.DifficultyRating); + difficultyFlow.Colour = beatmap.DifficultyRating == DifficultyRating.ExpertPlus ? colours.Gray9 : colours.ForDifficultyRating(beatmap.DifficultyRating); return true; } From 2419077c0763612f0cb05f8e503e7208373dfd47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 18:31:13 +0900 Subject: [PATCH 109/110] 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 ff6d7396ee..301c615ce4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -54,6 +54,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d7a34c2b1c..086359ee41 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index d2feebbfc9..0eb8d98a63 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 8be6abf6076224b1a3a5a7aa1490793911ab7426 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Fri, 6 Dec 2019 10:07:16 +0700 Subject: [PATCH 110/110] Add param to let function return lighter colour for some diff --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 +- osu.Game/Graphics/OsuColour.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 025b7e11fd..7bd40af512 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -168,7 +168,7 @@ namespace osu.Game.Beatmaps.Drawables difficultyName.Text = beatmap.Version; starRating.Text = $"{beatmap.StarDifficulty:0.##}"; - difficultyFlow.Colour = beatmap.DifficultyRating == DifficultyRating.ExpertPlus ? colours.Gray9 : colours.ForDifficultyRating(beatmap.DifficultyRating); + difficultyFlow.Colour = colours.ForDifficultyRating(beatmap.DifficultyRating, true); return true; } diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index af66f57f14..2dc12b3e67 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -38,7 +38,7 @@ namespace osu.Game.Graphics } } - public Color4 ForDifficultyRating(DifficultyRating difficulty) + public Color4 ForDifficultyRating(DifficultyRating difficulty, bool useLighterColour = false) { switch (difficulty) { @@ -56,10 +56,10 @@ namespace osu.Game.Graphics return Pink; case DifficultyRating.Expert: - return Purple; + return useLighterColour ? PurpleLight : Purple; case DifficultyRating.ExpertPlus: - return Gray0; + return useLighterColour ? Gray9 : Gray0; } }